i18n(es): translate zap/NWC/delete/stash toasts + reuse feesUi keys for fee metadata
This commit is contained in:
parent
b01bd22e96
commit
97c90c506a
8 changed files with 155 additions and 46 deletions
|
|
@ -5,7 +5,7 @@ import { Button } from '@/components/ui/button';
|
|||
import { useTranslation } from '@/contexts/language';
|
||||
import { useSasquatchPro } from '@/hooks/useSasquatchPro';
|
||||
import { PRO_TIERS } from '@/lib/sasquatchPro';
|
||||
import { DURATION_TIERS, PLATFORM_FEES, FEE_META, tierPriceSats, tierPerDaySats, type FeeType } from '@/hooks/usePlatformFee';
|
||||
import { DURATION_TIERS, PLATFORM_FEES, FEE_META, DURATION_TIER_KEYS, FEE_LABEL_KEYS, FEE_BENEFIT_KEYS, tierPriceSats, tierPerDaySats, type FeeType } from '@/hooks/usePlatformFee';
|
||||
import { SasquatchProDialog } from '@/components/SasquatchProDialog';
|
||||
import { useLabProfiles } from '@/hooks/useLabProfiles';
|
||||
import { useCurrentUser } from '@/hooks/useCurrentUser';
|
||||
|
|
@ -106,13 +106,13 @@ export function ProSupportScreen({ onBack }: { onBack: () => void }) {
|
|||
{(Object.keys(PLATFORM_FEES) as FeeType[]).map((type) => (
|
||||
<div key={type}>
|
||||
<p className="text-xs font-bold text-gray-300">
|
||||
<span className="mr-1">{FEE_META[type].emoji}</span>{FEE_META[type].label}
|
||||
<span className="ml-2 font-normal text-muted-foreground">{FEE_META[type].benefit}</span>
|
||||
<span className="mr-1">{FEE_META[type].emoji}</span>{t(FEE_LABEL_KEYS[type])}
|
||||
<span className="ml-2 font-normal text-muted-foreground">{t(FEE_BENEFIT_KEYS[type])}</span>
|
||||
</p>
|
||||
<div className="mt-1.5 grid grid-cols-2 gap-1.5 sm:grid-cols-4">
|
||||
{DURATION_TIERS.map((tier) => (
|
||||
<div key={tier.id} className={cn('rounded-lg border p-2 text-center', tier.bestValue ? 'border-[#ccff00]/40 bg-[#ccff00]/5' : 'border-white/10')}>
|
||||
<p className="text-[11px] font-bold text-white">{tier.label}</p>
|
||||
<p className="text-[11px] font-bold text-white">{t(DURATION_TIER_KEYS[tier.id])}</p>
|
||||
<p className="text-xs font-black text-white">{tierPriceSats(type, tier).toLocaleString()}</p>
|
||||
<p className="text-[10px] text-muted-foreground">{tierPerDaySats(type, tier).toLocaleString()}/{t('settingsUi.proSupport.day')}</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { useCurrentUser } from '@/hooks/useCurrentUser';
|
|||
import { isAdminPubkey } from '@/lib/admins';
|
||||
import { useAdminHide } from '@/hooks/useAdminHide';
|
||||
import { toast } from '@/hooks/useToast';
|
||||
import { useTranslation } from '@/contexts/language';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
|
||||
/**
|
||||
|
|
@ -43,6 +44,7 @@ function withTimeout<T>(promise: Promise<T>, ms: number, label: string): Promise
|
|||
}
|
||||
|
||||
export function useDeleteEntity() {
|
||||
const { t } = useTranslation();
|
||||
const { nostr } = useNostr();
|
||||
const { user } = useCurrentUser();
|
||||
const queryClient = useQueryClient();
|
||||
|
|
@ -105,8 +107,8 @@ export function useDeleteEntity() {
|
|||
// screen directly — no more silent ContentProvider stall. The signer has its
|
||||
// own graceful timeout, but we keep an outer guard as a belt-and-braces.
|
||||
toast({
|
||||
title: 'Approve in Amber',
|
||||
description: 'Amber will open — tap Approve to confirm the deletion.',
|
||||
title: t('toastsUi.deleteApproveAmber'),
|
||||
description: t('toastsUi.deleteApproveAmberDesc'),
|
||||
});
|
||||
|
||||
if (!user.signer) {
|
||||
|
|
@ -124,11 +126,11 @@ export function useDeleteEntity() {
|
|||
const msg = e instanceof Error ? e.message : String(e);
|
||||
// Distinguish a deliberate rejection from a real failure.
|
||||
if (/reject/i.test(msg)) {
|
||||
toast({ title: 'Cancelled', description: 'You rejected the request in Amber.' });
|
||||
toast({ title: t('toastsUi.deleteCancelled'), description: t('toastsUi.deleteCancelledDesc') });
|
||||
throw new Error('Signing cancelled.');
|
||||
}
|
||||
toast({
|
||||
title: "Couldn't sign",
|
||||
title: t('toastsUi.deleteCouldntSign'),
|
||||
description: msg,
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
|
@ -137,8 +139,8 @@ export function useDeleteEntity() {
|
|||
|
||||
// ── PHASE 2: PUBLISH ─────────────────────────────────────────────────────
|
||||
toast({
|
||||
title: 'Step 2/2: Publishing…',
|
||||
description: 'Sending the deletion to relays.',
|
||||
title: t('toastsUi.deletePublishing'),
|
||||
description: t('toastsUi.deletePublishingDesc'),
|
||||
});
|
||||
|
||||
try {
|
||||
|
|
@ -151,8 +153,8 @@ export function useDeleteEntity() {
|
|||
const msg = e instanceof Error ? e.message : String(e);
|
||||
// The event was SIGNED fine — the relay is the slow/failing part.
|
||||
toast({
|
||||
title: 'Stuck at PUBLISHING',
|
||||
description: `Relay step failed: ${msg}. It was signed OK; the relay didn't confirm.`,
|
||||
title: t('toastsUi.deleteStuck'),
|
||||
description: t('toastsUi.deleteStuckDesc', { error: msg }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
throw new Error(`PUBLISH step failed: ${msg}`);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { useState, useCallback } from 'react';
|
||||
import { useLocalStorage } from '@/hooks/useLocalStorage';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useTranslation } from '@/contexts/language';
|
||||
import type { LN } from '@getalby/sdk';
|
||||
|
||||
/** Marks a payment whose final status could NOT be confirmed after a timeout. */
|
||||
|
|
@ -50,6 +51,7 @@ export interface NWCInfo {
|
|||
}
|
||||
|
||||
export function useNWCInternal() {
|
||||
const { t } = useTranslation();
|
||||
const { toast } = useToast();
|
||||
const [connections, setConnections] = useLocalStorage<NWCConnection[]>('nwc-connections', []);
|
||||
const [activeConnection, setActiveConnection] = useLocalStorage<string | null>('nwc-active-connection', null);
|
||||
|
|
@ -73,8 +75,8 @@ export function useNWCInternal() {
|
|||
const parsed = parseNWCUri(uri);
|
||||
if (!parsed) {
|
||||
toast({
|
||||
title: 'Invalid NWC URI',
|
||||
description: 'Please check the connection string and try again.',
|
||||
title: t('toastsUi.nwcInvalidUri'),
|
||||
description: t('toastsUi.nwcInvalidUriDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
return false;
|
||||
|
|
@ -83,8 +85,8 @@ export function useNWCInternal() {
|
|||
const existingConnection = connections.find(c => c.connectionString === parsed.connectionString);
|
||||
if (existingConnection) {
|
||||
toast({
|
||||
title: 'Connection already exists',
|
||||
description: 'This wallet is already connected.',
|
||||
title: t('toastsUi.nwcExists'),
|
||||
description: t('toastsUi.nwcExistsDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
return false;
|
||||
|
|
@ -135,18 +137,18 @@ export function useNWCInternal() {
|
|||
setActiveConnection(parsed.connectionString);
|
||||
|
||||
toast({
|
||||
title: 'Wallet connected',
|
||||
description: `Successfully connected to ${connection.alias}.`,
|
||||
title: t('toastsUi.nwcConnected'),
|
||||
description: t('toastsUi.nwcConnectedDesc', { alias: connection.alias ?? '' }),
|
||||
});
|
||||
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('NWC connection failed:', error);
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
||||
const errorMessage = error instanceof Error ? error.message : t('toastsUi.nwcUnknownError');
|
||||
|
||||
toast({
|
||||
title: 'Connection failed',
|
||||
description: `Could not connect to the wallet: ${errorMessage}`,
|
||||
title: t('toastsUi.nwcFailed'),
|
||||
description: t('toastsUi.nwcFailedDesc', { error: errorMessage }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
return false;
|
||||
|
|
@ -170,8 +172,8 @@ export function useNWCInternal() {
|
|||
});
|
||||
|
||||
toast({
|
||||
title: 'Wallet disconnected',
|
||||
description: 'The wallet connection has been removed.',
|
||||
title: t('toastsUi.nwcDisconnected'),
|
||||
description: t('toastsUi.nwcDisconnectedDesc'),
|
||||
});
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -45,6 +45,14 @@ export const DURATION_TIERS: DurationTier[] = [
|
|||
|
||||
export const DEFAULT_TIER_ID: DurationTierId = '30d';
|
||||
|
||||
/** `feesUi.*` keys for each duration tier label (single source for the UI). */
|
||||
export const DURATION_TIER_KEYS: Record<DurationTierId, string> = {
|
||||
'7d': 'feesUi.duration7d',
|
||||
'30d': 'feesUi.duration30d',
|
||||
'90d': 'feesUi.duration90d',
|
||||
'365d': 'feesUi.duration365d',
|
||||
};
|
||||
|
||||
/** Compute the sats price for a fee type at a given duration tier. */
|
||||
export function tierPriceSats(type: FeeType, tier: DurationTier): number {
|
||||
// Round to the nearest 100 sats for tidy amounts.
|
||||
|
|
@ -89,6 +97,21 @@ export const FEE_META: Record<FeeType, {
|
|||
},
|
||||
};
|
||||
|
||||
/** `feesUi.*` keys for each fee type's label/benefit (UI translates these). */
|
||||
export const FEE_LABEL_KEYS: Record<FeeType, string> = {
|
||||
featuredEvent: 'feesUi.feeFeaturedEventLabel',
|
||||
labProfile: 'feesUi.feeLabProfileLabel',
|
||||
featuredShop: 'feesUi.feeFeaturedShopLabel',
|
||||
featuredTour: 'feesUi.feeFeaturedTourLabel',
|
||||
};
|
||||
|
||||
export const FEE_BENEFIT_KEYS: Record<FeeType, string> = {
|
||||
featuredEvent: 'feesUi.feeFeaturedEventBenefit',
|
||||
labProfile: 'feesUi.feeLabProfileBenefit',
|
||||
featuredShop: 'feesUi.feeFeaturedShopBenefit',
|
||||
featuredTour: 'feesUi.feeFeaturedTourBenefit',
|
||||
};
|
||||
|
||||
// ─── localStorage key per fee type + account ─────────────────────────────────
|
||||
// Scoped by pubkey so one account on a shared device can't inherit another's
|
||||
// paid status (a device-global key let any later login skip the fee).
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ import { useNostrLogin } from '@nostrify/react/login';
|
|||
import { useCurrentUser } from './useCurrentUser';
|
||||
import { useNostrPublish } from './useNostrPublish';
|
||||
import { toast } from './useToast';
|
||||
import { useTranslation } from '@/contexts/language';
|
||||
import { hasNip44 as checkNip44, isInteractiveSigner } from '@/lib/signerCapabilities';
|
||||
import { cacheStashEvent, getCachedStashEvent } from '@/lib/offlineCache';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
|
|
@ -158,6 +159,7 @@ export function mergeStashes(local: Stash, remote: Stash): { stash: Stash; merge
|
|||
* still resolves from any previously-cached decrypt (React Query cache).
|
||||
*/
|
||||
export function useStash(options?: { enabled?: boolean }) {
|
||||
const { t } = useTranslation();
|
||||
const { nostr } = useNostr();
|
||||
const { user } = useCurrentUser();
|
||||
const { logins } = useNostrLogin();
|
||||
|
|
@ -295,14 +297,14 @@ export function useStash(options?: { enabled?: boolean }) {
|
|||
const { stash: mergedStash, merged } = mergeStashes(known, remote);
|
||||
if (merged) {
|
||||
toast({
|
||||
title: 'Merged changes from another device',
|
||||
description: 'Your stash was edited elsewhere — both sets of changes were kept.',
|
||||
title: t('toastsUi.stashMerged'),
|
||||
description: t('toastsUi.stashMergedDesc'),
|
||||
});
|
||||
}
|
||||
return { stash: mergedStash, confirmed };
|
||||
}
|
||||
return { stash: remote, confirmed };
|
||||
}, [user, hasNip44, nostr, queryClient, stash]);
|
||||
}, [user, hasNip44, nostr, queryClient, stash, t]);
|
||||
|
||||
/**
|
||||
* Stash writes rewrite the WHOLE blob, so they must run against a just-read
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import { useCurrentUser } from '@/hooks/useCurrentUser';
|
|||
import { useAuthor } from '@/hooks/useAuthor';
|
||||
import { useRelays } from '@/lib/relays';
|
||||
import { useToast } from '@/hooks/useToast';
|
||||
import { useTranslation } from '@/contexts/language';
|
||||
import { useNWC } from '@/hooks/useNWCContext';
|
||||
import { PAYMENT_STATUS_UNKNOWN, type NWCConnection } from '@/hooks/useNWC';
|
||||
import { nip57 } from 'nostr-tools';
|
||||
|
|
@ -20,6 +21,7 @@ export function useZaps(
|
|||
_nwcConnection: NWCConnection | null,
|
||||
onZapSuccess?: () => void
|
||||
) {
|
||||
const { t } = useTranslation();
|
||||
const { nostr } = useNostr();
|
||||
const { toast } = useToast();
|
||||
const { user } = useCurrentUser();
|
||||
|
|
@ -219,8 +221,8 @@ export function useZaps(
|
|||
|
||||
if (!user) {
|
||||
toast({
|
||||
title: 'Login required',
|
||||
description: 'You must be logged in to send a zap.',
|
||||
title: t('toastsUi.zapLoginRequired'),
|
||||
description: t('toastsUi.zapLoginRequiredDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
setIsZapping(false);
|
||||
|
|
@ -229,8 +231,8 @@ export function useZaps(
|
|||
|
||||
if (!actualTarget) {
|
||||
toast({
|
||||
title: 'Event not found',
|
||||
description: 'Could not find the event to zap.',
|
||||
title: t('toastsUi.zapEventNotFound'),
|
||||
description: t('toastsUi.zapEventNotFoundDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
setIsZapping(false);
|
||||
|
|
@ -240,8 +242,8 @@ export function useZaps(
|
|||
try {
|
||||
if (!author.data || !author.data?.metadata || !author.data?.event ) {
|
||||
toast({
|
||||
title: 'Author not found',
|
||||
description: 'Could not find the author of this item.',
|
||||
title: t('toastsUi.zapAuthorNotFound'),
|
||||
description: t('toastsUi.zapAuthorNotFoundDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
setIsZapping(false);
|
||||
|
|
@ -264,8 +266,8 @@ export function useZaps(
|
|||
setInvoice(null);
|
||||
|
||||
toast({
|
||||
title: 'Zap successful!',
|
||||
description: `You sent ${amount} sats via NWC to the author.`,
|
||||
title: t('toastsUi.zapSuccess'),
|
||||
description: t('toastsUi.zapSuccessNwcDesc', { amount }),
|
||||
});
|
||||
|
||||
// Invalidate zap queries to refresh counts
|
||||
|
|
@ -280,8 +282,8 @@ export function useZaps(
|
|||
if ((nwcError as { code?: string })?.code === PAYMENT_STATUS_UNKNOWN) {
|
||||
setIsZapping(false);
|
||||
toast({
|
||||
title: 'Payment status unknown',
|
||||
description: 'Your wallet may still be settling this zap. Check your wallet before retrying — do not pay twice.',
|
||||
title: t('toastsUi.zapStatusUnknown'),
|
||||
description: t('toastsUi.zapStatusUnknownDesc'),
|
||||
variant: 'destructive',
|
||||
});
|
||||
return;
|
||||
|
|
@ -289,10 +291,10 @@ export function useZaps(
|
|||
console.error('NWC payment failed, falling back:', nwcError);
|
||||
|
||||
// Show specific NWC error to user for debugging
|
||||
const errorMessage = nwcError instanceof Error ? nwcError.message : 'Unknown NWC error';
|
||||
const errorMessage = nwcError instanceof Error ? nwcError.message : t('toastsUi.zapUnknownNwcError');
|
||||
toast({
|
||||
title: 'NWC payment failed',
|
||||
description: `${errorMessage}. Falling back to other payment methods...`,
|
||||
title: t('toastsUi.zapNwcFailed'),
|
||||
description: t('toastsUi.zapFallingBack', { error: errorMessage }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
}
|
||||
|
|
@ -319,8 +321,8 @@ export function useZaps(
|
|||
setInvoice(null);
|
||||
|
||||
toast({
|
||||
title: 'Zap successful!',
|
||||
description: `You sent ${amount} sats to the author.`,
|
||||
title: t('toastsUi.zapSuccess'),
|
||||
description: t('toastsUi.zapSuccessDesc', { amount }),
|
||||
});
|
||||
|
||||
// Invalidate zap queries to refresh counts
|
||||
|
|
@ -332,10 +334,10 @@ export function useZaps(
|
|||
console.error('WebLN payment failed, falling back:', weblnError);
|
||||
|
||||
// Show specific WebLN error to user for debugging
|
||||
const errorMessage = weblnError instanceof Error ? weblnError.message : 'Unknown WebLN error';
|
||||
const errorMessage = weblnError instanceof Error ? weblnError.message : t('toastsUi.zapUnknownWeblnError');
|
||||
toast({
|
||||
title: 'WebLN payment failed',
|
||||
description: `${errorMessage}. Falling back to other payment methods...`,
|
||||
title: t('toastsUi.zapWeblnFailed'),
|
||||
description: t('toastsUi.zapFallingBack', { error: errorMessage }),
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
||||
|
|
@ -349,7 +351,7 @@ export function useZaps(
|
|||
} catch (err) {
|
||||
console.error('Zap error:', err);
|
||||
toast({
|
||||
title: 'Zap failed',
|
||||
title: t('toastsUi.zapFailed'),
|
||||
description: (err as Error).message,
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
|
@ -358,7 +360,7 @@ export function useZaps(
|
|||
} catch (err) {
|
||||
console.error('Zap error:', err);
|
||||
toast({
|
||||
title: 'Zap failed',
|
||||
title: t('toastsUi.zapFailed'),
|
||||
description: (err as Error).message,
|
||||
variant: 'destructive',
|
||||
});
|
||||
|
|
|
|||
|
|
@ -6927,6 +6927,45 @@ walletUi: {
|
|||
pleaseTryAgain: 'Please try again.',
|
||||
relayUnreachable: 'Could not reach any relay — check your connection and try again.',
|
||||
loginToReport: 'Log in to report a spot.',
|
||||
zapLoginRequired: 'Login required',
|
||||
zapLoginRequiredDesc: 'You must be logged in to send a zap.',
|
||||
zapEventNotFound: 'Event not found',
|
||||
zapEventNotFoundDesc: 'Could not find the event to zap.',
|
||||
zapAuthorNotFound: 'Author not found',
|
||||
zapAuthorNotFoundDesc: 'Could not find the author of this item.',
|
||||
zapSuccess: 'Zap successful!',
|
||||
zapSuccessNwcDesc: 'You sent {{amount}} sats via NWC to the author.',
|
||||
zapSuccessDesc: 'You sent {{amount}} sats to the author.',
|
||||
zapStatusUnknown: 'Payment status unknown',
|
||||
zapStatusUnknownDesc: 'Your wallet may still be settling this zap. Check your wallet before retrying — do not pay twice.',
|
||||
zapNwcFailed: 'NWC payment failed',
|
||||
zapWeblnFailed: 'WebLN payment failed',
|
||||
zapFallingBack: '{{error}}. Falling back to other payment methods...',
|
||||
zapFailed: 'Zap failed',
|
||||
zapUnknownNwcError: 'Unknown NWC error',
|
||||
zapUnknownWeblnError: 'Unknown WebLN error',
|
||||
nwcInvalidUri: 'Invalid NWC URI',
|
||||
nwcInvalidUriDesc: 'Please check the connection string and try again.',
|
||||
nwcExists: 'Connection already exists',
|
||||
nwcExistsDesc: 'This wallet is already connected.',
|
||||
nwcConnected: 'Wallet connected',
|
||||
nwcConnectedDesc: 'Successfully connected to {{alias}}.',
|
||||
nwcFailed: 'Connection failed',
|
||||
nwcFailedDesc: 'Could not connect to the wallet: {{error}}',
|
||||
nwcUnknownError: 'Unknown error occurred',
|
||||
nwcDisconnected: 'Wallet disconnected',
|
||||
nwcDisconnectedDesc: 'The wallet connection has been removed.',
|
||||
deleteApproveAmber: 'Approve in Amber',
|
||||
deleteApproveAmberDesc: 'Amber will open — tap Approve to confirm the deletion.',
|
||||
deleteCancelled: 'Cancelled',
|
||||
deleteCancelledDesc: 'You rejected the request in Amber.',
|
||||
deleteCouldntSign: "Couldn't sign",
|
||||
deletePublishing: 'Step 2/2: Publishing…',
|
||||
deletePublishingDesc: 'Sending the deletion to relays.',
|
||||
deleteStuck: 'Stuck at PUBLISHING',
|
||||
deleteStuckDesc: "Relay step failed: {{error}}. It was signed OK; the relay didn't confirm.",
|
||||
stashMerged: 'Merged changes from another device',
|
||||
stashMergedDesc: 'Your stash was edited elsewhere — both sets of changes were kept.',
|
||||
},
|
||||
cardUi: {
|
||||
save: 'Save card to Nostr',
|
||||
|
|
|
|||
|
|
@ -6927,6 +6927,45 @@ walletUi: {
|
|||
pleaseTryAgain: 'Inténtalo de nuevo.',
|
||||
relayUnreachable: 'No se pudo alcanzar ningún relay — revisa tu conexión e inténtalo de nuevo.',
|
||||
loginToReport: 'Inicia sesión para informar de un spot.',
|
||||
zapLoginRequired: 'Inicio de sesión requerido',
|
||||
zapLoginRequiredDesc: 'Debes iniciar sesión para enviar un zap.',
|
||||
zapEventNotFound: 'Evento no encontrado',
|
||||
zapEventNotFoundDesc: 'No se pudo encontrar el evento a zapear.',
|
||||
zapAuthorNotFound: 'Autor no encontrado',
|
||||
zapAuthorNotFoundDesc: 'No se pudo encontrar el autor de este artículo.',
|
||||
zapSuccess: '¡Zap enviado!',
|
||||
zapSuccessNwcDesc: 'Enviaste {{amount}} sats vía NWC al autor.',
|
||||
zapSuccessDesc: 'Enviaste {{amount}} sats al autor.',
|
||||
zapStatusUnknown: 'Estado del pago desconocido',
|
||||
zapStatusUnknownDesc: 'Es posible que tu cartera aún esté liquidando este zap. Revisa tu cartera antes de reintentar — no pagues dos veces.',
|
||||
zapNwcFailed: 'Falló el pago por NWC',
|
||||
zapWeblnFailed: 'Falló el pago por WebLN',
|
||||
zapFallingBack: '{{error}}. Cambiando a otros métodos de pago...',
|
||||
zapFailed: 'Falló el zap',
|
||||
zapUnknownNwcError: 'Error desconocido de NWC',
|
||||
zapUnknownWeblnError: 'Error desconocido de WebLN',
|
||||
nwcInvalidUri: 'URI de NWC no válido',
|
||||
nwcInvalidUriDesc: 'Revisa la cadena de conexión e inténtalo de nuevo.',
|
||||
nwcExists: 'La conexión ya existe',
|
||||
nwcExistsDesc: 'Esta cartera ya está conectada.',
|
||||
nwcConnected: 'Cartera conectada',
|
||||
nwcConnectedDesc: 'Conectado correctamente a {{alias}}.',
|
||||
nwcFailed: 'Falló la conexión',
|
||||
nwcFailedDesc: 'No se pudo conectar a la cartera: {{error}}',
|
||||
nwcUnknownError: 'Se produjo un error desconocido',
|
||||
nwcDisconnected: 'Cartera desconectada',
|
||||
nwcDisconnectedDesc: 'Se ha eliminado la conexión de la cartera.',
|
||||
deleteApproveAmber: 'Aprueba en Amber',
|
||||
deleteApproveAmberDesc: 'Amber se abrirá — toca Aprobar para confirmar la eliminación.',
|
||||
deleteCancelled: 'Cancelado',
|
||||
deleteCancelledDesc: 'Rechazaste la solicitud en Amber.',
|
||||
deleteCouldntSign: 'No se pudo firmar',
|
||||
deletePublishing: 'Paso 2/2: Publicando…',
|
||||
deletePublishingDesc: 'Enviando la eliminación a los relays.',
|
||||
deleteStuck: 'Atascado en PUBLICANDO',
|
||||
deleteStuckDesc: 'Falló el paso de relay: {{error}}. Se firmó bien; el relay no confirmó.',
|
||||
stashMerged: 'Cambios fusionados desde otro dispositivo',
|
||||
stashMergedDesc: 'Tu stash se editó en otro lugar — se conservaron ambos conjuntos de cambios.',
|
||||
},
|
||||
cardUi: {
|
||||
save: 'Guardar carné en Nostr',
|
||||
|
|
|
|||
Loading…
Reference in a new issue