ui(auth): compact, scroll-safe sign-in dialog
- Fix the real bug: the dialog clipped its bottom links (flex column + max-h calc(100dvh-2rem), content min-h-0 flex-1 overflow-y-auto). - One dominant action per state: 'New here' is a compact row, not a second hero. - Plain card labels (Browser extension / Signer app / Sign in with your phone) with tiny NIP-07/46/55 hints; protocol jargon out of the main labels. - Bunker: input + Connect with instructions collapsed under 'Where do I get a bunker?'; no duplicate heading/divider. - Secret key moved to a quiet bottom link; subtitle says 'or keep browsing'. - 8px spacing grid (px-5 gutters, space-y-4 sections, gap-2 cards, p-2.5 cards, 448px max width). New strings backfilled into all 20 locales. Verified with headless 1280x900 + 390x844 screenshots.
This commit is contained in:
parent
f56a8b28e5
commit
fe3d9bae22
24 changed files with 237 additions and 71 deletions
16
AGENTS.md
16
AGENTS.md
|
|
@ -1533,8 +1533,20 @@ session with **no other memory of this project**. So:
|
|||
**Sign in with your phone** (NostrConnect) — plus a quiet **Secret Key** link;
|
||||
the cards are a **controlled tab chooser** (`loginTab` state) over the existing
|
||||
panels, and the NostrConnect QR moved from the bunker tab into its own
|
||||
`connect` panel. Verified with a headless 1280×900 screenshot of the
|
||||
auto-opened welcome modal. ⚠️ `SignupDialog` is a **default-only** export, so
|
||||
`connect` panel. **Compact pass (2026-10-26):** the dialog is now
|
||||
scroll-safe (`flex flex-col` + `max-h-[calc(100dvh-2rem)]`, content
|
||||
`min-h-0 flex-1 overflow-y-auto` — it used to clip the bottom links), the
|
||||
New-here block is a compact row (one dominant action per state), bunker
|
||||
instructions are a collapsed `<details>` ("Where do I get a bunker?"), and the
|
||||
secret-key option is a quiet bottom link. Labels are plain ("Browser
|
||||
extension · Signer app · Sign in with your phone") with **NIP-07/46/55** as
|
||||
tiny hints (`settingsUi.loginDialog.{extensionCard,signerCard,secretKeyLink,
|
||||
whereBunker,welcomeSubtitleBrowse}`; backfilled to all 20 locales). Spacing is
|
||||
an **8px grid**: `px-5` (20px) gutters, `space-y-4` (16px) between sections,
|
||||
`gap-2` (8px) between cards, `p-2.5` (10px) card padding, `pt-5/pb-3` header —
|
||||
a 448px max width keeps 3 cards ≥~120px each while staying a single focused
|
||||
column. Verified with headless 1280×900 and 390×844 screenshots.
|
||||
⚠️ `SignupDialog` is a **default-only** export, so
|
||||
lazy-load it as
|
||||
`lazy(() => import('…/SignupDialog'))`.
|
||||
- **Pass the app on — Android only (2026-10-26):** the About page renders
|
||||
|
|
|
|||
|
|
@ -321,47 +321,51 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
|
||||
return (
|
||||
<Dialog open={isOpen} onOpenChange={onClose}>
|
||||
<DialogContent className={cn("w-[calc(100%-1rem)] sm:max-w-md max-h-[90vh] max-h-[90dvh] p-0 overflow-hidden rounded-2xl bg-black border-2 border-[#ff0040]/50")}>
|
||||
<DialogHeader className={cn('px-4 sm:px-6 pt-4 sm:pt-6 pb-1')}>
|
||||
<DialogTitle className="text-center font-black uppercase tracking-wide text-xl">
|
||||
<DialogContent className={cn("flex w-[calc(100%-1rem)] flex-col sm:max-w-md max-h-[calc(100dvh-2rem)] p-0 overflow-hidden rounded-2xl bg-black border-2 border-[#ff0040]/50")}>
|
||||
<DialogHeader className={cn('px-5 pt-5 pb-3')}>
|
||||
<DialogTitle className="text-center font-black uppercase tracking-wide text-lg">
|
||||
{t('settingsUi.loginDialog.welcomeTitle')}
|
||||
</DialogTitle>
|
||||
<DialogDescription className="text-center text-sm text-gray-400">
|
||||
{t('settingsUi.loginDialog.welcomeSubtitle')}
|
||||
<DialogDescription className="text-center text-xs text-gray-400">
|
||||
{t('settingsUi.loginDialog.welcomeSubtitleBrowse')}
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
|
||||
<div className='px-4 sm:px-6 pt-2 pb-6 space-y-4 overflow-y-auto'>
|
||||
{/* Sign Up */}
|
||||
<div className='relative p-5 rounded-2xl bg-black border-2 border-[#ccff00]/50 overflow-hidden'>
|
||||
<div className="absolute inset-0 bg-[#ccff00]/5 blur-xl" />
|
||||
<div className='relative z-10 text-center space-y-3'>
|
||||
<div className='flex justify-center items-center gap-2'>
|
||||
<Sparkles className='w-5 h-5 text-[#ccff00]' />
|
||||
<span className='font-bold text-[#ccff00] uppercase tracking-wide'>{t('settingsUi.loginDialog.newHere')}</span>
|
||||
</div>
|
||||
<p className='text-xs text-gray-300'>{t('settingsUi.loginDialog.createFree')}</p>
|
||||
<Button onClick={() => { onClose(); onSignup?.(); }} className='w-full rounded-full py-3 font-bold bg-[#ccff00] text-black hover:bg-[#ccff00]/90 uppercase'>
|
||||
<UserPlus className='w-4 h-4 mr-2' />{t('settingsUi.loginDialog.createAccount')}
|
||||
</Button>
|
||||
<div className='min-h-0 flex-1 overflow-y-auto px-5 pb-5 pt-1 space-y-4'>
|
||||
{/* Sign up — a compact row, not a second hero: the dialog should have
|
||||
ONE dominant action per state, and logging in is the main path. */}
|
||||
<div className='flex items-center gap-3 rounded-xl border border-[#ccff00]/40 bg-[#ccff00]/5 p-3'>
|
||||
<div className='flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-[#ccff00]/15'>
|
||||
<Sparkles className='h-4 w-4 text-[#ccff00]' />
|
||||
</div>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<p className='text-sm font-bold text-[#ccff00]'>{t('settingsUi.loginDialog.newHere')}</p>
|
||||
<p className='text-[11px] leading-snug text-gray-400'>{t('settingsUi.loginDialog.createFree')}</p>
|
||||
</div>
|
||||
<Button
|
||||
size='sm'
|
||||
onClick={() => { onClose(); onSignup?.(); }}
|
||||
className='h-9 shrink-0 gap-1.5 bg-[#ccff00] px-3 text-xs font-bold text-black hover:bg-[#ccff00]/90'
|
||||
>
|
||||
<UserPlus className='h-3.5 w-3.5' />{t('settingsUi.loginDialog.createAccount')}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className='relative flex items-center'>
|
||||
<div className='flex-1 border-t border-gray-800' />
|
||||
<span className='px-3 text-xs text-gray-500'>{t('settingsUi.loginDialog.orLogIn')}</span>
|
||||
<span className='px-3 text-[11px] text-gray-500'>{t('settingsUi.loginDialog.orLogIn')}</span>
|
||||
<div className='flex-1 border-t border-gray-800' />
|
||||
</div>
|
||||
|
||||
<Tabs value={loginTab} onValueChange={(v) => setLoginTab(v as typeof loginTab)} className="w-full">
|
||||
{/* Method cards — a clear three-way choice (the old 4-tab strip was
|
||||
jargon-heavy). The secret-key option stays as a quiet link. */}
|
||||
{/* Method cards — plain-language labels; protocol names move to a
|
||||
tiny hint so newcomers aren't met with "NIP-46" as the main word. */}
|
||||
<div className="mb-3 grid grid-cols-3 gap-2">
|
||||
{([
|
||||
{ id: 'extension', Icon: Shield, label: t('settingsUi.loginDialog.browserExtensionTitle') },
|
||||
{ id: isAndroid ? 'amber' : 'bunker', Icon: isAndroid ? Smartphone : Cloud, label: isAndroid ? t('settingsUi.loginDialog.loginWithAmber') : t('settingsUi.loginDialog.bunkerTitle') },
|
||||
{ id: 'connect', Icon: QrCode, label: t('settingsUi.loginDialog.signInWithPhone') },
|
||||
] as const).map(({ id, Icon, label }) => {
|
||||
{ id: 'extension', Icon: Shield, label: t('settingsUi.loginDialog.extensionCard'), hint: 'NIP-07' },
|
||||
{ id: isAndroid ? 'amber' : 'bunker', Icon: isAndroid ? Smartphone : Cloud, label: t('settingsUi.loginDialog.signerCard'), hint: isAndroid ? 'NIP-55' : 'NIP-46' },
|
||||
{ id: 'connect', Icon: QrCode, label: t('settingsUi.loginDialog.signInWithPhone'), hint: 'NIP-46' },
|
||||
] as const).map(({ id, Icon, label, hint }) => {
|
||||
const active = loginTab === id;
|
||||
return (
|
||||
<button
|
||||
|
|
@ -369,7 +373,7 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
type="button"
|
||||
onClick={() => setLoginTab(id)}
|
||||
className={cn(
|
||||
'flex min-h-0 flex-col items-center gap-1.5 rounded-xl border p-3 text-center transition-colors',
|
||||
'flex min-h-0 flex-col items-center gap-1 rounded-xl border p-2.5 text-center transition-colors',
|
||||
active
|
||||
? 'border-[#ccff00]/60 bg-[#ccff00]/10 text-[#ccff00]'
|
||||
: 'border-white/10 bg-black/40 text-gray-300 hover:border-white/25 hover:text-white',
|
||||
|
|
@ -377,22 +381,11 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
>
|
||||
<Icon className="h-5 w-5" />
|
||||
<span className="text-[11px] font-bold leading-tight">{label}</span>
|
||||
<span className="text-[9px] uppercase tracking-widest text-gray-500">{hint}</span>
|
||||
</button>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
<div className="mb-3 text-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setLoginTab('nsec')}
|
||||
className={cn(
|
||||
'text-[11px] underline underline-offset-2',
|
||||
loginTab === 'nsec' ? 'text-yellow-300' : 'text-gray-500 hover:text-gray-300',
|
||||
)}
|
||||
>
|
||||
{t('settingsUi.loginDialog.secretKeyTitle')}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* ── AMBER TAB ── */}
|
||||
<TabsContent value='amber' className='space-y-3'>
|
||||
|
|
@ -576,35 +569,32 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
</div>
|
||||
</TabsContent>
|
||||
|
||||
{/* ── BUNKER TAB ── */}
|
||||
{/* ── SIGNER (BUNKER) TAB ── */}
|
||||
<TabsContent value='bunker' className='space-y-3'>
|
||||
<div className='relative flex items-center'>
|
||||
<div className='flex-1 border-t border-gray-800' />
|
||||
<span className='px-3 text-xs text-gray-500'>{t('settingsUi.loginDialog.orPasteBunker')}</span>
|
||||
<div className='flex-1 border-t border-gray-800' />
|
||||
</div>
|
||||
|
||||
<div className='p-5 rounded-xl bg-black/50 border-2 border-blue-500/30 space-y-4'>
|
||||
<div className='text-center'>
|
||||
<Cloud className='w-10 h-10 mx-auto mb-2 text-blue-400' />
|
||||
<p className='text-sm text-white font-bold'>{t('settingsUi.loginDialog.bunkerTitle')}</p>
|
||||
<p className='text-xs text-gray-400 mt-1'>{t('settingsUi.loginDialog.bunkerPasteBefore')} <code className='text-blue-300'>bunker://</code> {t('settingsUi.loginDialog.bunkerPasteAfter')}</p>
|
||||
<div className='space-y-3 rounded-xl border border-blue-500/30 bg-black/50 p-4'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Cloud className='h-4 w-4 text-blue-400' />
|
||||
<p className='text-sm font-bold text-white'>{t('settingsUi.loginDialog.signerCard')}</p>
|
||||
</div>
|
||||
<div className='text-xs text-gray-300 bg-black/40 rounded-lg p-3 space-y-1 border border-gray-800'>
|
||||
<p><strong className='text-blue-300'>Amber:</strong> {t('settingsUi.loginDialog.amberInstructions')}</p>
|
||||
<p><strong className='text-blue-300'>nsec.app:</strong> {t('settingsUi.loginDialog.nsecAppInstructions')}</p>
|
||||
</div>
|
||||
<div className='space-y-2'>
|
||||
<Input placeholder='bunker://...' value={bunkerUri} onChange={e => { setBunkerUri(e.target.value); setBunkerError(''); }} className='bg-black/60 border-blue-500/30 text-white placeholder:text-gray-600 text-xs font-mono' autoComplete='off' autoCorrect='off' spellCheck={false} />
|
||||
{bunkerError && <p className="text-xs text-red-400">{bunkerError}</p>}
|
||||
</div>
|
||||
<Button className='w-full rounded-full py-3 bg-blue-500 hover:bg-blue-600 text-white font-bold uppercase' disabled={isLoading || !bunkerUri.trim()} onClick={handleBunkerLogin}>
|
||||
<Input placeholder='bunker://...' value={bunkerUri} onChange={e => { setBunkerUri(e.target.value); setBunkerError(''); }} className='bg-black/60 border-blue-500/30 text-white placeholder:text-gray-600 text-xs font-mono' autoComplete='off' autoCorrect='off' spellCheck={false} />
|
||||
{bunkerError && <p className="text-xs text-red-400">{bunkerError}</p>}
|
||||
<Button className='w-full rounded-full py-2.5 bg-blue-500 hover:bg-blue-600 text-white font-bold uppercase' disabled={isLoading || !bunkerUri.trim()} onClick={handleBunkerLogin}>
|
||||
{isLoading ? <Loader2 className='w-4 h-4 animate-spin mr-2' /> : <Cloud className='w-4 h-4 mr-2' />}{t('settingsUi.loginDialog.connect')}
|
||||
</Button>
|
||||
<div className='flex gap-2 justify-center'>
|
||||
<a href="https://nsec.app" target="_blank" rel="noopener noreferrer" className="text-xs px-3 py-1 bg-blue-500/20 text-blue-400 rounded-full hover:bg-blue-500/30">nsec.app →</a>
|
||||
<a href="https://nostrum.social" target="_blank" rel="noopener noreferrer" className="text-xs px-3 py-1 bg-blue-500/20 text-blue-400 rounded-full hover:bg-blue-500/30">Nostrum →</a>
|
||||
</div>
|
||||
{/* Instructions collapse: the default state is just input + Connect. */}
|
||||
<details>
|
||||
<summary className='cursor-pointer text-[11px] text-gray-500 hover:text-gray-300'>
|
||||
{t('settingsUi.loginDialog.whereBunker')}
|
||||
</summary>
|
||||
<div className='mt-2 space-y-1 rounded-lg border border-gray-800 bg-black/40 p-3 text-[11px] text-gray-400'>
|
||||
<p><strong className='text-blue-300'>Amber:</strong> {t('settingsUi.loginDialog.amberInstructions')}</p>
|
||||
<p><strong className='text-blue-300'>nsec.app:</strong> {t('settingsUi.loginDialog.nsecAppInstructions')}</p>
|
||||
<div className='flex gap-2 pt-1'>
|
||||
<a href="https://nsec.app" target="_blank" rel="noopener noreferrer" className="rounded-full bg-blue-500/20 px-2.5 py-0.5 text-blue-400 hover:bg-blue-500/30">nsec.app →</a>
|
||||
<a href="https://nostrum.social" target="_blank" rel="noopener noreferrer" className="rounded-full bg-blue-500/20 px-2.5 py-0.5 text-blue-400 hover:bg-blue-500/30">Nostrum →</a>
|
||||
</div>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
</TabsContent>
|
||||
|
||||
|
|
@ -691,18 +681,32 @@ export const LoginDialog: React.FC<LoginDialogProps> = ({ isOpen, onClose, onLog
|
|||
|
||||
{/* ── EXTENSION TAB ── */}
|
||||
<TabsContent value='extension' className='space-y-3'>
|
||||
<div className='text-center p-5 rounded-xl bg-black/50 border-2 border-[#ff0040]/30 space-y-4'>
|
||||
<Shield className='w-10 h-10 mx-auto text-[#ff0040]' />
|
||||
<div>
|
||||
<p className='text-sm text-white font-bold'>{t('settingsUi.loginDialog.browserExtensionTitle')}</p>
|
||||
<p className='text-xs text-gray-400 mt-1'>{t('settingsUi.loginDialog.browserExtensionDesc')}</p>
|
||||
<div className='space-y-3 rounded-xl border border-[#ff0040]/30 bg-black/50 p-4'>
|
||||
<div className='flex items-center gap-2'>
|
||||
<Shield className='h-4 w-4 text-[#ff0040]' />
|
||||
<p className='text-sm font-bold text-white'>{t('settingsUi.loginDialog.browserExtensionTitle')}</p>
|
||||
</div>
|
||||
<Button className='w-full rounded-full py-3 bg-[#ff0040] hover:bg-[#ff0040]/90 text-white font-bold uppercase' onClick={handleExtensionLogin}>
|
||||
<p className='text-xs text-gray-400'>{t('settingsUi.loginDialog.browserExtensionDesc')}</p>
|
||||
<Button className='w-full rounded-full py-2.5 bg-[#ff0040] hover:bg-[#ff0040]/90 text-white font-bold uppercase' onClick={handleExtensionLogin}>
|
||||
{t('settingsUi.loginDialog.loginWithExtension')}
|
||||
</Button>
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
{/* Quiet fallback for advanced users; not a third hero action. */}
|
||||
<div className='pt-1 text-center'>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setLoginTab('nsec')}
|
||||
className={cn(
|
||||
'text-[11px] underline underline-offset-2',
|
||||
loginTab === 'nsec' ? 'text-yellow-300' : 'text-gray-500 hover:text-gray-300',
|
||||
)}
|
||||
>
|
||||
{t('settingsUi.loginDialog.secretKeyLink')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ const drift = {
|
|||
}
|
||||
},
|
||||
"settingsUi": {
|
||||
"loginDialog": {
|
||||
"welcomeSubtitleBrowse": "Zaregistruj se nebo se přihlas — nebo si dál prohlížej.",
|
||||
"extensionCard": "Rozšíření prohlížeče",
|
||||
"signerCard": "Podepisovací aplikace",
|
||||
"secretKeyLink": "Použít místo toho tajný klíč",
|
||||
"whereBunker": "Kde získám bunker?",
|
||||
},
|
||||
"settingsPage": {
|
||||
"trust": "Důvěra",
|
||||
"trustSub": "Zdroje a zobrazení"
|
||||
|
|
|
|||
|
|
@ -95,6 +95,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Registriere dich oder melde dich an – oder stöbere weiter.",
|
||||
extensionCard: "Browser-Erweiterung",
|
||||
signerCard: "Signer-App",
|
||||
secretKeyLink: "Stattdessen einen geheimen Schlüssel verwenden",
|
||||
whereBunker: "Wo bekomme ich einen Bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Vertrauen",
|
||||
trustSub: "Quellen und Anzeige",
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Εγγραφείτε ή συνδεθείτε — ή συνεχίστε την περιήγηση.",
|
||||
extensionCard: "Επέκταση προγράμματος περιήγησης",
|
||||
signerCard: "Εφαρμογή υπογραφής",
|
||||
secretKeyLink: "Χρήση μυστικού κλειδιού",
|
||||
whereBunker: "Πού βρίσκω bunker;",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Εμπιστοσύνη",
|
||||
trustSub: "Πηγές και εμφάνιση",
|
||||
|
|
|
|||
|
|
@ -4552,6 +4552,11 @@ settingsUi: {
|
|||
loginWithAmber: 'Login with Amber (Android)',
|
||||
welcomeTitle: 'Welcome to SkateSpots',
|
||||
welcomeSubtitle: 'Sign up or log in to continue',
|
||||
welcomeSubtitleBrowse: 'Sign up or log in — or keep browsing.',
|
||||
extensionCard: 'Browser extension',
|
||||
signerCard: 'Signer app',
|
||||
secretKeyLink: 'Use a secret key instead',
|
||||
whereBunker: 'Where do I get a bunker?',
|
||||
newHere: 'New here?',
|
||||
createFree: 'Create a free account. No email required.',
|
||||
createAccount: 'Create Account',
|
||||
|
|
|
|||
|
|
@ -4552,6 +4552,11 @@ settingsUi: {
|
|||
loginWithAmber: 'Iniciar sesión con Amber (Android)',
|
||||
welcomeTitle: 'Bienvenido a SkateSpots',
|
||||
welcomeSubtitle: 'Regístrate o inicia sesión para continuar',
|
||||
welcomeSubtitleBrowse: 'Regístrate o inicia sesión, o sigue explorando.',
|
||||
extensionCard: 'Extensión del navegador',
|
||||
signerCard: 'App firmante',
|
||||
secretKeyLink: 'Usar una clave secreta',
|
||||
whereBunker: '¿Dónde consigo un bunker?',
|
||||
newHere: '¿Nuevo por aquí?',
|
||||
createFree: 'Crea una cuenta gratis. Sin correo electrónico.',
|
||||
createAccount: 'Crear cuenta',
|
||||
|
|
|
|||
|
|
@ -95,6 +95,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Inscris-toi ou connecte-toi — ou continue à explorer.",
|
||||
extensionCard: "Extension navigateur",
|
||||
signerCard: "App signataire",
|
||||
secretKeyLink: "Utiliser une clé secrète",
|
||||
whereBunker: "Où trouver un bunker ?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Confiance",
|
||||
trustSub: "Sources et affichage",
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ const driftStrings = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Daftar atau masuk — atau tetap jelajahi.",
|
||||
extensionCard: "Ekstensi peramban",
|
||||
signerCard: "Aplikasi penandatangan",
|
||||
secretKeyLink: "Gunakan kunci rahasia saja",
|
||||
whereBunker: "Di mana saya mendapatkan bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: 'Kepercayaan',
|
||||
trustSub: 'Sumber dan tampilan',
|
||||
|
|
|
|||
|
|
@ -95,6 +95,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Registrati o accedi — oppure continua a esplorare.",
|
||||
extensionCard: "Estensione del browser",
|
||||
signerCard: "App firmataria",
|
||||
secretKeyLink: "Usa invece una chiave segreta",
|
||||
whereBunker: "Dove trovo un bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Fiducia",
|
||||
trustSub: "Fonti e visualizzazione",
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ const drift: Dict = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "登録またはログイン — または閲覧を続ける。",
|
||||
extensionCard: "ブラウザ拡張",
|
||||
signerCard: "署名アプリ",
|
||||
secretKeyLink: "代わりに秘密鍵を使う",
|
||||
whereBunker: "バンカーはどこで入手?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: '信頼',
|
||||
trustSub: 'ソースと表示',
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ const drift: Dict = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "가입하거나 로그인하세요 — 또는 계속 둘러보세요.",
|
||||
extensionCard: "브라우저 확장",
|
||||
signerCard: "서명 앱",
|
||||
secretKeyLink: "대신 비밀 키 사용",
|
||||
whereBunker: "벙커는 어디서 구하나요?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: '신뢰',
|
||||
trustSub: '출처와 표시',
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ const drift = {
|
|||
}
|
||||
},
|
||||
"settingsUi": {
|
||||
"loginDialog": {
|
||||
"welcomeSubtitleBrowse": "Meld je aan of log in — of blijf rondkijken.",
|
||||
"extensionCard": "Browserextensie",
|
||||
"signerCard": "Signeer-app",
|
||||
"secretKeyLink": "Gebruik in plaats daarvan een geheime sleutel",
|
||||
"whereBunker": "Waar vind ik een bunker?",
|
||||
},
|
||||
"settingsPage": {
|
||||
"trust": "Vertrouwen",
|
||||
"trustSub": "Bronnen en weergave"
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ const drift = {
|
|||
}
|
||||
},
|
||||
"settingsUi": {
|
||||
"loginDialog": {
|
||||
"welcomeSubtitleBrowse": "Zarejestruj się lub zaloguj — albo przeglądaj dalej.",
|
||||
"extensionCard": "Rozszerzenie przeglądarki",
|
||||
"signerCard": "Aplikacja podpisująca",
|
||||
"secretKeyLink": "Użyj zamiast tego klucza tajnego",
|
||||
"whereBunker": "Gdzie znajdę bunkier?",
|
||||
},
|
||||
"settingsPage": {
|
||||
"trust": "Zaufanie",
|
||||
"trustSub": "Źródła i wyświetlanie"
|
||||
|
|
|
|||
|
|
@ -95,6 +95,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Cadastre-se ou entre — ou continue explorando.",
|
||||
extensionCard: "Extensão do navegador",
|
||||
signerCard: "App assinador",
|
||||
secretKeyLink: "Usar uma chave secreta",
|
||||
whereBunker: "Onde consigo um bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Confiança",
|
||||
trustSub: "Fontes e exibição",
|
||||
|
|
|
|||
|
|
@ -93,6 +93,13 @@ const drift = {
|
|||
}
|
||||
},
|
||||
"settingsUi": {
|
||||
"loginDialog": {
|
||||
"welcomeSubtitleBrowse": "Înregistrează-te sau autentifică-te — sau continuă să explorezi.",
|
||||
"extensionCard": "Extensie de browser",
|
||||
"signerCard": "Aplicație de semnare",
|
||||
"secretKeyLink": "Folosește în schimb o cheie secretă",
|
||||
"whereBunker": "De unde obțin un bunker?",
|
||||
},
|
||||
"settingsPage": {
|
||||
"trust": "Încredere",
|
||||
"trustSub": "Surse și afișare"
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Зарегистрируйтесь или войдите — или продолжайте просмотр.",
|
||||
extensionCard: "Расширение браузера",
|
||||
signerCard: "Приложение-подписант",
|
||||
secretKeyLink: "Использовать секретный ключ",
|
||||
whereBunker: "Где взять бункер?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Доверие",
|
||||
trustSub: "Источники и отображение",
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Registrera dig eller logga in — eller fortsätt bläddra.",
|
||||
extensionCard: "Webbläsartillägg",
|
||||
signerCard: "Signeringsapp",
|
||||
secretKeyLink: "Använd en hemlig nyckel i stället",
|
||||
whereBunker: "Var hittar jag en bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Förtroende",
|
||||
trustSub: "Källor och visning",
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ const driftStrings = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "สมัครหรือเข้าสู่ระบบ — หรือสำรวจต่อ",
|
||||
extensionCard: "ส่วนขยายเบราว์เซอร์",
|
||||
signerCard: "แอปเซ็นชื่อ",
|
||||
secretKeyLink: "ใช้คีย์ลับแทน",
|
||||
whereBunker: "หา bunker ได้ที่ไหน?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: 'ความน่าเชื่อถือ',
|
||||
trustSub: 'แหล่งที่มาและการแสดงผล',
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ const driftStrings = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Kaydol veya giriş yap — ya da göz atmaya devam et.",
|
||||
extensionCard: "Tarayıcı uzantısı",
|
||||
signerCard: "İmzalayıcı uygulama",
|
||||
secretKeyLink: "Bunun yerine gizli anahtar kullan",
|
||||
whereBunker: "Bunker'ı nereden bulurum?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: 'Güven',
|
||||
trustSub: 'Kaynaklar ve görünüm',
|
||||
|
|
|
|||
|
|
@ -97,6 +97,13 @@ const drift = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Зареєструйтеся або увійдіть — або продовжуйте перегляд.",
|
||||
extensionCard: "Розширення браузера",
|
||||
signerCard: "Застосунок-підписувач",
|
||||
secretKeyLink: "Використати секретний ключ",
|
||||
whereBunker: "Де взяти бункер?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: "Довіра",
|
||||
trustSub: "Джерела та відображення",
|
||||
|
|
|
|||
|
|
@ -89,6 +89,13 @@ const driftStrings = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "Đăng ký hoặc đăng nhập — hoặc tiếp tục khám phá.",
|
||||
extensionCard: "Tiện ích trình duyệt",
|
||||
signerCard: "Ứng dụng ký",
|
||||
secretKeyLink: "Dùng khóa bí mật thay thế",
|
||||
whereBunker: "Tìm bunker ở đâu?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: 'Tin cậy',
|
||||
trustSub: 'Nguồn và hiển thị',
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ const drift: Dict = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "注册或登录 — 或继续浏览。",
|
||||
extensionCard: "浏览器扩展",
|
||||
signerCard: "签名应用",
|
||||
secretKeyLink: "改用私钥",
|
||||
whereBunker: "在哪里获取 bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: '信任',
|
||||
trustSub: '来源与显示',
|
||||
|
|
|
|||
|
|
@ -105,6 +105,13 @@ const drift: Dict = {
|
|||
},
|
||||
},
|
||||
settingsUi: {
|
||||
loginDialog: {
|
||||
welcomeSubtitleBrowse: "註冊或登入 — 或繼續瀏覽。",
|
||||
extensionCard: "瀏覽器擴充功能",
|
||||
signerCard: "簽章應用程式",
|
||||
secretKeyLink: "改用私密金鑰",
|
||||
whereBunker: "在哪裡取得 bunker?",
|
||||
},
|
||||
settingsPage: {
|
||||
trust: '信任',
|
||||
trustSub: '來源與顯示',
|
||||
|
|
|
|||
Loading…
Reference in a new issue