-
Public Key (npub)
+
{t('settings.keyManagement.publicKey.npub')}
{
void handleCopyNpub()
}}
className="px-3 py-1 text-xs bg-cyber-light border border-neon-cyan/30 hover:border-neon-cyan/50 hover:bg-cyber-dark text-cyber-accent hover:text-neon-cyan rounded transition-colors"
>
- {copiedNpub ? '✓ Copied' : 'Copy'}
+ {copiedNpub ? t('settings.keyManagement.copied') : t('settings.keyManagement.copy')}
{publicKeys.npub}
@@ -230,14 +230,14 @@ export function KeyManagementManager() {
-
Public Key (hex)
+
{t('settings.keyManagement.publicKey.hex')}
{
void handleCopyPublicKey()
}}
className="px-3 py-1 text-xs bg-cyber-light border border-neon-cyan/30 hover:border-neon-cyan/50 hover:bg-cyber-dark text-cyber-accent hover:text-neon-cyan rounded transition-colors"
>
- {copiedPublicKey ? '✓ Copied' : 'Copy'}
+ {copiedPublicKey ? t('settings.keyManagement.copied') : t('settings.keyManagement.copy')}
{publicKeys.publicKey}
@@ -247,9 +247,9 @@ export function KeyManagementManager() {
{!publicKeys && !accountExists && (
-
No account found
+
{t('settings.keyManagement.noAccount.title')}
- Create a new account by importing a private key. The key will be encrypted using a two-level encryption system.
+ {t('settings.keyManagement.noAccount.description')}
)}
@@ -263,28 +263,23 @@ export function KeyManagementManager() {
}}
className="w-full py-3 px-6 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan"
>
- {accountExists ? 'Replace Account (Import New Key)' : 'Import Private Key'}
+ {accountExists ? t('settings.keyManagement.import.button.replace') : t('settings.keyManagement.import.button.new')}
)}
{showImportForm && (
-
⚠️ Important
-
- After importing, you will receive 4 recovery words (BIP39 dictionary) to secure your account.
- These words encrypt a Key Encryption Key (KEK) stored in the browser's Credentials API, which then encrypts your private key stored in IndexedDB (two-level encryption system).
-
+
{t('settings.keyManagement.import.warning.title')}
+
{accountExists && (
-
- Warning: Importing a new key will replace your existing account. Make sure you have your recovery phrase saved before proceeding.
-
+
)}
- Private Key (nsec URL, nsec1..., or hex)
+ {t('settings.keyManagement.import.label')}
- You can paste a nsec key, a nostr:// URL containing a nsec, or a hex private key (64 characters).
+ {t('settings.keyManagement.import.help')}
{showReplaceWarning && (
-
⚠️ Replace Existing Account?
+
{t('settings.keyManagement.replace.warning.title')}
- This will delete your current account and create a new one with the imported key. Make sure you have saved your recovery phrase for the current account.
+ {t('settings.keyManagement.replace.warning.description')}
- Cancel
+ {t('settings.keyManagement.replace.cancel')}
{
@@ -324,7 +319,7 @@ export function KeyManagementManager() {
disabled={importing}
className="flex-1 py-2 px-4 bg-red-600/20 hover:bg-red-600/30 text-red-400 rounded-lg font-medium transition-all border border-red-400/50 hover:shadow-glow-red disabled:opacity-50"
>
- {importing ? 'Replacing...' : 'Replace Account'}
+ {importing ? t('settings.keyManagement.replace.replacing') : t('settings.keyManagement.replace.confirm')}
@@ -340,7 +335,7 @@ export function KeyManagementManager() {
}}
className="flex-1 py-2 px-4 bg-cyber-light border border-neon-cyan/30 hover:border-neon-cyan/50 hover:bg-cyber-dark text-cyber-accent hover:text-neon-cyan rounded-lg font-medium transition-colors"
>
- Cancel
+ {t('settings.keyManagement.import.cancel')}
{
@@ -349,7 +344,7 @@ export function KeyManagementManager() {
disabled={importing}
className="flex-1 py-2 px-4 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan disabled:opacity-50"
>
- {importing ? 'Importing...' : 'Import'}
+ {importing ? t('settings.keyManagement.import.importing') : t('settings.keyManagement.import.import')}
)}
@@ -360,16 +355,11 @@ export function KeyManagementManager() {
{recoveryPhrase && newNpub && (
-
⚠️ Important
-
- These 4 recovery words are your only way to recover your account.
- They will never be displayed again.
-
+
{t('settings.keyManagement.recovery.warning.title')}
+
+
- These words (BIP39 dictionary) are used with PBKDF2 to encrypt a Key Encryption Key (KEK) stored in the browser's Credentials API. This KEK then encrypts your private key stored in IndexedDB (two-level system).
-
-
- Save them in a safe place. Without these words, you will permanently lose access to your account.
+ {t('settings.keyManagement.recovery.warning.part3')}
@@ -391,12 +381,12 @@ export function KeyManagementManager() {
}}
className="w-full py-2 px-4 bg-cyber-light border border-neon-cyan/30 hover:border-neon-cyan/50 hover:bg-cyber-dark text-cyber-accent hover:text-neon-cyan rounded-lg text-sm font-medium transition-colors"
>
- {copiedRecoveryPhrase ? '✓ Copied!' : 'Copy Recovery Words'}
+ {copiedRecoveryPhrase ? t('settings.keyManagement.recovery.copied') : t('settings.keyManagement.recovery.copy')}
-
Your new public key (npub)
+
{t('settings.keyManagement.recovery.newNpub')}
{newNpub}
@@ -408,7 +398,7 @@ export function KeyManagementManager() {
}}
className="w-full py-2 px-4 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan rounded-lg font-medium transition-all border border-neon-cyan/50 hover:shadow-glow-cyan"
>
- Done
+ {t('settings.keyManagement.recovery.done')}
)}
diff --git a/components/Nip95ConfigManager.tsx b/components/Nip95ConfigManager.tsx
index 8bbdd7c..cc32a95 100644
--- a/components/Nip95ConfigManager.tsx
+++ b/components/Nip95ConfigManager.tsx
@@ -1,6 +1,7 @@
import { useState, useEffect } from 'react'
import { configStorage } from '@/lib/configStorage'
import type { Nip95Config } from '@/lib/configStorageTypes'
+import { t } from '@/lib/i18n'
interface Nip95ConfigManagerProps {
onConfigChange?: () => void
@@ -25,7 +26,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
const config = await configStorage.getConfig()
setApis(config.nip95Apis.sort((a, b) => a.priority - b.priority))
} catch (e) {
- const errorMessage = e instanceof Error ? e.message : 'Failed to load NIP-95 APIs'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.loadFailed')
setError(errorMessage)
console.error('Error loading NIP-95 APIs:', e)
} finally {
@@ -39,7 +40,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
await loadApis()
onConfigChange?.()
} catch (e) {
- const errorMessage = e instanceof Error ? e.message : 'Failed to update API'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.updateFailed')
setError(errorMessage)
console.error('Error updating NIP-95 API:', e)
}
@@ -51,7 +52,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
await loadApis()
onConfigChange?.()
} catch (e) {
- const errorMessage = e instanceof Error ? e.message : 'Failed to update priority'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.priorityFailed')
setError(errorMessage)
console.error('Error updating priority:', e)
}
@@ -64,7 +65,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
setEditingId(null)
onConfigChange?.()
} catch (e) {
- const errorMessage = e instanceof Error ? e.message : 'Failed to update URL'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.urlFailed')
setError(errorMessage)
console.error('Error updating URL:', e)
}
@@ -72,7 +73,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
async function handleAddApi() {
if (!newUrl.trim()) {
- setError('URL is required')
+ setError(t('settings.nip95.error.urlRequired'))
return
}
@@ -86,9 +87,9 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
onConfigChange?.()
} catch (e) {
if (e instanceof TypeError && e.message.includes('Invalid URL')) {
- setError('Invalid URL format')
+ setError(t('settings.nip95.error.invalidUrl'))
} else {
- const errorMessage = e instanceof Error ? e.message : 'Failed to add API'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.addFailed')
setError(errorMessage)
}
console.error('Error adding NIP-95 API:', e)
@@ -96,7 +97,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
}
async function handleRemoveApi(id: string) {
- if (!confirm('Are you sure you want to remove this endpoint?')) {
+ if (!confirm(t('settings.nip95.remove.confirm'))) {
return
}
@@ -105,7 +106,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
await loadApis()
onConfigChange?.()
} catch (e) {
- const errorMessage = e instanceof Error ? e.message : 'Failed to remove API'
+ const errorMessage = e instanceof Error ? e.message : t('settings.nip95.error.removeFailed')
setError(errorMessage)
console.error('Error removing NIP-95 API:', e)
}
@@ -114,7 +115,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
if (loading) {
return (
-
Loading...
+
{t('settings.nip95.loading')}
)
}
@@ -134,12 +135,12 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
)}
-
NIP-95 Upload Endpoints
+ {t('settings.nip95.title')}
setShowAddForm(!showAddForm)}
className="px-4 py-2 bg-neon-cyan/20 hover:bg-neon-cyan/30 text-neon-cyan border border-neon-cyan/50 rounded transition-colors"
>
- {showAddForm ? 'Cancel' : '+ Add Endpoint'}
+ {showAddForm ? t('settings.nip95.add.cancel') : t('settings.nip95.addButton')}
@@ -147,13 +148,13 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)
@@ -181,7 +182,7 @@ export function Nip95ConfigManager({ onConfigChange }: Nip95ConfigManagerProps)