Refactor browser extension i18n to use single file structure (#1006)

This commit is contained in:
Leendert de Borst
2025-07-15 12:56:50 +02:00
committed by Leendert de Borst
parent 32e6ca597a
commit 25ff5bf994
69 changed files with 2164 additions and 1787 deletions

View File

@@ -2,7 +2,7 @@ import { type Browser } from '@wxt-dev/browser';
import { sendMessage } from 'webext-bridge/background';
import { PasswordGenerator } from '@/utils/dist/shared/password-generator';
import { tc } from '@/utils/i18n/StandaloneI18n';
import { t } from '@/utils/i18n/StandaloneI18n';
import { browser } from "#imports";
@@ -21,7 +21,7 @@ export async function setupContextMenus() : Promise<void> {
browser.contextMenus.create({
id: "aliasvault-activate-form",
parentId: "aliasvault-root",
title: await tc('autofillWithAliasVault'),
title: await t('content.autofillWithAliasVault'),
contexts: ["editable"],
});
@@ -37,7 +37,7 @@ export async function setupContextMenus() : Promise<void> {
browser.contextMenus.create({
id: "aliasvault-generate-password",
parentId: "aliasvault-root",
title: await tc('generateRandomPassword'),
title: await t('content.generateRandomPassword'),
contexts: ["all"]
});
@@ -83,7 +83,7 @@ export function handleContextMenuClick(info: Browser.contextMenus.OnClickData, t
*/
async function copyPasswordToClipboard(generatedPassword: string) : Promise<void> {
navigator.clipboard.writeText(generatedPassword).then(async () => {
showToast(await tc('passwordCopiedToClipboard'));
showToast(await t('content.passwordCopiedToClipboard'));
});
/**

View File

@@ -3,7 +3,7 @@ import { storage } from 'wxt/utils/storage';
import type { Vault, VaultResponse, VaultPostResponse } from '@/utils/dist/shared/models/webapi';
import { EncryptionUtility } from '@/utils/EncryptionUtility';
import { tc } from '@/utils/i18n/StandaloneI18n';
import { t } from '@/utils/i18n/StandaloneI18n';
import { SqliteClient } from '@/utils/SqliteClient';
import { BoolResponse as messageBoolResponse } from '@/utils/types/messaging/BoolResponse';
import { CredentialsResponse as messageCredentialsResponse } from '@/utils/types/messaging/CredentialsResponse';
@@ -59,7 +59,7 @@ export async function handleCheckAuthStatus() : Promise<{ isLoggedIn: boolean, i
isLoggedIn,
isVaultLocked,
hasPendingMigrations: false,
error: error instanceof Error ? error.message : await tc('errors.unknownError', 'common')
error: error instanceof Error ? error.message : await t('common.errors.unknownError')
};
}
}
@@ -101,7 +101,7 @@ export async function handleStoreVault(
return { success: true };
} catch (error) {
console.error('Failed to store vault:', error);
return { success: false, error: await tc('errors.failedToStoreVault', 'common') };
return { success: false, error: await t('common.errors.failedToStoreVault') };
}
}
@@ -114,7 +114,7 @@ export async function handleSyncVault(
const statusResponse = await webApi.getStatus();
const statusError = webApi.validateStatusResponse(statusResponse);
if (statusError !== null) {
return { success: false, error: await tc(statusError) };
return { success: false, error: await t('common.errors.' + statusError) };
}
const vaultRevisionNumber = await storage.getItem('session:vaultRevisionNumber') as number;
@@ -148,7 +148,7 @@ export async function handleGetVault(
if (!encryptedVault) {
console.error('Vault not available');
return { success: false, error: await tc('errors.vaultNotAvailable', 'common') };
return { success: false, error: await t('common.errors.vaultNotAvailable') };
}
const decryptedVault = await EncryptionUtility.symmetricDecrypt(
@@ -165,7 +165,7 @@ export async function handleGetVault(
};
} catch (error) {
console.error('Failed to get vault:', error);
return { success: false, error: await tc('errors.failedToGetVault', 'common') };
return { success: false, error: await t('common.errors.failedToGetVault') };
}
}
@@ -193,7 +193,7 @@ export async function handleGetCredentials(
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!derivedKey) {
return { success: false, error: await tc('errors.vaultIsLocked', 'common') };
return { success: false, error: await t('common.errors.vaultIsLocked') };
}
try {
@@ -202,7 +202,7 @@ export async function handleGetCredentials(
return { success: true, credentials: credentials };
} catch (error) {
console.error('Error getting credentials:', error);
return { success: false, error: await tc('errors.failedToGetCredentials', 'common') };
return { success: false, error: await t('common.errors.failedToGetCredentials') };
}
}
@@ -215,7 +215,7 @@ export async function handleCreateIdentity(
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!derivedKey) {
return { success: false, error: await tc('errors.vaultIsLocked', 'common') };
return { success: false, error: await t('common.errors.vaultIsLocked') };
}
try {
@@ -230,7 +230,7 @@ export async function handleCreateIdentity(
return { success: true };
} catch (error) {
console.error('Failed to create identity:', error);
return { success: false, error: await tc('errors.failedToCreateIdentity', 'common') };
return { success: false, error: await t('common.errors.failedToCreateIdentity') };
}
}
@@ -272,7 +272,7 @@ export function handleGetDefaultEmailDomain(): Promise<stringResponse> {
return { success: true, value: defaultEmailDomain ?? undefined };
} catch (error) {
console.error('Error getting default email domain:', error);
return { success: false, error: await tc('errors.failedToGetDefaultEmailDomain', 'common') };
return { success: false, error: await t('common.errors.failedToGetDefaultEmailDomain') };
}
})();
}
@@ -296,7 +296,7 @@ export async function handleGetDefaultIdentitySettings(
};
} catch (error) {
console.error('Error getting default identity settings:', error);
return { success: false, error: await tc('errors.failedToGetDefaultIdentitySettings', 'common') };
return { success: false, error: await t('common.errors.failedToGetDefaultIdentitySettings') };
}
}
@@ -312,7 +312,7 @@ export async function handleGetPasswordSettings(
return { success: true, settings: passwordSettings };
} catch (error) {
console.error('Error getting password settings:', error);
return { success: false, error: await tc('errors.failedToGetPasswordSettings', 'common') };
return { success: false, error: await t('common.errors.failedToGetPasswordSettings') };
}
}
@@ -343,7 +343,7 @@ export async function handleUploadVault(
return { success: true, status: response.status, newRevisionNumber: response.newRevisionNumber };
} catch (error) {
console.error('Failed to upload vault:', error);
return { success: false, error: await tc('errors.failedToUploadVault', 'common') };
return { success: false, error: await t('common.errors.failedToUploadVault') };
}
}
@@ -354,7 +354,7 @@ export async function handleUploadVault(
export async function handlePersistFormValues(data: any): Promise<void> {
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!derivedKey) {
throw new Error(await tc('errors.noDerivedKeyAvailable', 'common'));
throw new Error(await t('common.errors.noDerivedKeyAvailable'));
}
// Always stringify the data properly
@@ -442,7 +442,7 @@ async function uploadNewVaultToServer(sqliteClient: SqliteClient) : Promise<Vaul
if (response.status === 0) {
await storage.setItem('session:vaultRevisionNumber', response.newRevisionNumber);
} else {
throw new Error(await tc('errors.failedToUploadVaultToServer', 'common'));
throw new Error(await t('common.errors.failedToUploadVaultToServer'));
}
return response;
@@ -455,7 +455,7 @@ async function createVaultSqliteClient() : Promise<SqliteClient> {
const encryptedVault = await storage.getItem('session:encryptedVault') as string;
const derivedKey = await storage.getItem('session:derivedKey') as string;
if (!encryptedVault || !derivedKey) {
throw new Error(await tc('errors.noVaultOrDerivedKeyFound', 'common'));
throw new Error(await t('common.errors.noVaultOrDerivedKeyFound'));
}
// Decrypt the vault.

View File

@@ -5,11 +5,11 @@ import { injectIcon, popupDebounceTimeHasPassed, validateInputField } from '@/en
import { isAutoShowPopupEnabled, openAutofillPopup, removeExistingPopup, createUpgradeRequiredPopup } from '@/entrypoints/contentScript/Popup';
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { t } from '@/utils/i18n/StandaloneI18n';
import { BoolResponse as messageBoolResponse } from '@/utils/types/messaging/BoolResponse';
import { defineContentScript } from '#imports';
import { createShadowRootUi } from '#imports';
import { tc } from '@/utils/i18n/StandaloneI18n';
export default defineContentScript({
matches: ['<all_urls>'],
@@ -160,7 +160,7 @@ export default defineContentScript({
if (authStatus.hasPendingMigrations) {
// Show upgrade required popup
await createUpgradeRequiredPopup(inputElement, container, await tc('vaultUpgradeRequired'));
await createUpgradeRequiredPopup(inputElement, container, await t('content.vaultUpgradeRequired'));
return;
}

View File

@@ -8,7 +8,7 @@ import { CreateIdentityGenerator } from '@/utils/dist/shared/identity-generator'
import type { Credential } from '@/utils/dist/shared/models/vault';
import { CreatePasswordGenerator, PasswordGenerator } from '@/utils/dist/shared/password-generator';
import { FormDetector } from '@/utils/formDetector/FormDetector';
import { tc } from '@/utils/i18n/StandaloneI18n';
import { t } from '@/utils/i18n/StandaloneI18n';
import { SqliteClient } from '@/utils/SqliteClient';
import { CredentialsResponse } from '@/utils/types/messaging/CredentialsResponse';
import { IdentitySettingsResponse } from '@/utils/types/messaging/IdentitySettingsResponse';
@@ -157,13 +157,13 @@ export function removeExistingPopup(container: HTMLElement) : void {
*/
export async function createAutofillPopup(input: HTMLInputElement, credentials: Credential[] | undefined, rootContainer: HTMLElement) : Promise<void> {
// Get all translations first
const newText = await tc('new');
const searchPlaceholder = await tc('searchVault');
const hideFor1HourText = await tc('hideFor1Hour');
const hidePermanentlyText = await tc('hidePermanently');
const noMatchesText = await tc('noMatchesFound');
const creatingText = await tc('creatingNewAlias');
const failedText = await tc('failedToCreateIdentity');
const newText = await t('content.new');
const searchPlaceholder = await t('content.searchVault');
const hideFor1HourText = await t('content.hideFor1Hour');
const hidePermanentlyText = await t('content.hidePermanently');
const noMatchesText = await t('content.noMatchesFound');
const creatingText = await t('content.creatingNewAlias');
const failedText = await t('content.failedToCreateIdentity');
// Disable browser's native autocomplete to avoid conflicts with AliasVault's autocomplete.
input.setAttribute('autocomplete', 'false');
@@ -471,7 +471,7 @@ export async function createVaultLockedPopup(input: HTMLInputElement, rootContai
// Add message
const messageElement = document.createElement('div');
messageElement.className = 'av-vault-locked-message';
messageElement.textContent = await tc('vaultLocked');
messageElement.textContent = await t('content.vaultLocked');
container.appendChild(messageElement);
// Add unlock button with SVG icon
@@ -771,10 +771,10 @@ export async function createAliasCreationPopup(suggestedNames: string[], rootCon
<circle cx="16" cy="16" r="1"/>
</svg>
`;
const randomIdentitySubtext = await tc('randomIdentityDescription');
const randomIdentityTitle = await tc('createRandomAlias');
const randomIdentityTitleDropdown = await tc('randomAlias');
const randomIdentitySubtextDropdown = await tc('randomIdentityDescriptionDropdown');
const randomIdentitySubtext = await t('content.randomIdentityDescription');
const randomIdentityTitle = await t('content.createRandomAlias');
const randomIdentityTitleDropdown = await t('content.randomAlias');
const randomIdentitySubtextDropdown = await t('content.randomIdentityDescriptionDropdown');
const manualUsernamePasswordIcon = `
<svg class="av-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
@@ -782,24 +782,24 @@ export async function createAliasCreationPopup(suggestedNames: string[], rootCon
<path d="M5.5 20a6.5 6.5 0 0 1 13 0"/>
</svg>
`;
const manualUsernamePasswordSubtext = await tc('manualCredentialDescription');
const manualUsernamePasswordTitle = await tc('createUsernamePassword');
const manualUsernamePasswordTitleDropdown = await tc('usernamePassword');
const manualUsernamePasswordSubtextDropdown = await tc('manualCredentialDescriptionDropdown');
const manualUsernamePasswordSubtext = await t('content.manualCredentialDescription');
const manualUsernamePasswordTitle = await t('content.createUsernamePassword');
const manualUsernamePasswordTitleDropdown = await t('content.usernamePassword');
const manualUsernamePasswordSubtextDropdown = await t('content.manualCredentialDescriptionDropdown');
// Get all translated strings first
const serviceNameText = await tc('serviceName');
const enterServiceNameText = await tc('enterServiceName');
const cancelText = await tc('cancel');
const createAndSaveAliasText = await tc('createAndSaveAlias');
const emailText = await tc('email');
const enterEmailAddressText = await tc('enterEmailAddress');
const usernameText = await tc('username');
const enterUsernameText = await tc('enterUsername');
const generatedPasswordText = await tc('generatedPassword');
const generateNewPasswordText = await tc('generateNewPassword');
const togglePasswordVisibilityText = await tc('togglePasswordVisibility');
const createAndSaveCredentialText = await tc('createAndSaveCredential');
const serviceNameText = await t('content.serviceName');
const enterServiceNameText = await t('content.enterServiceName');
const cancelText = await t('content.cancel');
const createAndSaveAliasText = await t('content.createAndSaveAlias');
const emailText = await t('content.email');
const enterEmailAddressText = await t('content.enterEmailAddress');
const usernameText = await t('content.username');
const enterUsernameText = await t('content.enterUsername');
const generatedPasswordText = await t('content.generatedPassword');
const generateNewPasswordText = await t('content.generateNewPassword');
const togglePasswordVisibilityText = await t('content.togglePasswordVisibility');
const createAndSaveCredentialText = await t('content.createAndSaveCredential');
// Create the main content
popup.innerHTML = `
@@ -1163,14 +1163,14 @@ export async function createAliasCreationPopup(suggestedNames: string[], rootCon
if (!emailLabel.querySelector('.av-create-popup-error-text')) {
const emailError = document.createElement('span');
emailError.className = 'av-create-popup-error-text';
emailError.textContent = await tc('enterEmailAndOrUsername');
emailError.textContent = await t('content.enterEmailAndOrUsername');
emailLabel.appendChild(emailError);
}
if (!usernameLabel.querySelector('.av-create-popup-error-text')) {
const usernameError = document.createElement('span');
usernameError.className = 'av-create-popup-error-text';
usernameError.textContent = await tc('enterEmailAndOrUsername');
usernameError.textContent = await t('content.enterEmailAndOrUsername');
usernameLabel.appendChild(usernameError);
}
@@ -1525,7 +1525,7 @@ export async function createUpgradeRequiredPopup(input: HTMLInputElement, rootCo
// Add upgrade button with SVG icon
const button = document.createElement('button');
button.title = await tc('openAliasVaultToUpgrade');
button.title = await t('content.openAliasVaultToUpgrade');
button.className = 'av-upgrade-required-button';
button.innerHTML = `
<svg class="av-icon-upgrade" viewBox="0 0 24 24">
@@ -1540,7 +1540,7 @@ export async function createUpgradeRequiredPopup(input: HTMLInputElement, rootCo
// Add close button as a separate element positioned to the right
const closeButton = document.createElement('button');
closeButton.className = 'av-button av-button-close av-upgrade-required-close';
closeButton.title = await tc('dismissPopup');
closeButton.title = await t('content.dismissPopup');
closeButton.innerHTML = `
<svg class="av-icon" viewBox="0 0 24 24">
<line x1="18" y1="6" x2="6" y2="18"></line>

View File

@@ -42,7 +42,7 @@ type RouteConfig = {
* App component.
*/
const App: React.FC = () => {
const { t } = useTranslation(['common', 'credentials', 'emails', 'settings']);
const { t } = useTranslation();
const authContext = useAuth();
const { isInitialLoading } = useLoading();
const [isLoading, setIsLoading] = useMinDurationLoading(true, 150);
@@ -57,13 +57,13 @@ const App: React.FC = () => {
{ path: '/unlock', element: <Unlock />, showBackButton: false },
{ path: '/unlock-success', element: <UnlockSuccess />, showBackButton: false },
{ path: '/upgrade', element: <Upgrade />, showBackButton: false },
{ path: '/auth-settings', element: <AuthSettings />, showBackButton: true, title: t('settings:title') },
{ path: '/auth-settings', element: <AuthSettings />, showBackButton: true, title: t('settings.title') },
{ path: '/credentials', element: <CredentialsList />, showBackButton: false },
{ path: '/credentials/add', element: <CredentialAddEdit />, showBackButton: true, title: t('credentials:addCredential') },
{ path: '/credentials/:id', element: <CredentialDetails />, showBackButton: true, title: t('credentials:credentialDetails') },
{ path: '/credentials/:id/edit', element: <CredentialAddEdit />, showBackButton: true, title: t('credentials:editCredential') },
{ path: '/credentials/add', element: <CredentialAddEdit />, showBackButton: true, title: t('credentials.addCredential') },
{ path: '/credentials/:id', element: <CredentialDetails />, showBackButton: true, title: t('credentials.credentialDetails') },
{ path: '/credentials/:id/edit', element: <CredentialAddEdit />, showBackButton: true, title: t('credentials.editCredential') },
{ path: '/emails', element: <EmailsList />, showBackButton: false },
{ path: '/emails/:id', element: <EmailDetails />, showBackButton: true, title: t('emails:title') },
{ path: '/emails/:id', element: <EmailDetails />, showBackButton: true, title: t('emails.title') },
{ path: '/settings', element: <Settings />, showBackButton: false },
{ path: '/logout', element: <Logout />, showBackButton: false },
];

View File

@@ -14,7 +14,7 @@ type AliasBlockProps = {
* Render the alias block.
*/
const AliasBlock: React.FC<AliasBlockProps> = ({ credential }) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const hasFirstName = Boolean(credential.Alias?.FirstName?.trim());
const hasLastName = Boolean(credential.Alias?.LastName?.trim());
const hasNickName = Boolean(credential.Alias?.NickName?.trim());
@@ -26,39 +26,39 @@ const AliasBlock: React.FC<AliasBlockProps> = ({ credential }) => {
return (
<div className="space-y-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('alias')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('common.alias')}</h2>
{(hasFirstName || hasLastName) && (
<FormInputCopyToClipboard
id="fullName"
label={t('fullName')}
label={t('common.fullName')}
value={[credential.Alias?.FirstName, credential.Alias?.LastName].filter(Boolean).join(' ')}
/>
)}
{hasFirstName && (
<FormInputCopyToClipboard
id="firstName"
label={t('firstName')}
label={t('common.firstName')}
value={credential.Alias?.FirstName ?? ''}
/>
)}
{hasLastName && (
<FormInputCopyToClipboard
id="lastName"
label={t('lastName')}
label={t('common.lastName')}
value={credential.Alias?.LastName ?? ''}
/>
)}
{hasBirthDate && (
<FormInputCopyToClipboard
id="birthDate"
label={t('birthDate')}
label={t('common.birthDate')}
value={IdentityHelperUtils.normalizeBirthDateForDisplay(credential.Alias?.BirthDate)}
/>
)}
{hasNickName && (
<FormInputCopyToClipboard
id="nickName"
label={t('nickname')}
label={t('common.nickname')}
value={credential.Alias?.NickName ?? ''}
/>
)}

View File

@@ -13,7 +13,7 @@ type LoginCredentialsBlockProps = {
* Render the login credentials block.
*/
const LoginCredentialsBlock: React.FC<LoginCredentialsBlockProps> = ({ credential }) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const email = credential.Alias?.Email?.trim();
const username = credential.Username?.trim();
const password = credential.Password?.trim();
@@ -24,25 +24,25 @@ const LoginCredentialsBlock: React.FC<LoginCredentialsBlockProps> = ({ credentia
return (
<div className="space-y-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('loginCredentials')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('common.loginCredentials')}</h2>
{email && (
<FormInputCopyToClipboard
id="email"
label={t('email')}
label={t('common.email')}
value={email}
/>
)}
{username && (
<FormInputCopyToClipboard
id="username"
label={t('username')}
label={t('common.username')}
value={username}
/>
)}
{password && (
<FormInputCopyToClipboard
id="password"
label={t('password')}
label={t('common.password')}
value={password}
type="password"
/>

View File

@@ -21,7 +21,7 @@ const convertUrlsToLinks = (text: string): string => {
* Render the notes block.
*/
const NotesBlock: React.FC<NotesBlockProps> = ({ notes }) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
if (!notes) {
return null;
}
@@ -30,7 +30,7 @@ const NotesBlock: React.FC<NotesBlockProps> = ({ notes }) => {
return (
<div>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('notes')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-2">{t('common.notes')}</h2>
<div className="p-4 bg-gray-50 rounded-lg dark:bg-gray-700">
<p
className="text-gray-900 dark:text-gray-100 whitespace-pre-wrap"

View File

@@ -14,7 +14,7 @@ type TotpBlockProps = {
* This component shows TOTP codes for a credential.
*/
const TotpBlock: React.FC<TotpBlockProps> = ({ credentialId }) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const [totpCodes, setTotpCodes] = useState<TotpCode[]>([]);
const [loading, setLoading] = useState(true);
const [currentCodes, setCurrentCodes] = useState<Record<string, string>>({});
@@ -140,8 +140,8 @@ const TotpBlock: React.FC<TotpBlockProps> = ({ credentialId }) => {
if (loading) {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">{t('twoFactorAuthentication')}</h2>
{t('loadingTotpCodes')}
<h2 className="text-lg font-semibold text-gray-900 dark:text-white mb-2">{t('common.twoFactorAuthentication')}</h2>
{t('common.loadingTotpCodes')}
</div>
);
}
@@ -153,7 +153,7 @@ const TotpBlock: React.FC<TotpBlockProps> = ({ credentialId }) => {
return (
<div className="mb-4">
<div className="space-y-2">
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">{t('twoFactorAuthentication')}</h2>
<h2 className="text-lg font-semibold text-gray-900 dark:text-white">{t('common.twoFactorAuthentication')}</h2>
<div className="grid grid-cols-1 gap-2">
{totpCodes.map(totpCode => (
<button
@@ -173,7 +173,7 @@ const TotpBlock: React.FC<TotpBlockProps> = ({ credentialId }) => {
</span>
<div className="text-xs">
{copiedId === totpCode.Id ? (
<span className="text-green-600 dark:text-green-400">{t('copied')}</span>
<span className="text-green-600 dark:text-green-400">{t('common.copied')}</span>
) : (
<span className="text-gray-500 dark:text-gray-400">{getRemainingSeconds()}s</span>
)}

View File

@@ -19,7 +19,7 @@ type EmailPreviewProps = {
* This component shows a preview of the latest emails in the inbox.
*/
export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
const { t } = useTranslation(['common', 'emails']);
const { t } = useTranslation();
const [emails, setEmails] = useState<MailboxEmail[]>([]);
const [loading, setLoading] = useState(true);
const [lastEmailId, setLastEmailId] = useState<number>(0);
@@ -76,7 +76,7 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
});
if (!response.ok) {
setError(t('emails:errors.emailLoadError'));
setError(t('emails.errors.emailLoadError'));
return;
}
@@ -125,17 +125,17 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
} catch {
// Try to parse as error response instead
const apiErrorResponse = response as ApiErrorResponse;
setError(t('emails:apiErrors.' + apiErrorResponse?.code));
setError(t('emails.apiErrors.' + apiErrorResponse?.code));
return;
}
} catch {
setError(t('emails:errors.emailLoadError'));
setError(t('emails.errors.emailLoadError'));
return;
}
}
} catch (err) {
console.error('Error loading emails:', err);
setError(t('emails:errors.emailUnexpectedError'));
setError(t('emails.errors.emailUnexpectedError'));
}
setLoading(false);
};
@@ -155,7 +155,7 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common:recentEmails')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common.recentEmails')}</h2>
</div>
<div className="p-3 bg-red-50 dark:bg-red-900/30 border border-red-200 dark:border-red-800 rounded">
<p className="text-sm text-red-600 dark:text-red-400">{error}</p>
@@ -168,10 +168,10 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common:recentEmails')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common.recentEmails')}</h2>
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</div>
{t('common:loadingEmails')}
{t('common.loadingEmails')}
</div>
);
}
@@ -179,10 +179,10 @@ export const EmailPreview: React.FC<EmailPreviewProps> = ({ email }) => {
return (
<div className="text-gray-500 dark:text-gray-400 mb-4">
<div className="flex items-center gap-2 mb-2">
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common:recentEmails')}</h2>
<h2 className="text-xl font-semibold text-gray-900 dark:text-white">{t('common.recentEmails')}</h2>
<div className="w-2 h-2 bg-green-500 rounded-full animate-pulse" />
</div>
{t('emails:noEmails')}
{t('emails.noEmails')}
</div>
);
}

View File

@@ -79,7 +79,7 @@ export const FormInput = forwardRef<HTMLInputElement, FormInputProps>(({
showPassword: controlledShowPassword,
onShowPasswordChange
}, ref) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const [internalShowPassword, setInternalShowPassword] = React.useState(false);
/**
@@ -114,7 +114,7 @@ export const FormInput = forwardRef<HTMLInputElement, FormInputProps>(({
* Toggle password visibility.
*/
onClick: (): void => setShowPassword(!showPassword),
title: showPassword ? t('hidePassword') : t('showPassword')
title: showPassword ? t('common.hidePassword') : t('common.showPassword')
}]
: buttons;

View File

@@ -61,7 +61,7 @@ export const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> =
value,
type = 'text'
}) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const [showPassword, setShowPassword] = useState(false);
const [copied, setCopied] = useState(false);
@@ -114,7 +114,7 @@ export const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> =
<button
type="button"
className="p-1 text-green-500 dark:text-green-400 transition-colors duration-200"
title={t('copied')}
title={t('common.copied')}
>
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<Icon name="check" />
@@ -125,7 +125,7 @@ export const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> =
type="button"
onClick={copyToClipboard}
className="p-1 text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white transition-colors duration-200"
title={t('copyToClipboard')}
title={t('common.copyToClipboard')}
>
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<Icon name="copy" />
@@ -137,7 +137,7 @@ export const FormInputCopyToClipboard: React.FC<FormInputCopyToClipboardProps> =
type="button"
onClick={() => setShowPassword(!showPassword)}
className="p-1 text-gray-600 hover:text-gray-900 dark:text-gray-400 dark:hover:text-white transition-colors duration-200"
title={showPassword ? t('hidePassword') : t('showPassword')}
title={showPassword ? t('common.hidePassword') : t('common.showPassword')}
>
<svg className="w-4 h-4" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<Icon name={showPassword ? 'visibility-off' : 'visibility'} />

View File

@@ -28,7 +28,7 @@ const LanguageSwitcher: React.FC<LanguageSwitcherProps> = ({
variant = 'dropdown',
size = 'md'
}): React.JSX.Element => {
const { i18n } = useTranslation('common');
const { i18n } = useTranslation();
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);

View File

@@ -8,7 +8,7 @@ type TabName = 'credentials' | 'emails' | 'settings';
* Bottom nav component.
*/
const BottomNav: React.FC = () => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const navigate = useNavigate();
const location = useLocation();
const [currentTab, setCurrentTab] = useState<TabName>('credentials');
@@ -62,7 +62,7 @@ const BottomNav: React.FC = () => {
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 7a2 2 0 012 2m4 0a6 6 0 01-7.743 5.743L11 17H9v2H7v2H4a1 1 0 01-1-1v-2.586a1 1 0 01.293-.707l5.964-5.964A6 6 0 1121 9z" />
</svg>
<span className="text-xs mt-1">{t('credentials:title', 'Credentials')}</span>
<span className="text-xs mt-1">{t('menu.credentials')}</span>
</button>
<button
onClick={() => handleTabChange('emails')}
@@ -73,7 +73,7 @@ const BottomNav: React.FC = () => {
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
<span className="text-xs mt-1">{t('emails:title', 'Emails')}</span>
<span className="text-xs mt-1">{t('menu.emails')}</span>
</button>
<button
onClick={() => handleTabChange('settings')}
@@ -85,7 +85,7 @@ const BottomNav: React.FC = () => {
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span className="text-xs mt-1">{t('settings:title', 'Settings')}</span>
<span className="text-xs mt-1">{t('menu.settings')}</span>
</button>
</div>
</div>

View File

@@ -23,7 +23,7 @@ const Header: React.FC<HeaderProps> = ({
routes = [],
rightButtons
}) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
const authContext = useAuth();
const navigate = useNavigate();
const location = useLocation();
@@ -88,7 +88,7 @@ const Header: React.FC<HeaderProps> = ({
className="flex items-center hover:opacity-80 transition-opacity"
>
<img src="/assets/images/logo.svg" alt="AliasVault" className="h-8 w-8 mr-2" />
<h1 className="text-gray-900 dark:text-white text-xl font-bold">{t('appName')}</h1>
<h1 className="text-gray-900 dark:text-white text-xl font-bold">{t('common.appName')}</h1>
{/* Hide beta badge on Safari as it's not allowed to show non-production badges */}
{!import.meta.env.SAFARI && (
<span className="text-primary-500 text-[10px] ml-1 font-normal">BETA</span>
@@ -108,7 +108,7 @@ const Header: React.FC<HeaderProps> = ({
onClick={(handleSettings)}
className="p-1 text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 rounded-lg hover:bg-gray-100 dark:hover:bg-gray-700"
>
<span className="sr-only">{t('settings')}</span>
<span className="sr-only">{t('common.settings')}</span>
<svg className="w-5 h-5" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<path fillRule="evenodd" d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z" clipRule="evenodd" />
</svg>

View File

@@ -10,7 +10,7 @@ import { useApiUrl } from '@/entrypoints/popup/utils/ApiUrlUtility';
const LoginServerInfo: React.FC = () => {
const { loadApiUrl, getDisplayUrl } = useApiUrl();
const navigate = useNavigate();
const { t } = useTranslation('auth');
const { t } = useTranslation();
useEffect(() => {
/**
@@ -28,7 +28,7 @@ const LoginServerInfo: React.FC = () => {
return (
<div className="text-xs text-gray-600 dark:text-gray-400 mb-4">
({t('connectingTo')}{' '}
({t('auth.connectingTo')}{' '}
<button
onClick={handleClick}
type="button"

View File

@@ -25,7 +25,7 @@ const Modal: React.FC<IModalProps> = ({
cancelText = '',
variant = 'default'
}) => {
const { t } = useTranslation('common');
const { t } = useTranslation();
if (!isOpen) {
return null;
}
@@ -48,7 +48,7 @@ const Modal: React.FC<IModalProps> = ({
className="absolute right-4 top-4 text-gray-400 hover:text-gray-500 focus:outline-none"
onClick={onClose}
>
<span className="sr-only">{t('close')}</span>
<span className="sr-only">{t('common.close')}</span>
<svg className="h-6 w-6" fill="none" viewBox="0 0 24 24" strokeWidth="1.5" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>

View File

@@ -23,9 +23,9 @@ export function useVaultMutate() : {
isLoading: boolean;
syncStatus: string;
} {
const { t } = useTranslation('common');
const { t } = useTranslation();
const [isLoading, setIsLoading] = useState(false);
const [syncStatus, setSyncStatus] = useState(t('syncingVault'));
const [syncStatus, setSyncStatus] = useState(t('common.syncingVault'));
const dbContext = useDb();
const { syncVault } = useVaultSync();
@@ -36,12 +36,12 @@ export function useVaultMutate() : {
operation: () => Promise<void>,
options: VaultMutationOptions
) : Promise<void> => {
setSyncStatus(t('savingChangesToVault'));
setSyncStatus(t('common.savingChangesToVault'));
// Execute the provided operation (e.g. create/update/delete credential)
await operation();
setSyncStatus(t('uploadingVaultToServer'));
setSyncStatus(t('common.uploadingVaultToServer'));
try {
// Upload the updated vault to the server.
@@ -103,11 +103,11 @@ export function useVaultMutate() : {
) => {
try {
setIsLoading(true);
setSyncStatus(t('checkingVaultUpdates'));
setSyncStatus(t('common.checkingVaultUpdates'));
// Skip sync check if requested (e.g., during upgrade operations)
if (options.skipSyncCheck) {
setSyncStatus(t('executingOperation'));
setSyncStatus(t('common.executingOperation'));
await executeMutateOperation(operation, options);
return;
}

View File

@@ -47,7 +47,7 @@ type VaultSyncOptions = {
export const useVaultSync = () : {
syncVault: (options?: VaultSyncOptions) => Promise<boolean>;
} => {
const { tc } = useTranslation('common');
const { t } = useTranslation();
const authContext = useAuth();
const dbContext = useDb();
const webApi = useWebApi();
@@ -67,7 +67,7 @@ export const useVaultSync = () : {
}
// Check app status and vault revision
onStatus?.(await tc('checkingVaultUpdates'));
onStatus?.(t('common.checkingVaultUpdates'));
const statusResponse = await withMinimumDelay(() => webApi.getStatus(), 300, enableDelay);
// Check if server is actually available, 0.0.0 indicates connection error which triggers offline mode.
@@ -77,7 +77,7 @@ export const useVaultSync = () : {
const statusError = webApi.validateStatusResponse(statusResponse);
if (statusError) {
onError?.(await tc(statusError));
onError?.(t('common.errors.' + statusError));
return false;
}
@@ -92,7 +92,7 @@ export const useVaultSync = () : {
const vaultRevisionNumber = vaultMetadata?.vaultRevisionNumber ?? 0;
if (statusResponse.vaultRevision > vaultRevisionNumber) {
onStatus?.(await tc('syncingUpdatedVault'));
onStatus?.(t('common.syncingUpdatedVault'));
const vaultResponseJson = await withMinimumDelay(() => webApi.get<VaultResponse>('Vault'), 1000, enableDelay);
const vaultError = webApi.validateVaultResponse(vaultResponseJson as VaultResponse, t);
@@ -171,7 +171,7 @@ export const useVaultSync = () : {
onError?.(errorMessage);
return false;
}
}, [authContext, dbContext, webApi, tc]);
}, [authContext, dbContext, webApi, t]);
return { syncVault };
};

View File

@@ -57,14 +57,14 @@ const createUrlSchema = (t: (key: string) => string): Yup.ObjectSchema<{apiUrl:
* Auth settings page only shown when user is not logged in.
*/
const AuthSettings: React.FC = () => {
const { t } = useTranslation('settings');
const { t } = useTranslation();
const [selectedOption, setSelectedOption] = useState<string>('');
const [customUrl, setCustomUrl] = useState<string>('');
const [customClientUrl, setCustomClientUrl] = useState<string>('');
const [isGloballyEnabled, setIsGloballyEnabled] = useState<boolean>(true);
const [errors, setErrors] = useState<{ apiUrl?: string; clientUrl?: string }>({});
const { setIsInitialLoading } = useLoading();
const urlSchema = createUrlSchema(t);
useEffect(() => {
@@ -176,14 +176,14 @@ const AuthSettings: React.FC = () => {
{/* Language Settings Section */}
<div className="mb-6">
<div className="flex flex-col gap-2">
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('language')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('common.language')}</p>
<LanguageSwitcher variant="dropdown" size="sm" />
</div>
</div>
<div className="mb-6">
<label htmlFor="api-connection" className="block text-sm font-medium text-gray-700 dark:text-gray-200 mb-2">
{t('serverUrl')}
{t('common.serverUrl')}
</label>
<select
value={selectedOption}
@@ -238,7 +238,7 @@ const AuthSettings: React.FC = () => {
{/* Autofill Popup Settings Section */}
<div className="mb-6">
<div className="flex flex-col gap-2">
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('autofillEnabled')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('common.autofillEnabled')}</p>
<button
onClick={toggleGlobalPopup}
className={`px-4 py-2 rounded-md transition-colors ${
@@ -247,13 +247,13 @@ const AuthSettings: React.FC = () => {
: 'bg-red-200 text-red-800 hover:bg-red-300 dark:bg-red-900/30 dark:text-red-400 dark:hover:bg-red-900/50'
}`}
>
{isGloballyEnabled ? t('common:enabled', 'Enabled') : t('common:disabled', 'Disabled')}
{isGloballyEnabled ? t('common.enabled', 'Enabled') : t('common.disabled', 'Disabled')}
</button>
</div>
</div>
<div className="text-center text-gray-400 dark:text-gray-600">
{t('version')}: {AppInfo.VERSION}
{t('common.version')}: {AppInfo.VERSION}
</div>
</div>
);

View File

@@ -69,7 +69,7 @@ const credentialSchema = Yup.object().shape({
* Add or edit credential page.
*/
const CredentialAddEdit: React.FC = () => {
const { t } = useTranslation(['common', 'credentials']);
const { t } = useTranslation();
const { id } = useParams();
const navigate = useNavigate();
const dbContext = useDb();
@@ -460,14 +460,14 @@ const CredentialAddEdit: React.FC = () => {
{isEditMode && (
<HeaderButton
onClick={() => setShowDeleteModal(true)}
title={t('credentials:deleteCredential')}
title={t('credentials.deleteCredential')}
iconType={HeaderIconType.DELETE}
variant="danger"
/>
)}
<HeaderButton
onClick={handleSubmit(onSubmit)}
title={t('credentials:saveCredential')}
title={t('credentials.saveCredential')}
iconType={HeaderIconType.SAVE}
/>
</div>
@@ -483,7 +483,7 @@ const CredentialAddEdit: React.FC = () => {
}, [setHeaderButtons]);
if (isEditMode && !watch('ServiceName')) {
return <div>{t('common:loading')}</div>;
return <div>{t('common.loading')}</div>;
}
return (
@@ -505,10 +505,10 @@ const CredentialAddEdit: React.FC = () => {
setShowDeleteModal(false);
void handleDelete();
}}
title={t('credentials:deleteCredentialTitle')}
message={t('credentials:deleteCredentialConfirm')}
confirmText={t('common:delete')}
cancelText={t('common:cancel')}
title={t('credentials.deleteCredentialTitle')}
message={t('credentials.deleteCredentialConfirm')}
confirmText={t('common.delete')}
cancelText={t('common.cancel')}
variant="danger"
/>
@@ -529,7 +529,7 @@ const CredentialAddEdit: React.FC = () => {
<circle cx="8" cy="16" r="1"/>
<circle cx="16" cy="16" r="1"/>
</svg>
{t('credentials:randomAlias')}
{t('credentials.randomAlias')}
</button>
<button
type="button"
@@ -542,18 +542,18 @@ const CredentialAddEdit: React.FC = () => {
<circle cx="12" cy="7" r="4"/>
<path d="M5.5 20a6.5 6.5 0 0 1 13 0"/>
</svg>
{t('credentials:manual')}
{t('credentials.manual')}
</button>
</div>
)}
<div className="space-y-4">
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials:service')}</h2>
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials.service')}</h2>
<div className="space-y-4">
<FormInput
id="serviceName"
label={t('credentials:serviceName')}
label={t('credentials.serviceName')}
ref={serviceNameRef}
value={watch('ServiceName') ?? ''}
onChange={(value) => setValue('ServiceName', value)}
@@ -562,7 +562,7 @@ const CredentialAddEdit: React.FC = () => {
/>
<FormInput
id="serviceUrl"
label={t('credentials:serviceUrl')}
label={t('credentials.serviceUrl')}
value={watch('ServiceUrl') ?? ''}
onChange={(value) => setValue('ServiceUrl', value)}
error={errors.ServiceUrl?.message}
@@ -573,11 +573,11 @@ const CredentialAddEdit: React.FC = () => {
{(mode === 'manual' || isEditMode) && (
<>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials:loginCredentials')}</h2>
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials.loginCredentials')}</h2>
<div className="space-y-4">
<FormInput
id="username"
label={t('common:username')}
label={t('common.username')}
value={watch('Username') ?? ''}
onChange={(value) => setValue('Username', value)}
error={errors.Username?.message}
@@ -585,13 +585,13 @@ const CredentialAddEdit: React.FC = () => {
{
icon: 'refresh',
onClick: generateRandomUsername,
title: t('credentials:generateRandomUsername')
title: t('credentials.generateRandomUsername')
}
]}
/>
<FormInput
id="password"
label={t('common:password')}
label={t('common.password')}
type="password"
value={watch('Password') ?? ''}
onChange={(value) => setValue('Password', value)}
@@ -602,7 +602,7 @@ const CredentialAddEdit: React.FC = () => {
{
icon: 'refresh',
onClick: generateRandomPassword,
title: t('credentials:generateRandomPassword')
title: t('credentials.generateRandomPassword')
}
]}
/>
@@ -611,11 +611,11 @@ const CredentialAddEdit: React.FC = () => {
onClick={handleGenerateRandomAlias}
className="w-full bg-primary-500 text-white py-2 px-4 rounded hover:bg-primary-600 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
>
{t('credentials:generateRandomAlias')}
{t('credentials.generateRandomAlias')}
</button>
<FormInput
id="email"
label={t('common:email')}
label={t('common.email')}
value={watch('Alias.Email') ?? ''}
onChange={(value) => setValue('Alias.Email', value)}
error={errors.Alias?.Email?.message}
@@ -624,40 +624,40 @@ const CredentialAddEdit: React.FC = () => {
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials:alias')}</h2>
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials.alias')}</h2>
<div className="space-y-4">
<FormInput
id="firstName"
label={t('credentials:firstName')}
label={t('credentials.firstName')}
value={watch('Alias.FirstName') ?? ''}
onChange={(value) => setValue('Alias.FirstName', value)}
error={errors.Alias?.FirstName?.message}
/>
<FormInput
id="lastName"
label={t('credentials:lastName')}
label={t('credentials.lastName')}
value={watch('Alias.LastName') ?? ''}
onChange={(value) => setValue('Alias.LastName', value)}
error={errors.Alias?.LastName?.message}
/>
<FormInput
id="nickName"
label={t('credentials:nickName')}
label={t('credentials.nickName')}
value={watch('Alias.NickName') ?? ''}
onChange={(value) => setValue('Alias.NickName', value)}
error={errors.Alias?.NickName?.message}
/>
<FormInput
id="gender"
label={t('credentials:gender')}
label={t('credentials.gender')}
value={watch('Alias.Gender') ?? ''}
onChange={(value) => setValue('Alias.Gender', value)}
error={errors.Alias?.Gender?.message}
/>
<FormInput
id="birthDate"
label={t('credentials:birthDate')}
placeholder={t('credentials:birthDatePlaceholder')}
label={t('credentials.birthDate')}
placeholder={t('credentials.birthDatePlaceholder')}
value={watch('Alias.BirthDate') ?? ''}
onChange={(value) => setValue('Alias.BirthDate', value)}
error={errors.Alias?.BirthDate?.message}
@@ -666,11 +666,11 @@ const CredentialAddEdit: React.FC = () => {
</div>
<div className="bg-white dark:bg-gray-800 p-4 rounded-lg border border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials:metadata')}</h2>
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">{t('credentials.metadata')}</h2>
<div className="space-y-4">
<FormInput
id="notes"
label={t('credentials:notes')}
label={t('credentials.notes')}
value={watch('Notes') ?? ''}
onChange={(value) => setValue('Notes', value)}
multiline

View File

@@ -23,7 +23,7 @@ import type { Credential } from '@/utils/dist/shared/models/vault';
* Credential details page.
*/
const CredentialDetails: React.FC = (): React.ReactElement => {
const { t } = useTranslation(['common', 'credentials']);
const { t } = useTranslation();
const { id } = useParams();
const navigate = useNavigate();
const dbContext = useDb();
@@ -76,13 +76,13 @@ const CredentialDetails: React.FC = (): React.ReactElement => {
{!PopoutUtility.isPopup() && (
<HeaderButton
onClick={openInNewPopup}
title={t('common:openInNewWindow')}
title={t('common.openInNewWindow')}
iconType={HeaderIconType.EXPAND}
/>
)}
<HeaderButton
onClick={handleEdit}
title={t('credentials:editCredential')}
title={t('credentials.editCredential')}
iconType={HeaderIconType.EDIT}
/>
</div>
@@ -97,7 +97,7 @@ const CredentialDetails: React.FC = (): React.ReactElement => {
}, [setHeaderButtons]);
if (!credential) {
return <div>{t('common:loading')}</div>;
return <div>{t('common.loading')}</div>;
}
return (

View File

@@ -22,7 +22,7 @@ import { useMinDurationLoading } from '@/hooks/useMinDurationLoading';
* Credentials list page.
*/
const CredentialsList: React.FC = () => {
const { t } = useTranslation('credentials');
const { t } = useTranslation();
const dbContext = useDb();
const webApi = useWebApi();
const navigate = useNavigate();
@@ -158,14 +158,14 @@ const CredentialsList: React.FC = () => {
return (
<div>
<div className="flex justify-between items-center mb-4">
<h2 className="text-gray-900 dark:text-white text-xl">{t('title')}</h2>
<h2 className="text-gray-900 dark:text-white text-xl">{t('credentials.title')}</h2>
<ReloadButton onClick={syncVaultAndRefresh} />
</div>
{credentials.length > 0 ? (
<input
type="text"
placeholder={t('searchPlaceholder')}
placeholder={t('credentials.searchPlaceholder')}
value={searchTerm}
onChange={(e) => setSearchTerm(e.target.value)}
autoFocus
@@ -178,13 +178,13 @@ const CredentialsList: React.FC = () => {
{credentials.length === 0 ? (
<div className="text-gray-500 dark:text-gray-400 space-y-2 mb-10">
<p className="text-sm">
{t('welcomeTitle')}
{t('credentials.welcomeTitle')}
</p>
<p className="text-sm">
{t('welcomeDescription')}
{t('credentials.welcomeDescription')}
</p>
<p className="text-sm">
{t('manualCreationHint')}
{t('credentials.manualCreationHint')}
</p>
</div>
) : (

View File

@@ -23,7 +23,7 @@ import { HeaderIconType } from '../components/Icons/HeaderIcons';
* Email details page.
*/
const EmailDetails: React.FC = (): React.ReactElement => {
const { t } = useTranslation(['common', 'emails']);
const { t } = useTranslation();
const { id } = useParams<{ id: string }>();
const navigate = useNavigate();
const dbContext = useDb();
@@ -151,13 +151,13 @@ const EmailDetails: React.FC = (): React.ReactElement => {
{!PopoutUtility.isPopup() && (
<HeaderButton
onClick={openInNewPopup}
title={t('common:openInNewWindow')}
title={t('common.openInNewWindow')}
iconType={HeaderIconType.EXPAND}
/>
)}
<HeaderButton
onClick={() => setShowDeleteModal(true)}
title={t('emails:deleteEmail')}
title={t('emails.deleteEmail')}
iconType={HeaderIconType.DELETE}
variant="danger"
/>
@@ -184,11 +184,11 @@ const EmailDetails: React.FC = (): React.ReactElement => {
}
if (error) {
return <div className="text-red-500">{t('common:error')} {error}</div>;
return <div className="text-red-500">{t('common.error')} {error}</div>;
}
if (!email) {
return <div className="text-gray-500">{t('emails:emailNotFound')}</div>;
return <div className="text-gray-500">{t('emails.emailNotFound')}</div>;
}
return (
@@ -200,10 +200,10 @@ const EmailDetails: React.FC = (): React.ReactElement => {
setShowDeleteModal(false);
void handleDelete();
}}
title={t('emails:deleteEmailTitle')}
message={t('emails:deleteEmailConfirm')}
confirmText={t('common:delete')}
cancelText={t('common:cancel')}
title={t('emails.deleteEmailTitle')}
message={t('emails.deleteEmailConfirm')}
confirmText={t('common.delete')}
cancelText={t('common.cancel')}
variant="danger"
/>
@@ -214,9 +214,9 @@ const EmailDetails: React.FC = (): React.ReactElement => {
<h1 className="text-2xl font-bold text-gray-900 dark:text-white">{email.subject}</h1>
</div>
<div className="space-y-1 text-sm text-gray-600 dark:text-gray-400">
<p>{t('emails:from')} {email.fromDisplay} ({email.fromLocal}@{email.fromDomain})</p>
<p>{t('emails:to')} {email.toLocal}@{email.toDomain}</p>
<p>{t('emails:date')} {new Date(email.dateSystem).toLocaleString()}</p>
<p>{t('emails.from')} {email.fromDisplay} ({email.fromLocal}@{email.fromDomain})</p>
<p>{t('emails.to')} {email.toLocal}@{email.toDomain}</p>
<p>{t('emails.date')} {new Date(email.dateSystem).toLocaleString()}</p>
</div>
</div>
@@ -226,7 +226,7 @@ const EmailDetails: React.FC = (): React.ReactElement => {
<iframe
srcDoc={ConversionUtility.convertAnchorTagsToOpenInNewTab(email.messageHtml)}
className="w-full min-h-[500px] border-0"
title={t('emails:emailContent')}
title={t('emails.emailContent')}
/>
) : (
<pre className="whitespace-pre-wrap text-gray-700 dark:text-gray-300">
@@ -239,7 +239,7 @@ const EmailDetails: React.FC = (): React.ReactElement => {
{email.attachments && email.attachments.length > 0 && (
<div className="p-6 border-t border-gray-200 dark:border-gray-700">
<h2 className="text-lg font-semibold mb-4 text-gray-900 dark:text-white">
{t('emails:attachments')}
{t('emails.attachments')}
</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 md:grid-cols-3 gap-4">
{email.attachments.map((attachment) => (

View File

@@ -29,8 +29,7 @@ import { storage } from '#imports';
* Login page
*/
const Login: React.FC = () => {
const { t } = useTranslation('auth');
const { t: tCommon } = useTranslation('common');
const { t } = useTranslation();
const navigate = useNavigate();
const authContext = useAuth();
const dbContext = useDb();
@@ -141,7 +140,7 @@ const Login: React.FC = () => {
// Check if token was returned.
if (!validationResponse.token) {
throw new Error(t('errors.noToken'));
throw new Error(t('auth.errors.noToken'));
}
// Try to get latest vault manually providing auth token.
@@ -149,7 +148,7 @@ const Login: React.FC = () => {
'Authorization': `Bearer ${validationResponse.token.token}`
} });
const vaultError = webApi.validateVaultResponse(vaultResponseJson, tCommon);
const vaultError = webApi.validateVaultResponse(vaultResponseJson, t);
if (vaultError) {
setError(vaultError);
hideLoading();
@@ -174,7 +173,7 @@ const Login: React.FC = () => {
}
} catch (err) {
await authContext.logout();
setError(err instanceof Error ? err.message : t('errors.migrationError'));
setError(err instanceof Error ? err.message : t('auth.errors.migrationError'));
hideLoading();
return;
}
@@ -187,9 +186,9 @@ const Login: React.FC = () => {
} catch (err) {
// Show API authentication errors as-is.
if (err instanceof ApiAuthError) {
setError(tCommon('apiErrors.' + err.message));
setError(t('common.apiErrors.' + err.message));
} else {
setError(t('errors.serverError'));
setError(t('auth.errors.serverError'));
}
hideLoading();
}
@@ -206,13 +205,13 @@ const Login: React.FC = () => {
showLoading();
if (!passwordHashString || !passwordHashBase64 || !loginResponse) {
throw new Error(t('errors.loginDataMissing'));
throw new Error(t('auth.errors.loginDataMissing'));
}
// Validate that 2FA code is a 6-digit number
const code = twoFactorCode.trim();
if (!/^\d{6}$/.test(code)) {
throw new Error(t('errors.invalidCode'));
throw new Error(t('auth.errors.invalidCode'));
}
const validationResponse = await srpUtil.validateLogin2Fa(
@@ -225,7 +224,7 @@ const Login: React.FC = () => {
// Check if token was returned.
if (!validationResponse.token) {
throw new Error(t('errors.noToken'));
throw new Error(t('auth.errors.noToken'));
}
// Try to get latest vault manually providing auth token.
@@ -233,7 +232,7 @@ const Login: React.FC = () => {
'Authorization': `Bearer ${validationResponse.token.token}`
} });
const vaultError = webApi.validateVaultResponse(vaultResponseJson, tCommon);
const vaultError = webApi.validateVaultResponse(vaultResponseJson, t);
if (vaultError) {
setError(vaultError);
hideLoading();
@@ -258,7 +257,7 @@ const Login: React.FC = () => {
}
} catch (err) {
await authContext.logout();
setError(err instanceof Error ? err.message : t('errors.migrationError'));
setError(err instanceof Error ? err.message : t('auth.errors.migrationError'));
hideLoading();
return;
}
@@ -277,9 +276,9 @@ const Login: React.FC = () => {
// Show API authentication errors as-is.
console.error('2FA error:', err);
if (err instanceof ApiAuthError) {
setError(tCommon('apiErrors:' + err.message));
setError(t('common.apiErrors.' + err.message));
} else {
setError(t('errors.serverError'));
setError(t('auth.errors.serverError'));
}
hideLoading();
}
@@ -307,10 +306,10 @@ const Login: React.FC = () => {
)}
<div className="mb-6">
<p className="text-gray-700 dark:text-gray-200 mb-4">
{t('twoFactorTitle')}
{t('auth.twoFactorTitle')}
</p>
<label className="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2" htmlFor="twoFactorCode">
{t('authCode')}
{t('auth.authCode')}
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-200 dark:bg-gray-800 dark:border-gray-600 leading-tight focus:outline-none focus:shadow-outline"
@@ -318,13 +317,13 @@ const Login: React.FC = () => {
type="text"
value={twoFactorCode}
onChange={(e) => setTwoFactorCode(e.target.value)}
placeholder={t('authCodePlaceholder')}
placeholder={t('auth.authCodePlaceholder')}
required
/>
</div>
<div className="flex flex-col w-full space-y-2">
<Button type="submit">
{t('verify')}
{t('auth.verify')}
</Button>
<Button
type="button"
@@ -343,11 +342,11 @@ const Login: React.FC = () => {
}}
variant="secondary"
>
{t('cancel')}
{t('auth.cancel')}
</Button>
</div>
<p className="text-xs text-gray-500 dark:text-gray-400 mt-4 text-center">
{t('twoFactorNote')}
{t('auth.twoFactorNote')}
</p>
</form>
</div>
@@ -362,18 +361,18 @@ const Login: React.FC = () => {
{error}
</div>
)}
<h2 className="text-xl font-bold dark:text-gray-200">{t('loginTitle')}</h2>
<h2 className="text-xl font-bold dark:text-gray-200">{t('auth.loginTitle')}</h2>
<LoginServerInfo />
<div className="mb-4">
<label className="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2" htmlFor="username">
{t('username')}
{t('auth.username')}
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-200 dark:bg-gray-800 dark:border-gray-600 leading-tight focus:outline-none focus:shadow-outline"
id="username"
type="text"
name="username"
placeholder={t('usernamePlaceholder')}
placeholder={t('auth.usernamePlaceholder')}
value={credentials.username}
onChange={handleChange}
required
@@ -381,14 +380,14 @@ const Login: React.FC = () => {
</div>
<div className="mb-4">
<label className="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2" htmlFor="password">
{t('password')}
{t('auth.password')}
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-200 dark:bg-gray-800 dark:border-gray-600 mb-3 leading-tight focus:outline-none focus:shadow-outline"
id="password"
type="password"
name="password"
placeholder={t('passwordPlaceholder')}
placeholder={t('auth.passwordPlaceholder')}
value={credentials.password}
onChange={handleChange}
required
@@ -402,24 +401,24 @@ const Login: React.FC = () => {
onChange={(e) => setRememberMe(e.target.checked)}
className="mr-2"
/>
<span className="text-sm text-gray-700 dark:text-gray-200">{t('rememberMe')}</span>
<span className="text-sm text-gray-700 dark:text-gray-200">{t('auth.rememberMe')}</span>
</label>
</div>
<div className="flex w-full">
<Button type="submit">
{t('loginButton')}
{t('auth.loginButton')}
</Button>
</div>
</form>
<div className="text-center text-sm text-gray-600 dark:text-gray-400">
{t('noAccount')}{' '}
{t('auth.noAccount')}{' '}
<a
href={clientUrl ?? ''}
target="_blank"
rel="noopener noreferrer"
className="text-orange-500 hover:text-orange-600 dark:text-orange-400 dark:hover:text-orange-500"
>
{t('createVault')}
{t('auth.createVault')}
</a>
</div>
</div>

View File

@@ -34,7 +34,7 @@ type PopupSettings = {
* Settings page component.
*/
const Settings: React.FC = () => {
const { t } = useTranslation('settings');
const { t } = useTranslation();
const { theme, setTheme } = useTheme();
const authContext = useAuth();
const { setHeaderButtons } = useHeaderButtons();
@@ -80,14 +80,14 @@ const Settings: React.FC = () => {
<>
<HeaderButton
onClick={() => PopoutUtility.openInNewPopup()}
title={t('openInNewWindow')}
title={t('settings.openInNewWindow')}
iconType={HeaderIconType.EXPAND}
/>
</>
)}
<HeaderButton
onClick={openClientTab}
title={t('openWebApp')}
title={t('settings.openWebApp')}
iconType={HeaderIconType.EXTERNAL_LINK}
/>
</div>
@@ -258,7 +258,7 @@ const Settings: React.FC = () => {
return (
<div className="space-y-6">
<div className="flex justify-between items-center mb-4">
<h2 className="text-gray-900 dark:text-white text-xl">{t('title')}</h2>
<h2 className="text-gray-900 dark:text-white text-xl">{t('settings.title')}</h2>
</div>
{/* User Menu Section */}
@@ -279,7 +279,7 @@ const Settings: React.FC = () => {
{authContext.username}
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
{t('loggedIn')}
{t('settings.loggedIn')}
</p>
</div>
</div>
@@ -287,7 +287,7 @@ const Settings: React.FC = () => {
onClick={handleLogout}
className="px-4 py-2 text-sm font-medium text-red-600 hover:text-red-700 dark:text-red-400 dark:hover:text-red-300"
>
{t('logout')}
{t('settings.logout')}
</button>
</div>
</div>
@@ -296,14 +296,14 @@ const Settings: React.FC = () => {
{/* Global Settings Section */}
<section>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('globalSettings')}</h3>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('settings.globalSettings')}</h3>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4 space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('autofillPopup')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('settings.autofillPopup')}</p>
<p className={`text-sm mt-1 ${settings.isGloballyEnabled ? 'text-gray-600 dark:text-gray-400' : 'text-red-600 dark:text-red-400'}`}>
{settings.isGloballyEnabled ? t('activeOnAllSites') : t('disabledOnAllSites')}
{settings.isGloballyEnabled ? t('settings.activeOnAllSites') : t('settings.disabledOnAllSites')}
</p>
</div>
<button
@@ -314,15 +314,15 @@ const Settings: React.FC = () => {
: 'bg-red-500 hover:bg-red-600 text-white'
}`}
>
{settings.isGloballyEnabled ? t('enabled') : t('disabled')}
{settings.isGloballyEnabled ? t('settings.enabled') : t('settings.disabled')}
</button>
</div>
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('rightClickContextMenu')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('settings.rightClickContextMenu')}</p>
<p className={`text-sm mt-1 ${settings.isContextMenuEnabled ? 'text-gray-600 dark:text-gray-400' : 'text-red-600 dark:text-red-400'}`}>
{settings.isContextMenuEnabled ? t('enabled') : t('disabled')}
{settings.isContextMenuEnabled ? t('settings.enabled') : t('settings.disabled')}
</p>
</div>
<button
@@ -343,18 +343,18 @@ const Settings: React.FC = () => {
{/* Site-Specific Settings Section */}
{settings.isGloballyEnabled && (
<section>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('siteSpecificSettings')}</h3>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('settings.siteSpecificSettings')}</h3>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('autofillPopupOn')}{settings.currentUrl}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('settings.autofillPopupOn')}{settings.currentUrl}</p>
<p className={`text-sm mt-1 ${settings.isEnabled ? 'text-gray-600 dark:text-gray-400' : 'text-red-600 dark:text-red-400'}`}>
{settings.isEnabled ? t('enabledForThisSite') : t('disabledForThisSite')}
{settings.isEnabled ? t('settings.enabledForThisSite') : t('settings.disabledForThisSite')}
</p>
{!settings.isEnabled && settings.temporaryDisabledUrls[settings.currentUrl] && (
<p className="text-xs text-gray-500 dark:text-gray-400 mt-1">
{t('temporarilyDisabledUntil')}{new Date(settings.temporaryDisabledUrls[settings.currentUrl]).toLocaleTimeString()}
{t('settings.temporarilyDisabledUntil')}{new Date(settings.temporaryDisabledUrls[settings.currentUrl]).toLocaleTimeString()}
</p>
)}
</div>
@@ -367,7 +367,7 @@ const Settings: React.FC = () => {
: 'bg-red-500 hover:bg-red-600 text-white'
}`}
>
{settings.isEnabled ? t('enabled') : t('disabled')}
{settings.isEnabled ? t('settings.enabled') : t('settings.disabled')}
</button>
)}
</div>
@@ -377,7 +377,7 @@ const Settings: React.FC = () => {
onClick={resetSettings}
className="w-full px-4 py-2 bg-gray-100 hover:bg-gray-200 dark:bg-gray-700 dark:hover:bg-gray-600 rounded-md text-gray-700 dark:text-gray-300 transition-colors text-sm"
>
{t('resetAllSiteSettings')}
{t('settings.resetAllSiteSettings')}
</button>
</div>
</div>
@@ -387,17 +387,17 @@ const Settings: React.FC = () => {
{/* Appearance Settings Section */}
<section>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('appearance')}</h3>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('settings.appearance')}</h3>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4">
<div className="mb-4">
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white mb-3">{t('language')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white mb-3">{t('settings.language')}</p>
<LanguageSwitcher variant="dropdown" size="sm" />
</div>
</div>
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white mb-2">{t('theme')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white mb-2">{t('settings.theme')}</p>
<div className="flex flex-col space-y-2">
<label className="flex items-center">
<input
@@ -408,7 +408,7 @@ const Settings: React.FC = () => {
onChange={() => setThemePreference('system')}
className="mr-2"
/>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('useDefault')}</span>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('settings.useDefault')}</span>
</label>
<label className="flex items-center">
<input
@@ -419,7 +419,7 @@ const Settings: React.FC = () => {
onChange={() => setThemePreference('light')}
className="mr-2"
/>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('light')}</span>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('settings.light')}</span>
</label>
<label className="flex items-center">
<input
@@ -430,7 +430,7 @@ const Settings: React.FC = () => {
onChange={() => setThemePreference('dark')}
className="mr-2"
/>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('dark')}</span>
<span className="text-sm text-gray-700 dark:text-gray-300">{t('settings.dark')}</span>
</label>
</div>
</div>
@@ -441,18 +441,18 @@ const Settings: React.FC = () => {
{/* Keyboard Shortcuts Section */}
{import.meta.env.CHROME && (
<section>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('keyboardShortcuts')}</h3>
<h3 className="text-md font-semibold text-gray-900 dark:text-white mb-3">{t('settings.keyboardShortcuts')}</h3>
<div className="bg-white dark:bg-gray-800 rounded-lg shadow-sm border border-gray-200 dark:border-gray-700">
<div className="p-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('configureKeyboardShortcuts')}</p>
<p className="text-sm font-medium text-gray-900 dark:text-white">{t('settings.configureKeyboardShortcuts')}</p>
</div>
<button
onClick={openKeyboardShortcuts}
className="px-4 py-2 bg-blue-500 hover:bg-blue-600 text-white rounded-md transition-colors"
>
{t('configure')}
{t('settings.configure')}
</button>
</div>
</div>
@@ -461,7 +461,7 @@ const Settings: React.FC = () => {
)}
<div className="text-center text-gray-400 dark:text-gray-600">
{t('versionPrefix')}{AppInfo.VERSION} ({getDisplayUrl()})
{t('settings.versionPrefix')}{AppInfo.VERSION} ({getDisplayUrl()})
</div>
</div>
);

View File

@@ -25,8 +25,7 @@ import { storage } from '#imports';
* Unlock page
*/
const Unlock: React.FC = () => {
const { t } = useTranslation('auth');
const { t: tc } = useTranslation('common');
const { t } = useTranslation();
const authContext = useAuth();
const dbContext = useDb();
const navigate = useNavigate();
@@ -47,21 +46,21 @@ const Unlock: React.FC = () => {
const statusResponse = await webApi.getStatus();
const statusError = webApi.validateStatusResponse(statusResponse);
if (statusError !== null) {
await webApi.logout(tc(statusError));
await webApi.logout(t('common.apiErrors.' + statusError));
navigate('/logout');
}
setIsInitialLoading(false);
};
checkStatus();
}, [webApi, authContext, setIsInitialLoading, navigate, tc]);
}, [webApi, authContext, setIsInitialLoading, navigate, t]);
// Set header buttons on mount and clear on unmount
useEffect((): (() => void) => {
const headerButtonsJSX = !PopoutUtility.isPopup() ? (
<HeaderButton
onClick={() => PopoutUtility.openInNewPopup()}
title={t('common:openInNewWindow', 'Open in new window')}
title={t('common.openInNewWindow')}
iconType={HeaderIconType.EXPAND}
/>
) : null;
@@ -96,9 +95,9 @@ const Unlock: React.FC = () => {
// Make API call to get latest vault
const vaultResponseJson = await webApi.get<VaultResponse>('Vault');
const vaultError = webApi.validateVaultResponse(vaultResponseJson);
const vaultError = webApi.validateVaultResponse(vaultResponseJson, t);
if (vaultError) {
setError(vaultError);
setError(t('common.apiErrors.' + vaultError));
hideLoading();
return;
}
@@ -115,7 +114,7 @@ const Unlock: React.FC = () => {
// Redirect to reinitialize page
navigate('/reinitialize', { replace: true });
} catch (err) {
setError(t('errors.wrongPassword'));
setError(t('auth.errors.wrongPassword'));
console.error('Unlock error:', err);
} finally {
hideLoading();
@@ -146,14 +145,14 @@ const Unlock: React.FC = () => {
{authContext.username}
</p>
<p className="text-xs text-gray-500 dark:text-gray-400">
{t('loggedIn')}
{t('auth.loggedIn')}
</p>
</div>
</div>
{/* Instruction Title */}
<h2 className="text-xl font-semibold text-gray-900 dark:text-white mb-4">
{t('unlockTitle')}
{t('auth.unlockTitle')}
</h2>
{error && (
@@ -164,7 +163,7 @@ const Unlock: React.FC = () => {
<div className="mb-2">
<label className="block text-gray-700 dark:text-gray-200 text-sm font-bold mb-2" htmlFor="password">
{t('masterPassword')}
{t('auth.masterPassword')}
</label>
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 dark:text-gray-200 dark:bg-gray-800 dark:border-gray-600 mb-3 leading-tight focus:outline-none focus:shadow-outline"
@@ -172,17 +171,17 @@ const Unlock: React.FC = () => {
type="password"
value={password}
onChange={(e) => setPassword(e.target.value)}
placeholder={t('passwordPlaceholder')}
placeholder={t('auth.passwordPlaceholder')}
required
/>
</div>
<Button type="submit">
{t('unlockVault')}
{t('auth.unlockVault')}
</Button>
<div className="text-sm font-medium text-gray-500 dark:text-gray-200 mt-6">
{t('switchAccounts')} <button onClick={handleLogout} className="text-primary-700 hover:underline dark:text-primary-500">{t('logout')}</button>
{t('auth.switchAccounts')} <button onClick={handleLogout} className="text-primary-700 hover:underline dark:text-primary-500">{t('auth.logout')}</button>
</div>
</form>
</div>

View File

@@ -8,7 +8,7 @@ import { useNavigate } from 'react-router-dom';
*/
const UnlockSuccess: React.FC = () => {
const navigate = useNavigate();
const { t } = useTranslation('auth');
const { t } = useTranslation();
/**
* Handle browsing vault contents - navigate to credentials page and reset mode parameter
@@ -31,23 +31,23 @@ const UnlockSuccess: React.FC = () => {
</svg>
</div>
<h2 className="text-xl font-semibold mb-4 text-gray-900 dark:text-white">
{t('unlockSuccessTitle')}
{t('auth.unlockSuccessTitle')}
</h2>
<p className="mb-6 text-gray-600 dark:text-gray-400">
{t('unlockSuccessDescription')}
{t('auth.unlockSuccessDescription')}
</p>
<div className="space-y-3 w-full">
<button
onClick={() => window.close()}
className="w-full px-4 py-2 text-white bg-primary-600 rounded hover:bg-primary-700 focus:outline-none focus:ring-2 focus:ring-primary-500 focus:ring-offset-2"
>
{t('closePopup')}
{t('auth.closePopup')}
</button>
<button
onClick={handleBrowseVaultContents}
className="w-full px-4 py-2 text-gray-700 bg-gray-100 rounded hover:bg-gray-200 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 dark:bg-gray-700 dark:text-gray-300 dark:hover:bg-gray-600"
>
{t('browseVault')}
{t('auth.browseVault')}
</button>
</div>
</div>

View File

@@ -0,0 +1,316 @@
{
"auth": {
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
},
"menu": {
"credentials": "Credentials",
"emails": "Emails",
"settings": "Settings"
},
"common": {
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
},
"content": {
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
},
"credentials": {
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
},
"emails": {
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
},
"settings": {
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}
}

View File

@@ -1,35 +0,0 @@
{
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"connectingTo": "Connecting to",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again."
}
}

View File

@@ -1,39 +0,0 @@
{
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation..."
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
}

View File

@@ -1,18 +0,0 @@
{
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailInUse": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"emailSyncError": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
}
}

View File

@@ -1,33 +0,0 @@
{
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version "
}

View File

@@ -0,0 +1,316 @@
{
"auth": {
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
},
"menu": {
"credentials": "Credentials",
"emails": "Emails",
"settings": "Settings"
},
"common": {
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
},
"content": {
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
},
"credentials": {
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
},
"emails": {
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
},
"settings": {
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}
}

View File

@@ -1,42 +0,0 @@
{
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
}

View File

@@ -1,90 +0,0 @@
{
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
}

View File

@@ -1,39 +0,0 @@
{
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
}

View File

@@ -1,20 +0,0 @@
{
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
}

View File

@@ -1,39 +0,0 @@
{
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}

View File

@@ -0,0 +1,316 @@
{
"auth": {
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
},
"menu": {
"credentials": "Credentials",
"emails": "Emails",
"settings": "Settings"
},
"common": {
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
},
"content": {
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
},
"credentials": {
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
},
"emails": {
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
},
"settings": {
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}
}

View File

@@ -1,35 +0,0 @@
{
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"connectingTo": "Connecting to",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again."
}
}

View File

@@ -1,39 +0,0 @@
{
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation..."
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
}

View File

@@ -1,18 +0,0 @@
{
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailInUse": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"emailSyncError": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
}
}

View File

@@ -1,33 +0,0 @@
{
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version "
}

View File

@@ -0,0 +1,316 @@
{
"auth": {
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
},
"menu": {
"credentials": "Credentials",
"emails": "Emails",
"settings": "Settings"
},
"common": {
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
},
"content": {
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
},
"credentials": {
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
},
"emails": {
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
},
"settings": {
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}
}

View File

@@ -1,35 +0,0 @@
{
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"connectingTo": "Connecting to",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again."
}
}

View File

@@ -1,39 +0,0 @@
{
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation..."
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
}

View File

@@ -1,18 +0,0 @@
{
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailInUse": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"emailSyncError": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
}
}

View File

@@ -1,33 +0,0 @@
{
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version "
}

View File

@@ -0,0 +1,307 @@
{
"auth": {
"loginTitle": "Inloggen bij AliasVault",
"username": "Gebruikersnaam of e-mail",
"usernamePlaceholder": "naam / naam@bedrijf.com",
"password": "Wachtwoord",
"passwordPlaceholder": "Voer je wachtwoord in",
"rememberMe": "Onthoud mij",
"loginButton": "Inloggen",
"noAccount": "Nog geen account?",
"createVault": "Nieuwe vault aanmaken",
"twoFactorTitle": "Voer de authenticatiecode van je authenticator-app in.",
"authCode": "Authenticatiecode",
"authCodePlaceholder": "Voer 6-cijferige code in",
"verify": "Verifiëren",
"cancel": "Annuleren",
"twoFactorNote": "Opmerking: als je geen toegang hebt tot je authenticator, kunt je je 2FA resetten door met een in te loggen via de website.",
"masterPassword": "Hoofdwachtwoord",
"unlockVault": "Vault ontgrendelen",
"unlockTitle": "Ontgrendel je vault",
"unlockDescription": "Voer je hoofdwachtwoord in om je vault te ontgrendelen.",
"logout": "Uitloggen",
"logoutConfirm": "Weet je zeker dat je wilt uitloggen?",
"sessionExpired": "Je sessie is verlopen. Log opnieuw in.",
"unlockSuccess": "Vault succesvol ontgrendeld!",
"unlockSuccessTitle": "Je vault is succesvol ontgrendeld",
"unlockSuccessDescription": "Je kunt nu automatisch invullen gebruiken in inlogformulieren in je browser.",
"closePopup": "Sluit deze popup",
"browseVault": "Bekijk vault-inhoud",
"connectingTo": "Verbinden met",
"loggedIn": "Ingelogd",
"errors": {
"invalidCode": "Voer een geldige 6-cijferige code in.",
"serverError": "Kon de AliasVault server niet bereiken. Probeer het later opnieuw of neem contact op met support als het probleem aanhoudt.",
"noToken": "Inloggen mislukt -- geen token ontvangen",
"migrationError": "Er is een fout opgetreden bij het controleren op updates.",
"wrongPassword": "Onjuist wachtwoord. Probeer het opnieuw.",
"accountLocked": "Account tijdelijk vergrendeld vanwege te veel mislukte pogingen.",
"networkError": "Netwerkfout. Controleer de verbinding en probeer het opnieuw.",
"loginDataMissing": "Loginsessie verlopen. Probeer het opnieuw."
}
},
"menu": {
"credentials": "Inloggegevens",
"emails": "E-mails",
"settings": "Instellingen"
},
"common": {
"appName": "AliasVault",
"loading": "Laden...",
"error": "Fout",
"success": "Succes",
"cancel": "Annuleren",
"delete": "Verwijderen",
"close": "Sluiten",
"copied": "Gekopieerd!",
"openInNewWindow": "Openen in nieuw venster",
"language": "Taal",
"enabled": "Ingeschakeld",
"disabled": "Uitgeschakeld",
"showPassword": "Wachtwoord tonen",
"hidePassword": "Wachtwoord verbergen",
"copyToClipboard": "Naar klembord kopiëren",
"loadingEmails": "E-mails laden...",
"loadingTotpCodes": "TOTP-codes laden...",
"settings": "Instellingen",
"recentEmails": "Recente e-mails",
"loginCredentials": "Inloggegevens",
"twoFactorAuthentication": "Twee-factor authenticatie",
"alias": "Alias",
"notes": "Notities",
"fullName": "Volledige Naam",
"firstName": "Voornaam",
"lastName": "Achternaam",
"birthDate": "Geboortedatum",
"nickname": "Bijnaam",
"email": "E-mail",
"username": "Gebruikersnaam",
"password": "Wachtwoord",
"syncingVault": "Vault synchroniseren",
"savingChangesToVault": "Wijzigingen opslaan in vault",
"uploadingVaultToServer": "Vault uploaden naar server",
"checkingVaultUpdates": "Controleren op vault updates",
"syncingUpdatedVault": "Bijgewerkte vault synchroniseren",
"executingOperation": "Actie uitvoeren...",
"errors": {
"VaultMergeRequired": "Uw vault moet worden bijgewerkt. Log in op de AliasVault website en volg de stappen.",
"VaultOutdated": "Uw vault is verouderd. Log in op de AliasVault website en volg de stappen.",
"NoVaultFound": "Uw account heeft nog geen vault. Voltooi eerst de tutorial in de AliasVault webclient voordat u de browserextensie gebruikt.",
"serverNotAvailable": "De AliasVault server is niet beschikbaar. Probeer het later opnieuw of neem contact op met de ondersteuning als het probleem aanhoudt.",
"clientVersionNotSupported": "Deze versie van de AliasVault browserextensie wordt niet meer ondersteund door de server. Update uw browserextensie naar de nieuwste versie.",
"serverVersionNotSupported": "De AliasVault server moet worden bijgewerkt naar een nieuwere versie om deze browserextensie te kunnen gebruiken. Neem contact op met de ondersteuning als u hulp nodig hebt.",
"unknownError": "Er is een onbekende fout opgetreden",
"failedToStoreVault": "Vault opslaan mislukt",
"vaultNotAvailable": "Vault niet beschikbaar",
"failedToGetVault": "Vault ophalen mislukt",
"vaultIsLocked": "Vault is vergrendeld",
"failedToGetCredentials": "Inloggegevens ophalen mislukt",
"failedToCreateIdentity": "Identiteit aanmaken mislukt",
"failedToGetDefaultEmailDomain": "Standaard e-maildomein ophalen mislukt",
"failedToGetDefaultIdentitySettings": "Standaard identiteitsinstellingen ophalen mislukt",
"failedToGetPasswordSettings": "Wachtwoordinstellingen ophalen mislukt",
"failedToUploadVault": "Vault uploaden mislukt",
"noDerivedKeyAvailable": "Geen afgeleide sleutel beschikbaar voor versleuteling",
"failedToUploadVaultToServer": "Nieuwe vault uploaden naar server mislukt",
"noVaultOrDerivedKeyFound": "Geen vault of afgeleide sleutel gevonden"
},
"apiErrors": {
"UNKNOWN_ERROR": "Er is een onbekende fout opgetreden. Probeer het opnieuw.",
"ACCOUNT_LOCKED": "Account tijdelijk vergrendeld vanwege te veel mislukte pogingen. Probeer het later opnieuw.",
"ACCOUNT_BLOCKED": "Uw account is uitgeschakeld. Als u denkt dat dit een vergissing is, neem dan contact op met de ondersteuning.",
"USER_NOT_FOUND": "Gebruikersnaam of wachtwoord is onjuist. Probeer het opnieuw.",
"INVALID_AUTHENTICATOR_CODE": "Ongeldige authenticatiecode. Probeer het opnieuw.",
"INVALID_RECOVERY_CODE": "Ongeldige herstelcode. Probeer het opnieuw.",
"REFRESH_TOKEN_REQUIRED": "Vernieuwingstoken is vereist.",
"USER_NOT_FOUND_IN_TOKEN": "Gebruiker niet gevonden in token.",
"USER_NOT_FOUND_IN_DATABASE": "Gebruiker niet gevonden in database.",
"INVALID_REFRESH_TOKEN": "Ongeldig vernieuwingstoken.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Vernieuwingstoken succesvol ingetrokken.",
"PUBLIC_REGISTRATION_DISABLED": "Registratie van nieuwe accounts is momenteel uitgeschakeld op deze server. Neem contact op met de beheerder.",
"USERNAME_REQUIRED": "Gebruikersnaam is vereist.",
"USERNAME_ALREADY_IN_USE": "Gebruikersnaam is al in gebruik.",
"USERNAME_AVAILABLE": "Gebruikersnaam is beschikbaar.",
"USERNAME_MISMATCH": "Gebruikersnaam komt niet overeen met de huidige gebruiker.",
"PASSWORD_MISMATCH": "Het opgegeven wachtwoord komt niet overeen met uw huidige wachtwoord.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account succesvol verwijderd.",
"USERNAME_EMPTY_OR_WHITESPACE": "Gebruikersnaam mag niet leeg zijn of alleen uit spaties bestaan.",
"USERNAME_TOO_SHORT": "Gebruikersnaam te kort: moet minimaal 3 tekens lang zijn.",
"USERNAME_TOO_LONG": "Gebruikersnaam te lang: mag niet langer zijn dan 40 tekens.",
"USERNAME_ADMIN_NOT_ALLOWED": "Gebruikersnaam 'admin' is niet toegestaan.",
"USERNAME_INVALID_EMAIL": "Ongeldig e-mailadres.",
"USERNAME_INVALID_CHARACTERS": "Gebruikersnaam is ongeldig, mag alleen letters of cijfers bevatten.",
"VAULT_NOT_UP_TO_DATE": "Uw kluis is niet up-to-date. Synchroniseer uw kluis en probeer het opnieuw.",
"INTERNAL_SERVER_ERROR": "Interne serverfout.",
"VAULT_ERROR": "De lokale kluis is niet up-to-date. Synchroniseer uw kluis door de pagina te vernieuwen en probeer het opnieuw."
}
},
"content": {
"new": "Nieuw",
"cancel": "Annuleren",
"search": "Zoeken",
"vaultLocked": "AliasVault is vergrendeld.",
"creatingNewAlias": "Nieuwe alias aanmaken...",
"noMatchesFound": "Geen resultaten gevonden",
"searchVault": "Kluis doorzoeken...",
"serviceName": "Servicenaam",
"email": "E-mail",
"username": "Gebruikersnaam",
"generatedPassword": "Gegenereerd wachtwoord",
"enterServiceName": "Voer servicenaam in",
"enterEmailAddress": "Voer e-mailadres in",
"enterUsername": "Voer gebruikersnaam in",
"hideFor1Hour": "Verberg voor 1 uur (huidige site)",
"hidePermanently": "Permanent verbergen (huidige site)",
"createRandomAlias": "Willekeurige alias aanmaken",
"createUsernamePassword": "Gebruikersnaam/wachtwoord aanmaken",
"randomAlias": "Willekeurige alias",
"usernamePassword": "Gebruikersnaam/wachtwoord",
"createAndSaveAlias": "Alias aanmaken en opslaan",
"createAndSaveCredential": "Inloggegevens aanmaken en opslaan",
"randomIdentityDescription": "Genereer een willekeurige identiteit met een willekeurig e-mailadres toegankelijk in AliasVault.",
"manualCredentialDescription": "Specificeer je eigen e-mailadres en gebruikersnaam.",
"failedToCreateIdentity": "Identiteit aanmaken mislukt. Probeer opnieuw.",
"enterEmailAndOrUsername": "Voer e-mail en/of gebruikersnaam in",
"autofillWithAliasVault": "Autofill met AliasVault",
"generateRandomPassword": "Willekeurig wachtwoord genereren (kopiëren naar klembord)",
"passwordCopiedToClipboard": "Wachtwoord gekopieerd naar klembord"
},
"credentials": {
"title": "Credentials",
"addCredential": "Inloggegevens toevoegen",
"editCredential": "Credential bewerken",
"deleteCredential": "Credential verwijderen",
"credentialDetails": "Credential details",
"serviceName": "Naam dienst",
"serviceNamePlaceholder": "bijv. Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://voorbeeld.nl",
"username": "Gebruikersnaam",
"usernamePlaceholder": "Voer gebruikersnaam in",
"password": "Wachtwoord",
"passwordPlaceholder": "Voer wachtwoord in",
"generatePassword": "Wachtwoord genereren",
"copyPassword": "Wachtwoord kopiëren",
"showPassword": "Wachtwoord tonen",
"hidePassword": "Wachtwoord verbergen",
"notes": "Notities",
"notesPlaceholder": "Aanvullende notities...",
"totp": "Twee-factor-authenticatie",
"totpCode": "TOTP-code",
"copyTotp": "Kopiëren",
"totpSecret": "TOTP-sleutel",
"totpSecretPlaceholder": "Voer TOTP-secret key in",
"noCredentials": "Geen credentials gevonden",
"noCredentialsDescription": "Voeg je eerste credentials toe om te beginnen",
"searchCredentials": "Zoek credentials...",
"searchPlaceholder": "Credentials zoeken...",
"welcomeTitle": "Welkom bij AliasVault!",
"welcomeDescription": "Om de AliasVault browser extensie te gebruiken: navigeer naar een website en gebruik de AliasVault autofill popup om nieuwe credentials aan te maken.",
"manualCreationHint": "Als je handmatig identiteiten wilt aanmaken, open dan de volledige AliasVault app via het uitklapicoon in de rechterbovenhoek.",
"lastUsed": "Laatst gebruikt",
"createdAt": "Aangemaakt",
"updatedAt": "Laatst bijgewerkt",
"autofill": "Autofill",
"fillForm": "Formulier invullen",
"copyUsername": "Gebruikersnaam kopiëren",
"openWebsite": "Website openen",
"favorite": "Favoriet",
"unfavorite": "Uit favorieten verwijderen",
"deleteConfirm": "Weet u zeker dat u deze credential wilt verwijderen?",
"deleteSuccess": "Credential succesvol verwijderd",
"saveSuccess": "Credential succesvol opgeslagen",
"copySuccess": "Gekopieerd naar klembord",
"tags": "Labels",
"addTag": "Label toevoegen",
"removeTag": "Label verwijderen",
"folder": "Map",
"selectFolder": "Map selecteren",
"createFolder": "Map aanmaken",
"saveCredential": "Credential opslaan",
"deleteCredentialTitle": "Credential verwijderen",
"deleteCredentialConfirm": "Weet je zeker dat je deze credential wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
"randomAlias": "Willekeurige alias",
"manual": "Handmatig",
"service": "Naam van dienst",
"serviceUrl": "URL",
"loginCredentials": "Inloggegevens",
"generateRandomUsername": "Gebruikersnaam genereren",
"generateRandomPassword": "Wachtwoord genereren",
"generateRandomAlias": "Alias genereren",
"alias": "Alias",
"firstName": "Voornaam",
"lastName": "Achternaam",
"nickName": "Bijnaam",
"gender": "Geslacht",
"birthDate": "Geboortedatum",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Servicenaam is verplicht",
"invalidUrl": "Voer een geldige URL in",
"saveError": "Credential opslaan mislukt",
"loadError": "Credential laden mislukt",
"deleteError": "Credential verwijderen mislukt",
"copyError": "Kopiëren naar klembord mislukt"
}
},
"emails": {
"title": "E-mail details",
"deleteEmailTitle": "E-mail Verwijderen",
"deleteEmailConfirm": "Weet u zeker dat u deze e-mail definitief wilt verwijderen?",
"from": "Van",
"to": "Naar",
"date": "Datum",
"emailContent": "E-mailinhoud",
"attachments": "Bijlagen",
"emailNotFound": "E-mail niet gevonden",
"noEmails": "Geen e-mails gevonden",
"errors": {
"emailLoadError": "Er is een fout opgetreden bij het laden van e-mails. Probeer het later opnieuw.",
"emailUnexpectedError": "Er is een onverwachte fout opgetreden bij het laden van e-mails. Probeer het later opnieuw."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "Het huidige gekozen e-mailadres is al in gebruik. Wijzig het e-mailadres door deze credential te bewerken.",
"CLAIM_DOES_NOT_EXIST": "Er is een fout opgetreden bij het laden van e-mails. Probeer de credential te bewerken en op te slaan om de database te synchroniseren, en probeer het opnieuw."
}
},
"settings": {
"title": "Instellingen",
"serverUrl": "Server URL",
"language": "Taal",
"autofillEnabled": "Autofill",
"version": "Versie",
"openInNewWindow": "Openen in nieuw venster",
"openWebApp": "Web-app openen",
"loggedIn": "Ingelogd",
"logout": "Uitloggen",
"globalSettings": "Globale Instellingen",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Actief voor alle sites (tenzij hieronder uitgeschakeld)",
"disabledOnAllSites": "Uitgeschakeld op alle sites",
"enabled": "Ingeschakeld",
"disabled": "Uitgeschakeld",
"rightClickContextMenu": "Rechts-klik contextmenu",
"siteSpecificSettings": "Site-specifieke Instellingen",
"autofillPopupOn": "Autofill popup op: ",
"enabledForThisSite": "Ingeschakeld voor deze site",
"disabledForThisSite": "Uitgeschakeld voor deze site",
"temporarilyDisabledUntil": "Tijdelijk uitgeschakeld tot ",
"resetAllSiteSettings": "Alle site-specifieke instellingen resetten",
"appearance": "Uiterlijk",
"theme": "Thema",
"useDefault": "Standaard gebruiken",
"light": "Licht",
"dark": "Donker",
"keyboardShortcuts": "Snelkoppelingen",
"configureKeyboardShortcuts": "Snelkoppelingen configureren",
"configure": "Configureren",
"versionPrefix": "Versie ",
"validation": {
"apiUrlRequired": "API URL is vereist",
"apiUrlInvalid": "Voer een geldige API URL in",
"clientUrlRequired": "Client URL is vereist",
"clientUrlInvalid": "Voer een geldige client URL in"
}
}
}

View File

@@ -1,41 +0,0 @@
{
"loginTitle": "Inloggen bij AliasVault",
"username": "Gebruikersnaam of e-mail",
"usernamePlaceholder": "naam / naam@bedrijf.com",
"password": "Wachtwoord",
"passwordPlaceholder": "Voer je wachtwoord in",
"rememberMe": "Onthoud mij",
"loginButton": "Inloggen",
"noAccount": "Nog geen account?",
"createVault": "Nieuwe vault aanmaken",
"twoFactorTitle": "Voer de authenticatiecode van je authenticator-app in.",
"authCode": "Authenticatiecode",
"authCodePlaceholder": "Voer 6-cijferige code in",
"verify": "Verifiëren",
"cancel": "Annuleren",
"twoFactorNote": "Opmerking: als je geen toegang hebt tot je authenticator, kunt je je 2FA resetten door met een in te loggen via de website.",
"masterPassword": "Hoofdwachtwoord",
"unlockVault": "Vault ontgrendelen",
"unlockTitle": "Ontgrendel je vault",
"unlockDescription": "Voer je hoofdwachtwoord in om je vault te ontgrendelen.",
"logout": "Uitloggen",
"logoutConfirm": "Weet je zeker dat je wilt uitloggen?",
"sessionExpired": "Je sessie is verlopen. Log opnieuw in.",
"unlockSuccess": "Vault succesvol ontgrendeld!",
"unlockSuccessTitle": "Je vault is succesvol ontgrendeld",
"unlockSuccessDescription": "Je kunt nu automatisch invullen gebruiken in inlogformulieren in je browser.",
"closePopup": "Sluit deze popup",
"browseVault": "Bekijk vault-inhoud",
"connectingTo": "Verbinden met",
"loggedIn": "Ingelogd",
"errors": {
"invalidCode": "Voer een geldige 6-cijferige code in.",
"serverError": "Kon de AliasVault server niet bereiken. Probeer het later opnieuw of neem contact op met support als het probleem aanhoudt.",
"noToken": "Inloggen mislukt -- geen token ontvangen",
"migrationError": "Er is een fout opgetreden bij het controleren op updates.",
"wrongPassword": "Onjuist wachtwoord. Probeer het opnieuw.",
"accountLocked": "Account tijdelijk vergrendeld vanwege te veel mislukte pogingen.",
"networkError": "Netwerkfout. Controleer de verbinding en probeer het opnieuw.",
"loginDataMissing": "Loginsessie verlopen. Probeer het opnieuw."
}
}

View File

@@ -1,90 +0,0 @@
{
"appName": "AliasVault",
"loading": "Laden...",
"error": "Fout",
"success": "Succes",
"cancel": "Annuleren",
"delete": "Verwijderen",
"close": "Sluiten",
"copied": "Gekopieerd!",
"openInNewWindow": "Openen in nieuw venster",
"language": "Taal",
"enabled": "Ingeschakeld",
"disabled": "Uitgeschakeld",
"showPassword": "Wachtwoord tonen",
"hidePassword": "Wachtwoord verbergen",
"copyToClipboard": "Naar klembord kopiëren",
"loadingEmails": "E-mails laden...",
"loadingTotpCodes": "TOTP-codes laden...",
"settings": "Instellingen",
"recentEmails": "Recente e-mails",
"loginCredentials": "Inloggegevens",
"twoFactorAuthentication": "Twee-factor authenticatie",
"alias": "Alias",
"notes": "Notities",
"fullName": "Volledige Naam",
"firstName": "Voornaam",
"lastName": "Achternaam",
"birthDate": "Geboortedatum",
"nickname": "Bijnaam",
"email": "E-mail",
"username": "Gebruikersnaam",
"password": "Wachtwoord",
"syncingVault": "Vault synchroniseren",
"savingChangesToVault": "Wijzigingen opslaan in vault",
"uploadingVaultToServer": "Vault uploaden naar server",
"checkingVaultUpdates": "Controleren op vault updates",
"syncingUpdatedVault": "Bijgewerkte vault synchroniseren",
"executingOperation": "Actie uitvoeren...",
"errors": {
"VaultMergeRequired": "Uw vault moet worden bijgewerkt. Log in op de AliasVault website en volg de stappen.",
"VaultOutdated": "Uw vault is verouderd. Log in op de AliasVault website en volg de stappen.",
"NoVaultFound": "Uw account heeft nog geen vault. Voltooi eerst de tutorial in de AliasVault webclient voordat u de browserextensie gebruikt.",
"serverNotAvailable": "De AliasVault server is niet beschikbaar. Probeer het later opnieuw of neem contact op met de ondersteuning als het probleem aanhoudt.",
"clientVersionNotSupported": "Deze versie van de AliasVault browserextensie wordt niet meer ondersteund door de server. Update uw browserextensie naar de nieuwste versie.",
"serverVersionNotSupported": "De AliasVault server moet worden bijgewerkt naar een nieuwere versie om deze browserextensie te kunnen gebruiken. Neem contact op met de ondersteuning als u hulp nodig hebt.",
"unknownError": "Er is een onbekende fout opgetreden",
"failedToStoreVault": "Vault opslaan mislukt",
"vaultNotAvailable": "Vault niet beschikbaar",
"failedToGetVault": "Vault ophalen mislukt",
"vaultIsLocked": "Vault is vergrendeld",
"failedToGetCredentials": "Inloggegevens ophalen mislukt",
"failedToCreateIdentity": "Identiteit aanmaken mislukt",
"failedToGetDefaultEmailDomain": "Standaard e-maildomein ophalen mislukt",
"failedToGetDefaultIdentitySettings": "Standaard identiteitsinstellingen ophalen mislukt",
"failedToGetPasswordSettings": "Wachtwoordinstellingen ophalen mislukt",
"failedToUploadVault": "Vault uploaden mislukt",
"noDerivedKeyAvailable": "Geen afgeleide sleutel beschikbaar voor versleuteling",
"failedToUploadVaultToServer": "Nieuwe vault uploaden naar server mislukt",
"noVaultOrDerivedKeyFound": "Geen vault of afgeleide sleutel gevonden"
},
"apiErrors": {
"UNKNOWN_ERROR": "Er is een onbekende fout opgetreden. Probeer het opnieuw.",
"ACCOUNT_LOCKED": "Account tijdelijk vergrendeld vanwege te veel mislukte pogingen. Probeer het later opnieuw.",
"ACCOUNT_BLOCKED": "Uw account is uitgeschakeld. Als u denkt dat dit een vergissing is, neem dan contact op met de ondersteuning.",
"USER_NOT_FOUND": "Gebruikersnaam of wachtwoord is onjuist. Probeer het opnieuw.",
"INVALID_AUTHENTICATOR_CODE": "Ongeldige authenticatiecode. Probeer het opnieuw.",
"INVALID_RECOVERY_CODE": "Ongeldige herstelcode. Probeer het opnieuw.",
"REFRESH_TOKEN_REQUIRED": "Vernieuwingstoken is vereist.",
"USER_NOT_FOUND_IN_TOKEN": "Gebruiker niet gevonden in token.",
"USER_NOT_FOUND_IN_DATABASE": "Gebruiker niet gevonden in database.",
"INVALID_REFRESH_TOKEN": "Ongeldig vernieuwingstoken.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Vernieuwingstoken succesvol ingetrokken.",
"PUBLIC_REGISTRATION_DISABLED": "Registratie van nieuwe accounts is momenteel uitgeschakeld op deze server. Neem contact op met de beheerder.",
"USERNAME_REQUIRED": "Gebruikersnaam is vereist.",
"USERNAME_ALREADY_IN_USE": "Gebruikersnaam is al in gebruik.",
"USERNAME_AVAILABLE": "Gebruikersnaam is beschikbaar.",
"USERNAME_MISMATCH": "Gebruikersnaam komt niet overeen met de huidige gebruiker.",
"PASSWORD_MISMATCH": "Het opgegeven wachtwoord komt niet overeen met uw huidige wachtwoord.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account succesvol verwijderd.",
"USERNAME_EMPTY_OR_WHITESPACE": "Gebruikersnaam mag niet leeg zijn of alleen uit spaties bestaan.",
"USERNAME_TOO_SHORT": "Gebruikersnaam te kort: moet minimaal 3 tekens lang zijn.",
"USERNAME_TOO_LONG": "Gebruikersnaam te lang: mag niet langer zijn dan 40 tekens.",
"USERNAME_ADMIN_NOT_ALLOWED": "Gebruikersnaam 'admin' is niet toegestaan.",
"USERNAME_INVALID_EMAIL": "Ongeldig e-mailadres.",
"USERNAME_INVALID_CHARACTERS": "Gebruikersnaam is ongeldig, mag alleen letters of cijfers bevatten.",
"VAULT_NOT_UP_TO_DATE": "Uw kluis is niet up-to-date. Synchroniseer uw kluis en probeer het opnieuw.",
"INTERNAL_SERVER_ERROR": "Interne serverfout.",
"VAULT_ERROR": "De lokale kluis is niet up-to-date. Synchroniseer uw kluis door de pagina te vernieuwen en probeer het opnieuw."
}
}

View File

@@ -1,31 +0,0 @@
{
"new": "Nieuw",
"cancel": "Annuleren",
"search": "Zoeken",
"vaultLocked": "AliasVault is vergrendeld.",
"creatingNewAlias": "Nieuwe alias aanmaken...",
"noMatchesFound": "Geen resultaten gevonden",
"searchVault": "Kluis doorzoeken...",
"serviceName": "Servicenaam",
"email": "E-mail",
"username": "Gebruikersnaam",
"generatedPassword": "Gegenereerd wachtwoord",
"enterServiceName": "Voer servicenaam in",
"enterEmailAddress": "Voer e-mailadres in",
"enterUsername": "Voer gebruikersnaam in",
"hideFor1Hour": "Verberg voor 1 uur (huidige site)",
"hidePermanently": "Permanent verbergen (huidige site)",
"createRandomAlias": "Willekeurige alias aanmaken",
"createUsernamePassword": "Gebruikersnaam/wachtwoord aanmaken",
"randomAlias": "Willekeurige alias",
"usernamePassword": "Gebruikersnaam/wachtwoord",
"createAndSaveAlias": "Alias aanmaken en opslaan",
"createAndSaveCredential": "Inloggegevens aanmaken en opslaan",
"randomIdentityDescription": "Genereer een willekeurige identiteit met een willekeurig e-mailadres toegankelijk in AliasVault.",
"manualCredentialDescription": "Specificeer je eigen e-mailadres en gebruikersnaam.",
"failedToCreateIdentity": "Identiteit aanmaken mislukt. Probeer opnieuw.",
"enterEmailAndOrUsername": "Voer e-mail en/of gebruikersnaam in",
"autofillWithAliasVault": "Autofill met AliasVault",
"generateRandomPassword": "Willekeurig wachtwoord genereren (kopiëren naar klembord)",
"passwordCopiedToClipboard": "Wachtwoord gekopieerd naar klembord"
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Inloggegevens toevoegen",
"editCredential": "Credential bewerken",
"deleteCredential": "Credential verwijderen",
"credentialDetails": "Credential details",
"serviceName": "Naam dienst",
"serviceNamePlaceholder": "bijv. Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://voorbeeld.nl",
"username": "Gebruikersnaam",
"usernamePlaceholder": "Voer gebruikersnaam in",
"password": "Wachtwoord",
"passwordPlaceholder": "Voer wachtwoord in",
"generatePassword": "Wachtwoord genereren",
"copyPassword": "Wachtwoord kopiëren",
"showPassword": "Wachtwoord tonen",
"hidePassword": "Wachtwoord verbergen",
"notes": "Notities",
"notesPlaceholder": "Aanvullende notities...",
"totp": "Twee-factor-authenticatie",
"totpCode": "TOTP-code",
"copyTotp": "Kopiëren",
"totpSecret": "TOTP-sleutel",
"totpSecretPlaceholder": "Voer TOTP-secret key in",
"noCredentials": "Geen credentials gevonden",
"noCredentialsDescription": "Voeg je eerste credentials toe om te beginnen",
"searchCredentials": "Zoek credentials...",
"searchPlaceholder": "Credentials zoeken...",
"welcomeTitle": "Welkom bij AliasVault!",
"welcomeDescription": "Om de AliasVault browser extensie te gebruiken: navigeer naar een website en gebruik de AliasVault autofill popup om nieuwe credentials aan te maken.",
"manualCreationHint": "Als je handmatig identiteiten wilt aanmaken, open dan de volledige AliasVault app via het uitklapicoon in de rechterbovenhoek.",
"lastUsed": "Laatst gebruikt",
"createdAt": "Aangemaakt",
"updatedAt": "Laatst bijgewerkt",
"autofill": "Autofill",
"fillForm": "Formulier invullen",
"copyUsername": "Gebruikersnaam kopiëren",
"openWebsite": "Website openen",
"favorite": "Favoriet",
"unfavorite": "Uit favorieten verwijderen",
"deleteConfirm": "Weet u zeker dat u deze credential wilt verwijderen?",
"deleteSuccess": "Credential succesvol verwijderd",
"saveSuccess": "Credential succesvol opgeslagen",
"copySuccess": "Gekopieerd naar klembord",
"tags": "Labels",
"addTag": "Label toevoegen",
"removeTag": "Label verwijderen",
"folder": "Map",
"selectFolder": "Map selecteren",
"createFolder": "Map aanmaken",
"saveCredential": "Credential opslaan",
"deleteCredentialTitle": "Credential verwijderen",
"deleteCredentialConfirm": "Weet je zeker dat je deze credential wilt verwijderen? Deze actie kan niet ongedaan worden gemaakt.",
"randomAlias": "Willekeurige alias",
"manual": "Handmatig",
"service": "Naam van dienst",
"serviceUrl": "URL",
"loginCredentials": "Inloggegevens",
"generateRandomUsername": "Gebruikersnaam genereren",
"generateRandomPassword": "Wachtwoord genereren",
"generateRandomAlias": "Alias genereren",
"alias": "Alias",
"firstName": "Voornaam",
"lastName": "Achternaam",
"nickName": "Bijnaam",
"gender": "Geslacht",
"birthDate": "Geboortedatum",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Servicenaam is verplicht",
"invalidUrl": "Voer een geldige URL in",
"saveError": "Credential opslaan mislukt",
"loadError": "Credential laden mislukt",
"deleteError": "Credential verwijderen mislukt",
"copyError": "Kopiëren naar klembord mislukt"
}
}

View File

@@ -1,20 +0,0 @@
{
"title": "E-mail details",
"deleteEmailTitle": "E-mail Verwijderen",
"deleteEmailConfirm": "Weet u zeker dat u deze e-mail definitief wilt verwijderen?",
"from": "Van",
"to": "Naar",
"date": "Datum",
"emailContent": "E-mailinhoud",
"attachments": "Bijlagen",
"emailNotFound": "E-mail niet gevonden",
"noEmails": "Geen e-mails gevonden",
"errors": {
"emailLoadError": "Er is een fout opgetreden bij het laden van e-mails. Probeer het later opnieuw.",
"emailUnexpectedError": "Er is een onverwachte fout opgetreden bij het laden van e-mails. Probeer het later opnieuw."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "Het huidige gekozen e-mailadres is al in gebruik. Wijzig het e-mailadres door deze credential te bewerken.",
"CLAIM_DOES_NOT_EXIST": "Er is een fout opgetreden bij het laden van e-mails. Probeer de credential te bewerken en op te slaan om de database te synchroniseren, en probeer het opnieuw."
}
}

View File

@@ -1,39 +0,0 @@
{
"title": "Instellingen",
"serverUrl": "Server URL",
"language": "Taal",
"autofillEnabled": "Autofill",
"version": "Versie",
"openInNewWindow": "Openen in nieuw venster",
"openWebApp": "Web-app openen",
"loggedIn": "Ingelogd",
"logout": "Uitloggen",
"globalSettings": "Globale Instellingen",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Actief voor alle sites (tenzij hieronder uitgeschakeld)",
"disabledOnAllSites": "Uitgeschakeld op alle sites",
"enabled": "Ingeschakeld",
"disabled": "Uitgeschakeld",
"rightClickContextMenu": "Rechts-klik contextmenu",
"siteSpecificSettings": "Site-specifieke Instellingen",
"autofillPopupOn": "Autofill popup op: ",
"enabledForThisSite": "Ingeschakeld voor deze site",
"disabledForThisSite": "Uitgeschakeld voor deze site",
"temporarilyDisabledUntil": "Tijdelijk uitgeschakeld tot ",
"resetAllSiteSettings": "Alle site-specifieke instellingen resetten",
"appearance": "Uiterlijk",
"theme": "Thema",
"useDefault": "Standaard gebruiken",
"light": "Licht",
"dark": "Donker",
"keyboardShortcuts": "Snelkoppelingen",
"configureKeyboardShortcuts": "Snelkoppelingen configureren",
"configure": "Configureren",
"versionPrefix": "Versie ",
"validation": {
"apiUrlRequired": "API URL is vereist",
"apiUrlInvalid": "Voer een geldige API URL in",
"clientUrlRequired": "Client URL is vereist",
"clientUrlInvalid": "Voer een geldige client URL in"
}
}

View File

@@ -0,0 +1,316 @@
{
"auth": {
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"unlockSuccessTitle": "Your vault is successfully unlocked",
"unlockSuccessDescription": "You can now use autofill in login forms in your browser.",
"closePopup": "Close this popup",
"browseVault": "Browse vault contents",
"connectingTo": "Connecting to",
"switchAccounts": "Switch accounts?",
"loggedIn": "Logged in",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again.",
"loginDataMissing": "Login session expired. Please try again."
}
},
"menu": {
"credentials": "Credentials",
"emails": "Emails",
"settings": "Settings"
},
"common": {
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation...",
"errors": {
"VaultMergeRequired": "Your vault needs to be updated. Please login on the AliasVault website and follow the steps.",
"VaultOutdated": "Your vault is outdated. Please login on the AliasVault website and follow the steps.",
"NoVaultFound": "Your account does not have a vault yet. Please complete the tutorial in the AliasVault web client before using the browser extension.",
"serverNotAvailable": "The AliasVault server is not available. Please try again later or contact support if the problem persists.",
"clientVersionNotSupported": "This version of the AliasVault browser extension is not supported by the server anymore. Please update your browser extension to the latest version.",
"serverVersionNotSupported": "The AliasVault server needs to be updated to a newer version in order to use this browser extension. Please contact support if you need help.",
"unknownError": "An unknown error occurred",
"failedToStoreVault": "Failed to store vault",
"vaultNotAvailable": "Vault not available",
"failedToGetVault": "Failed to get vault",
"vaultIsLocked": "Vault is locked",
"failedToGetCredentials": "Failed to get credentials",
"failedToCreateIdentity": "Failed to create identity",
"failedToGetDefaultEmailDomain": "Failed to get default email domain",
"failedToGetDefaultIdentitySettings": "Failed to get default identity settings",
"failedToGetPasswordSettings": "Failed to get password settings",
"failedToUploadVault": "Failed to upload vault",
"noDerivedKeyAvailable": "No derived key available for encryption",
"failedToUploadVaultToServer": "Failed to upload new vault to server",
"noVaultOrDerivedKeyFound": "No vault or derived key found"
},
"apiErrors": {
"UNKNOWN_ERROR": "An unknown error occurred. Please try again.",
"ACCOUNT_LOCKED": "Account temporarily locked due to too many failed attempts. Please try again later.",
"ACCOUNT_BLOCKED": "Your account has been disabled. If you believe this is a mistake, please contact support.",
"USER_NOT_FOUND": "Invalid username or password. Please try again.",
"INVALID_AUTHENTICATOR_CODE": "Invalid authenticator code. Please try again.",
"INVALID_RECOVERY_CODE": "Invalid recovery code. Please try again.",
"REFRESH_TOKEN_REQUIRED": "Refresh token is required.",
"USER_NOT_FOUND_IN_TOKEN": "User not found in token.",
"USER_NOT_FOUND_IN_DATABASE": "User not found in database.",
"INVALID_REFRESH_TOKEN": "Invalid refresh token.",
"REFRESH_TOKEN_REVOKED_SUCCESSFULLY": "Refresh token revoked successfully.",
"PUBLIC_REGISTRATION_DISABLED": "New account registration is currently disabled on this server. Please contact the administrator.",
"USERNAME_REQUIRED": "Username is required.",
"USERNAME_ALREADY_IN_USE": "Username is already in use.",
"USERNAME_AVAILABLE": "Username is available.",
"USERNAME_MISMATCH": "Username does not match the current user.",
"PASSWORD_MISMATCH": "The provided password does not match your current password.",
"ACCOUNT_SUCCESSFULLY_DELETED": "Account successfully deleted.",
"USERNAME_EMPTY_OR_WHITESPACE": "Username cannot be empty or whitespace.",
"USERNAME_TOO_SHORT": "Username too short: must be at least 3 characters long.",
"USERNAME_TOO_LONG": "Username too long: cannot be longer than 40 characters.",
"USERNAME_ADMIN_NOT_ALLOWED": "Username 'admin' is not allowed.",
"USERNAME_INVALID_EMAIL": "Invalid email address.",
"USERNAME_INVALID_CHARACTERS": "Username is invalid, can only contain letters or digits.",
"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."
}
},
"content": {
"new": "New",
"cancel": "Cancel",
"search": "Search",
"vaultLocked": "AliasVault is locked.",
"creatingNewAlias": "Creating new alias...",
"noMatchesFound": "No matches found",
"searchVault": "Search vault...",
"serviceName": "Service name",
"email": "Email",
"username": "Username",
"generatedPassword": "Generated Password",
"enterServiceName": "Enter service name",
"enterEmailAddress": "Enter email address",
"enterUsername": "Enter username",
"hideFor1Hour": "Hide for 1 hour (current site)",
"hidePermanently": "Hide permanently (current site)",
"createRandomAlias": "Create random alias",
"createUsernamePassword": "Create username/password",
"randomAlias": "Random alias",
"usernamePassword": "Username/password",
"createAndSaveAlias": "Create and save alias",
"createAndSaveCredential": "Create and save credential",
"randomIdentityDescription": "Generate a random identity with a random email address accessible in AliasVault.",
"randomIdentityDescriptionDropdown": "Random identity with random email",
"manualCredentialDescription": "Specify your own email address and username.",
"manualCredentialDescriptionDropdown": "Manual username and password",
"failedToCreateIdentity": "Failed to create identity. Please try again.",
"enterEmailAndOrUsername": "Enter email and/or username",
"autofillWithAliasVault": "Autofill with AliasVault",
"generateRandomPassword": "Generate random password (copy to clipboard)",
"generateNewPassword": "Generate new password",
"togglePasswordVisibility": "Toggle password visibility",
"passwordCopiedToClipboard": "Password copied to clipboard",
"enterEmailAndOrUsernameError": "Enter email and/or username",
"openAliasVaultToUpgrade": "Open AliasVault to upgrade",
"vaultUpgradeRequired": "Vault upgrade required.",
"dismissPopup": "Dismiss popup"
},
"credentials": {
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
},
"emails": {
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
},
"apiErrors": {
"CLAIM_DOES_NOT_MATCH_USER": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"CLAIM_DOES_NOT_EXIST": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again."
}
},
"settings": {
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version ",
"validation": {
"apiUrlRequired": "API URL is required",
"apiUrlInvalid": "Please enter a valid API URL",
"clientUrlRequired": "Client URL is required",
"clientUrlInvalid": "Please enter a valid client URL"
}
}
}

View File

@@ -1,35 +0,0 @@
{
"loginTitle": "Log in to AliasVault",
"username": "Username or email",
"usernamePlaceholder": "name / name@company.com",
"password": "Password",
"passwordPlaceholder": "Enter your password",
"rememberMe": "Remember me",
"loginButton": "Login",
"noAccount": "No account yet?",
"createVault": "Create new vault",
"twoFactorTitle": "Please enter the authentication code from your authenticator app.",
"authCode": "Authentication Code",
"authCodePlaceholder": "Enter 6-digit code",
"verify": "Verify",
"cancel": "Cancel",
"twoFactorNote": "Note: if you don't have access to your authenticator device, you can reset your 2FA with a recovery code by logging in via the website.",
"masterPassword": "Master Password",
"unlockVault": "Unlock Vault",
"unlockTitle": "Unlock Your Vault",
"unlockDescription": "Enter your master password to unlock your vault.",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to logout?",
"sessionExpired": "Your session has expired. Please log in again.",
"unlockSuccess": "Vault unlocked successfully!",
"connectingTo": "Connecting to",
"errors": {
"invalidCode": "Please enter a valid 6-digit authentication code.",
"serverError": "Could not reach AliasVault server. Please try again later or contact support if the problem persists.",
"noToken": "Login failed -- no token returned",
"migrationError": "An error occurred while checking for pending migrations.",
"wrongPassword": "Incorrect password. Please try again.",
"accountLocked": "Account temporarily locked due to too many failed attempts.",
"networkError": "Network error. Please check your connection and try again."
}
}

View File

@@ -1,39 +0,0 @@
{
"appName": "AliasVault",
"loading": "Loading...",
"error": "Error",
"success": "Success",
"cancel": "Cancel",
"delete": "Delete",
"close": "Close",
"copied": "Copied!",
"openInNewWindow": "Open in new window",
"language": "Language",
"enabled": "Enabled",
"disabled": "Disabled",
"showPassword": "Show password",
"hidePassword": "Hide password",
"copyToClipboard": "Copy to clipboard",
"loadingEmails": "Loading emails...",
"loadingTotpCodes": "Loading TOTP codes...",
"settings": "Settings",
"recentEmails": "Recent emails",
"loginCredentials": "Login credentials",
"twoFactorAuthentication": "Two-factor authentication",
"alias": "Alias",
"notes": "Notes",
"fullName": "Full Name",
"firstName": "First Name",
"lastName": "Last Name",
"birthDate": "Birth Date",
"nickname": "Nickname",
"email": "Email",
"username": "Username",
"password": "Password",
"syncingVault": "Syncing vault",
"savingChangesToVault": "Saving changes to vault",
"uploadingVaultToServer": "Uploading vault to server",
"checkingVaultUpdates": "Checking for vault updates",
"syncingUpdatedVault": "Syncing updated vault",
"executingOperation": "Executing operation..."
}

View File

@@ -1,79 +0,0 @@
{
"title": "Credentials",
"addCredential": "Add Credential",
"editCredential": "Edit Credential",
"deleteCredential": "Delete Credential",
"credentialDetails": "Credential Details",
"serviceName": "Service Name",
"serviceNamePlaceholder": "e.g., Gmail, Facebook, Bank",
"website": "Website",
"websitePlaceholder": "https://example.com",
"username": "Username",
"usernamePlaceholder": "Enter username",
"password": "Password",
"passwordPlaceholder": "Enter password",
"generatePassword": "Generate Password",
"copyPassword": "Copy Password",
"showPassword": "Show Password",
"hidePassword": "Hide Password",
"notes": "Notes",
"notesPlaceholder": "Additional notes...",
"totp": "Two-Factor Authentication",
"totpCode": "TOTP Code",
"copyTotp": "Copy TOTP",
"totpSecret": "TOTP Secret",
"totpSecretPlaceholder": "Enter TOTP secret key",
"noCredentials": "No credentials found",
"noCredentialsDescription": "Add your first credential to get started",
"searchCredentials": "Search credentials...",
"searchPlaceholder": "Search credentials...",
"welcomeTitle": "Welcome to AliasVault!",
"welcomeDescription": "To use the AliasVault browser extension: navigate to a website and use the AliasVault autofill popup to create a new credential.",
"manualCreationHint": "If you want to create manual identities, open the full AliasVault app via the popout icon in the top right corner.",
"lastUsed": "Last used",
"createdAt": "Created",
"updatedAt": "Last updated",
"autofill": "Autofill",
"fillForm": "Fill Form",
"copyUsername": "Copy Username",
"openWebsite": "Open Website",
"favorite": "Favorite",
"unfavorite": "Remove from Favorites",
"deleteConfirm": "Are you sure you want to delete this credential?",
"deleteSuccess": "Credential deleted successfully",
"saveSuccess": "Credential saved successfully",
"copySuccess": "Copied to clipboard",
"tags": "Tags",
"addTag": "Add Tag",
"removeTag": "Remove Tag",
"folder": "Folder",
"selectFolder": "Select Folder",
"createFolder": "Create Folder",
"saveCredential": "Save credential",
"deleteCredentialTitle": "Delete Credential",
"deleteCredentialConfirm": "Are you sure you want to delete this credential? This action cannot be undone.",
"randomAlias": "Random Alias",
"manual": "Manual",
"service": "Service",
"serviceUrl": "Service URL",
"loginCredentials": "Login Credentials",
"generateRandomUsername": "Generate random username",
"generateRandomPassword": "Generate random password",
"generateRandomAlias": "Generate Random Alias",
"alias": "Alias",
"firstName": "First Name",
"lastName": "Last Name",
"nickName": "Nick Name",
"gender": "Gender",
"birthDate": "Birth Date",
"birthDatePlaceholder": "YYYY-MM-DD",
"metadata": "Metadata",
"errors": {
"serviceNameRequired": "Service name is required",
"invalidUrl": "Please enter a valid URL",
"saveError": "Failed to save credential",
"loadError": "Failed to load credentials",
"deleteError": "Failed to delete credential",
"copyError": "Failed to copy to clipboard"
}
}

View File

@@ -1,18 +0,0 @@
{
"title": "Email Details",
"deleteEmailTitle": "Delete Email",
"deleteEmailConfirm": "Are you sure you want to permanently delete this email?",
"from": "From",
"to": "To",
"date": "Date",
"emailContent": "Email content",
"attachments": "Attachments",
"emailNotFound": "Email not found",
"noEmails": "No emails found",
"errors": {
"emailLoadError": "An error occurred while loading emails. Please try again later.",
"emailInUse": "The current chosen email address is already in use. Please change the email address by editing this credential.",
"emailSyncError": "An error occurred while trying to load the emails. Please try to edit and save the credential entry to synchronize the database, then try again.",
"emailUnexpectedError": "An unexpected error occurred while loading emails. Please try again later."
}
}

View File

@@ -1,33 +0,0 @@
{
"title": "Settings",
"serverUrl": "Server URL",
"language": "Language",
"autofillEnabled": "Enable Autofill",
"version": "Version",
"openInNewWindow": "Open in new window",
"openWebApp": "Open web app",
"loggedIn": "Logged in",
"logout": "Logout",
"globalSettings": "Global Settings",
"autofillPopup": "Autofill popup",
"activeOnAllSites": "Active on all sites (unless disabled below)",
"disabledOnAllSites": "Disabled on all sites",
"enabled": "Enabled",
"disabled": "Disabled",
"rightClickContextMenu": "Right-click context menu",
"siteSpecificSettings": "Site-Specific Settings",
"autofillPopupOn": "Autofill popup on: ",
"enabledForThisSite": "Enabled for this site",
"disabledForThisSite": "Disabled for this site",
"temporarilyDisabledUntil": "Temporarily disabled until ",
"resetAllSiteSettings": "Reset all site-specific settings",
"appearance": "Appearance",
"theme": "Theme",
"useDefault": "Use default",
"light": "Light",
"dark": "Dark",
"keyboardShortcuts": "Keyboard Shortcuts",
"configureKeyboardShortcuts": "Configure keyboard shortcuts",
"configure": "Configure",
"versionPrefix": "Version "
}

View File

@@ -1,34 +1,18 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// Import all translations
import authEn from '../locales/en/auth.json';
import commonEn from '../locales/en/common.json';
import credentialsEn from '../locales/en/credentials.json';
import emailsEn from '../locales/en/emails.json';
import settingsEn from '../locales/en/settings.json';
import authNl from '../locales/nl/auth.json';
import commonNl from '../locales/nl/common.json';
import credentialsNl from '../locales/nl/credentials.json';
import emailsNl from '../locales/nl/emails.json';
import settingsNl from '../locales/nl/settings.json';
// Import consolidated translations
import enTranslations from '../locales/en.json';
import nlTranslations from '../locales/nl.json';
import { storage } from '#imports';
const resources = {
en: {
common: commonEn,
auth: authEn,
credentials: credentialsEn,
settings: settingsEn,
emails: emailsEn
translation: enTranslations
},
nl: {
common: commonNl,
auth: authNl,
credentials: credentialsNl,
settings: settingsNl,
emails: emailsNl
translation: nlTranslations
}
};

View File

@@ -4,7 +4,7 @@ import { storage } from '#imports';
* Type for content translations
*/
export type ContentTranslations = {
[key: string]: string;
[key: string]: string | ContentTranslations;
};
/**
@@ -38,10 +38,10 @@ export async function getCurrentLanguage(): Promise<string> {
}
/**
* Load translations for a specific namespace and language
* Load translations for a specific language
*/
async function loadTranslations(namespace: string, language: string): Promise<ContentTranslations> {
const cacheKey = `${namespace}:${language}`;
async function loadTranslations(language: string): Promise<ContentTranslations> {
const cacheKey = `all:${language}`;
// Check cache first
if (translationCache.has(cacheKey)) {
@@ -49,8 +49,8 @@ async function loadTranslations(namespace: string, language: string): Promise<Co
}
try {
// Dynamically import the translation file
const translations = await import(`../../locales/${language}/${namespace}.json`);
// Dynamically import the consolidated translation file
const translations = await import(`../../locales/${language}.json`);
const translationData = translations.default || translations;
// Cache the translations
@@ -58,12 +58,12 @@ async function loadTranslations(namespace: string, language: string): Promise<Co
return translationData;
} catch (error) {
console.warn(`Failed to load translations for ${namespace}:${language}`, error);
console.warn(`Failed to load translations for ${language}`, error);
// Fallback to English if available
if (language !== 'en') {
try {
const fallbackTranslations = await import(`../../locales/en/${namespace}.json`);
const fallbackTranslations = await import(`../../locales/en.json`);
const fallbackData = fallbackTranslations.default || fallbackTranslations;
translationCache.set(cacheKey, fallbackData);
return fallbackData;
@@ -80,21 +80,19 @@ async function loadTranslations(namespace: string, language: string): Promise<Co
/**
* Translation function for non-React contexts
*
* @param key - Translation key (supports nested keys like 'errors.networkError')
* @param namespace - Translation namespace (default: 'content')
* @param key - Translation key (supports nested keys like 'auth.loginButton' or 'common.errors.networkError')
* @param fallback - Fallback text if translation is not found
* @returns Promise<string> - Translated text
*/
export async function t(
key: string,
namespace: string = 'content',
fallback?: string
): Promise<string> {
try {
const language = await getCurrentLanguage();
const translations = await loadTranslations(namespace, language);
const translations = await loadTranslations(language);
// Support nested keys like 'errors.networkError'
// Support nested keys like 'auth.loginButton' or 'common.errors.networkError'
const value = getNestedValue(translations, key);
if (value && typeof value === 'string') {
@@ -103,7 +101,7 @@ export async function t(
// If translation not found and we're not using English, try English fallback
if (language !== 'en') {
const englishTranslations = await loadTranslations(namespace, 'en');
const englishTranslations = await loadTranslations('en');
const englishValue = getNestedValue(englishTranslations, key);
if (englishValue && typeof englishValue === 'string') {
@@ -123,74 +121,9 @@ export async function t(
* Get nested value from object using dot notation
*/
function getNestedValue(obj: Record<string, unknown>, path: string): unknown {
return path.split('.').reduce((current, key) => {
return current && current[key] !== undefined ? current[key] : undefined;
return path.split('.').reduce((current: unknown, key: string) => {
return current && typeof current === 'object' && current !== null && key in current
? (current as Record<string, unknown>)[key]
: undefined;
}, obj);
}
/**
* Translation function specifically for content scripts
* This is a convenience wrapper around the main t() function
*/
export async function tc(key: string, fallback?: string): Promise<string> {
return t(key, 'content', fallback);
}
/**
* Translation function for errors namespace
*/
export async function te(key: string, fallback?: string): Promise<string> {
return t(key, 'errors', fallback);
}
/**
* Translation function for common namespace
*/
export async function tcommon(key: string, fallback?: string): Promise<string> {
return t(key, 'common', fallback);
}
/**
* Clear translation cache (useful for language changes)
*/
export function clearTranslationCache(): void {
translationCache.clear();
}
/**
* Pre-load common translations for use in synchronous contexts
*/
export async function preloadTranslationsForSync(
namespaces: string[] = ['common', 'errors']
): Promise<Record<string, ContentTranslations>> {
const languages = ['en', 'nl'];
const translations: Record<string, ContentTranslations> = {};
for (const lang of languages) {
const langTranslations: ContentTranslations = {};
for (const namespace of namespaces) {
try {
const nsTranslations = await loadTranslations(namespace, lang);
// Flatten the namespace structure for easier access
Object.keys(nsTranslations).forEach(key => {
if (namespace === 'common' && key === 'errors') {
// Handle nested errors object
const errors = nsTranslations[key] as Record<string, string>;
Object.keys(errors).forEach(errorKey => {
langTranslations[`errors.${errorKey}`] = errors[errorKey];
});
} else {
langTranslations[key] = nsTranslations[key];
}
});
} catch (error) {
console.warn(`Failed to preload ${namespace} translations for ${lang}:`, error);
}
}
translations[lang] = langTranslations;
}
return translations;
}

View File

@@ -45,8 +45,8 @@ files:
type: resx
translation_replace:
.en: ''
- source: /apps/browser-extension/src/locales/en/**/*.json
translation: /apps/browser-extension/src/locales/%two_letters_code%/%file_name%.%file_extension%
- source: /apps/browser-extension/src/locales/en.json
translation: /apps/browser-extension/src/locales/%two_letters_code%.json
type: json
- source: /apps/mobile-app/i18n/locales/en.json
translation: /apps/mobile-app/i18n/locales/%two_letters_code%.json