chore: Update translations
continuous-integration/drone/push Build is failing Details

This commit is contained in:
Kieran 2023-09-14 18:45:29 +00:00
parent a8f000d9d8
commit 9c05b6a101
21 changed files with 609 additions and 567 deletions

View File

@ -4,7 +4,11 @@ import Note from "../Note";
export default function Articles() {
const data = useArticles();
return <>
{orderDescending(data.data ?? []).map(a => <Note data={a} key={a.id} related={[]} />)}
return (
<>
{orderDescending(data.data ?? []).map(a => (
<Note data={a} key={a.id} related={[]} />
))}
</>
);
}

View File

@ -13,7 +13,8 @@ export function DeckNav() {
const unreadDms = 0;
const hasNotifications = false;
return <nav className="deck flex-column f-space">
return (
<nav className="deck flex-column f-space">
<div className="flex-column f-center g24">
<Link className="btn" to="/messages">
<Icon name="mail" size={24} />
@ -32,11 +33,9 @@ export function DeckNav() {
<Icon name="settings-02" size={24} />
</Link>
<Link to={profileLink(publicKey ?? "")}>
<Avatar
pubkey={publicKey ?? ""}
user={profile}
/>
<Avatar pubkey={publicKey ?? ""} user={profile} />
</Link>
</div>
</nav>
);
}

View File

@ -3,7 +3,17 @@ import React, { useMemo, useState, ReactNode } from "react";
import { useNavigate, Link } from "react-router-dom";
import { useInView } from "react-intersection-observer";
import { useIntl, FormattedMessage } from "react-intl";
import { TaggedNostrEvent, HexKey, EventKind, NostrPrefix, Lists, EventExt, parseZap, tagToNostrLink, createNostrLinkToEvent } from "@snort/system";
import {
TaggedNostrEvent,
HexKey,
EventKind,
NostrPrefix,
Lists,
EventExt,
parseZap,
tagToNostrLink,
createNostrLinkToEvent,
} from "@snort/system";
import { System } from "index";
import useEventPublisher from "Feed/EventPublisher";
@ -200,19 +210,22 @@ export function NoteInner(props: NoteProps) {
const image = findTag(ev, "image");
return (
<div className="long-form-note">
<h3>
{title}
</h3>
<h3>{title}</h3>
<div className="text">
<p>
{summary}
</p>
<Text id={ev.id} content={ev.content} tags={ev.tags} creator={ev.pubkey} depth={props.depth} truncate={255} disableLinkPreview={true} />
<p>{summary}</p>
<Text
id={ev.id}
content={ev.content}
tags={ev.tags}
creator={ev.pubkey}
depth={props.depth}
truncate={255}
disableLinkPreview={true}
/>
{image && <ProxyImg src={image} />}
</div>
</div>
)
);
} else {
const body = ev?.content ?? "";
return (
@ -226,7 +239,7 @@ export function NoteInner(props: NoteProps) {
/>
);
}
}
};
const transformBody = () => {
if (deletions?.length > 0) {
@ -297,7 +310,11 @@ export function NoteInner(props: NoteProps) {
const maxMentions = 2;
const replyTo = thread?.replyTo ?? thread?.root;
const replyLink = replyTo ? tagToNostrLink([replyTo.key, replyTo.value ?? "", replyTo.relay ?? "", replyTo.marker ?? ""].filter(a => a.length > 0)) : undefined;
const replyLink = replyTo
? tagToNostrLink(
[replyTo.key, replyTo.value ?? "", replyTo.relay ?? "", replyTo.marker ?? ""].filter(a => a.length > 0),
)
: undefined;
const mentions: { pk: string; name: string; link: ReactNode }[] = [];
for (const pk of thread?.pubKeys ?? []) {
const u = UserCache.getFromCache(pk);
@ -330,11 +347,7 @@ export function NoteInner(props: NoteProps) {
{pubMentions} {others}
</>
) : (
replyLink && (
<Link to={`/e/${replyLink.encode()}`}>
{replyLink.encode().substring(0, 12)}
</Link>
)
replyLink && <Link to={`/e/${replyLink.encode()}`}>{replyLink.encode().substring(0, 12)}</Link>
)}
</div>
);

View File

@ -15,4 +15,3 @@
justify-content: center;
gap: 12px;
}

View File

@ -7,8 +7,14 @@ import { FormattedMessage } from "react-intl";
import useLogin from "Hooks/useLogin";
import Icon from "Icons/Icon";
export type RootTab = "following" | "conversations" | "trending-notes" | "trending-people" | "suggested" | "tags" | "global";
export type RootTab =
| "following"
| "conversations"
| "trending-notes"
| "trending-people"
| "suggested"
| "tags"
| "global";
export function RootTabs({ base }: { base?: string }) {
const navigate = useNavigate();
@ -109,7 +115,6 @@ export function RootTabs({ base }: { base?: string }) {
return menuItems.find(a => a.tab === rootType)?.element;
}
return (
<div className="root-type">
<Menu

View File

@ -53,7 +53,6 @@ export function SpotlightMedia(props: SpotlightMediaProps) {
);
}
export function SpotlightMediaModal(props: SpotlightMediaProps) {
return (
<Modal onClose={props.onClose} className="spotlight">

View File

@ -2,13 +2,7 @@ import "./Thread.css";
import { useMemo, useState, ReactNode, useContext } from "react";
import { useIntl } from "react-intl";
import { useNavigate, Link, useParams } from "react-router-dom";
import {
TaggedNostrEvent,
u256,
NostrPrefix,
EventExt,
parseNostrLink,
} from "@snort/system";
import { TaggedNostrEvent, u256, NostrPrefix, EventExt, parseNostrLink } from "@snort/system";
import { eventLink, getReactions, getAllReactions } from "SnortUtils";
import BackButton from "Element/BackButton";
@ -160,7 +154,8 @@ const TierThree = ({ active, isLastSubthread, notes, related, chains, onNavigate
return (
<>
<div
className={`subthread-container ${hasMultipleNotes ? "subthread-multi" : ""} ${isLast ? "subthread-last" : "subthread-mid"
className={`subthread-container ${hasMultipleNotes ? "subthread-multi" : ""} ${
isLast ? "subthread-last" : "subthread-mid"
}`}>
<Divider variant="small" />
<Note
@ -190,7 +185,8 @@ const TierThree = ({ active, isLastSubthread, notes, related, chains, onNavigate
return (
<div
key={r.id}
className={`subthread-container ${lastReply ? "" : "subthread-multi"} ${lastReply ? "subthread-last" : "subthread-mid"
className={`subthread-container ${lastReply ? "" : "subthread-multi"} ${
lastReply ? "subthread-last" : "subthread-mid"
}`}>
<Divider variant="small" />
<Note
@ -213,9 +209,11 @@ export function ThreadRoute() {
const params = useParams();
const link = parseNostrLink(params.id ?? "", NostrPrefix.Note);
return <ThreadContextWrapper link={link}>
return (
<ThreadContextWrapper link={link}>
<Thread />
</ThreadContextWrapper>
);
}
export function Thread() {

View File

@ -113,9 +113,12 @@ const TimelineFollows = (props: TimelineFollowsProps) => {
)}
</>
)}
{mainFeed.map(a => props.noteRenderer?.(a) ?? (
{mainFeed.map(
a =>
props.noteRenderer?.(a) ?? (
<Note data={a as TaggedNostrEvent} related={relatedFeed(a.id)} key={a.id} depth={0} />
))}
),
)}
<div className="flex f-center p">
<AsyncButton
onClick={async () => {

View File

@ -9,10 +9,7 @@ export function useArticles() {
const sub = useMemo(() => {
if (!publicKey) return null;
const rb = new RequestBuilder(`articles:${publicKey}`);
rb.withFilter()
.kinds([EventKind.LongFormTextNote])
.authors(follows.item)
.limit(20);
rb.withFilter().kinds([EventKind.LongFormTextNote]).authors(follows.item).limit(20);
return rb;
}, [follows.timestamp]);

View File

@ -16,7 +16,7 @@ export function useTheme() {
useEffect(() => {
const osTheme = window.matchMedia("(prefers-color-scheme: light)");
setTheme(
preferences.theme === "system" && osTheme.matches ? "light" : preferences.theme === "light" ? "light" : "dark"
preferences.theme === "system" && osTheme.matches ? "light" : preferences.theme === "light" ? "light" : "dark",
);
osTheme.onchange = e => {
@ -28,5 +28,4 @@ export function useTheme() {
osTheme.onchange = null;
};
}, [preferences.theme]);
}

View File

@ -1,21 +1,29 @@
import { unwrap } from "@snort/shared";
import { EventExt, EventKind, NostrLink, NostrPrefix, TaggedNostrEvent, u256, Thread as ThreadInfo, } from "@snort/system";
import {
EventExt,
EventKind,
NostrLink,
NostrPrefix,
TaggedNostrEvent,
u256,
Thread as ThreadInfo,
} from "@snort/system";
import useThreadFeed from "Feed/ThreadFeed";
import { findTag } from "SnortUtils";
import { ReactNode, createContext, useMemo, useState } from "react";
import { useLocation } from "react-router-dom";
export interface ThreadContext {
current: string,
root?: TaggedNostrEvent,
chains: Map<string, Array<TaggedNostrEvent>>,
data: Array<TaggedNostrEvent>,
current: string;
root?: TaggedNostrEvent;
chains: Map<string, Array<TaggedNostrEvent>>;
data: Array<TaggedNostrEvent>;
setCurrent: (i: string) => void;
}
export const ThreadContext = createContext({} as ThreadContext)
export const ThreadContext = createContext({} as ThreadContext);
export function ThreadContextWrapper({ link, children }: { link: NostrLink, children?: ReactNode }) {
export function ThreadContextWrapper({ link, children }: { link: NostrLink; children?: ReactNode }) {
const location = useLocation();
const [currentId, setCurrentId] = useState(link.id);
const thread = useThreadFeed(link);
@ -32,7 +40,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
if (t?.root?.key === "a" && t?.root?.value) {
const parsed = t.root.value.split(":");
replyTo = thread.data?.find(
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2]
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2],
)?.id;
}
if (replyTo) {
@ -53,7 +61,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
thread.data?.find(
ne =>
ne.id === currentId ||
(link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author)
(link.type === NostrPrefix.Address && findTag(ne, "d") === currentId && ne.pubkey === link.author),
) ?? (location.state && "sig" in location.state ? (location.state as TaggedNostrEvent) : undefined);
if (currentNote) {
const currentThread = EventExt.extractThread(currentNote);
@ -69,7 +77,7 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
if (replyTo.key === "a" && replyTo.value) {
const parsed = replyTo.value.split(":");
return thread.data?.find(
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2]
a => a.kind === Number(parsed[0]) && a.pubkey === parsed[1] && findTag(a, "d") === parsed[2],
);
}
if (replyTo.value) {
@ -100,11 +108,9 @@ export function ThreadContextWrapper({ link, children }: { link: NostrLink, chil
root,
chains,
data: thread.data,
setCurrent: v => setCurrentId(v)
} as ThreadContext
setCurrent: v => setCurrentId(v),
} as ThreadContext;
}, [root, chains]);
return <ThreadContext.Provider value={ctxValue}>
{children}
</ThreadContext.Provider>
return <ThreadContext.Provider value={ctxValue}>{children}</ThreadContext.Provider>;
}

View File

@ -61,7 +61,7 @@
flex-direction: row;
border-radius: unset;
gap: 16px;
--border-color: #3A3A3A;
--border-color: #3a3a3a;
}
.thread-overlay .modal-body > div:last-of-type {

View File

@ -41,19 +41,25 @@ export function SnortDeckLayout() {
if (!login.publicKey) return null;
const cols = ["notes", "media", "notifications", "articles"] as Array<Cols>;
return <div className="deck-layout">
return (
<div className="deck-layout">
<DeckNav />
<div className="deck-cols">
{cols.map(c => {
switch (c) {
case "notes": return <NotesCol />
case "media": return <MediaCol setThread={setThread} />
case "articles": return <ArticlesCol />
case "notifications": return <NotificationsCol />
case "notes":
return <NotesCol />;
case "media":
return <MediaCol setThread={setThread} />;
case "articles":
return <ArticlesCol />;
case "notifications":
return <NotificationsCol />;
}
})}
</div>
{thread && <>
{thread && (
<>
<Modal onClose={() => setThread(undefined)} className="thread-overlay">
<ThreadContextWrapper link={createNostrLink(NostrPrefix.Note, thread)}>
<SpotlightFromThread onClose={() => setThread(undefined)} />
@ -62,9 +68,11 @@ export function SnortDeckLayout() {
</div>
</ThreadContextWrapper>
</Modal>
</>}
</>
)}
<Toaster />
</div>
);
}
function SpotlightFromThread({ onClose }: { onClose: () => void }) {
@ -73,7 +81,7 @@ function SpotlightFromThread({ onClose }: { onClose: () => void }) {
const parsed = thread.root ? transformTextCached(thread.root.id, thread.root.content, thread.root.tags) : [];
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return <SpotlightMedia images={images.map(a => a.content)} idx={0} onClose={onClose} />
return <SpotlightMedia images={images.map(a => a.content)} idx={0} onClose={onClose} />;
}
function NotesCol() {
@ -118,25 +126,37 @@ function MediaCol({ setThread }: { setThread: (e: string) => void }) {
<FormattedMessage defaultMessage="Media" />
</div>
<div className="image-grid p">
<TimelineFollows postsOnly={true} liveStreams={false} noteFilter={e => {
<TimelineFollows
postsOnly={true}
liveStreams={false}
noteFilter={e => {
const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return images.length > 0;
}} noteRenderer={e => {
}}
noteRenderer={e => {
const parsed = transformTextCached(e.id, e.content, e.tags);
const images = parsed.filter(a => a.type === "media" && a.mimeType?.startsWith("image/"));
return <div className="media-note" key={e.id} style={{
"--img": `url(${proxy(images[0].content)})`
} as CSSProperties} onClick={() => setThread(e.id)}></div>
}} />
return (
<div
className="media-note"
key={e.id}
style={
{
"--img": `url(${proxy(images[0].content)})`,
} as CSSProperties
}
onClick={() => setThread(e.id)}></div>
);
}}
/>
</div>
</div>
);
}
function NotificationsCol() {
return (
<div>
<div className="deck-col-header flex g8">

View File

@ -164,12 +164,12 @@ const DefaultTab = () => {
const tab = publicKey ? preferences.defaultRootTab ?? `notes` : `trending/notes`;
const elm = RootTabRoutes.find(a => a.path === tab)?.element;
return elm;
}
};
export const RootTabRoutes = [
{
path: "",
element: <DefaultTab />
element: <DefaultTab />,
},
{
path: "global",

View File

@ -262,7 +262,7 @@ button.icon:hover {
}
.light .btn {
color: #64748B;
color: #64748b;
}
.btn-warn {

View File

@ -211,8 +211,8 @@ export const router = createBrowserRouter([
}
return null;
},
children: RootTabRoutes
}
children: RootTabRoutes,
},
]);
const root = ReactDOM.createRoot(unwrap(document.getElementById("root")));

View File

@ -10,8 +10,8 @@
"/4tOwT": "Überspringen",
"/JE/X+": "Konto Hilfe",
"/PCavi": "Öffentlich",
"/RD0e2": "Nostr nutzt digitale Signaturen, um manipulationssichere Notes zu erstellen, welche sicher auf viele Relays repliziert werden können, um eine redundante Speicherung deiner Inhalte zu bieten.",
"/Xf4UW": "Send anonymous usage metrics",
"/RD0e2": "Nostr nutzt digitale Signaturen, um manipulationssichere Notes zu erstellen, welche sicher auf viele Relais repliziert werden können, um eine redundante Speicherung deiner Inhalte zu bieten.",
"/Xf4UW": "Anonyme Nutzungsmetriken senden",
"/d6vEc": "Mach dein Profil leichter zu finden und zu teilen",
"/n5KSF": "{n} ms",
"00LcfG": "Mehr laden",
@ -52,7 +52,7 @@
"4Z3t5i": "Verwende imgproxy um Bilder zu komprimieren",
"4rYCjn": "Notiz an mich selbst",
"5BVs2e": "Zap",
"5CB6zB": "Zap Splits",
"5CB6zB": "Zap-Aufteilungen",
"5JcXdV": "Konto erstellen",
"5oTnfy": "Handle kaufen",
"5rOdPG": "Sobald du deine Erweiterung für die Schlüsselverwaltung eingerichtet und einen Schlüssel generiert hast, kannst du unserem Prozess für neue Benutzer folgen, um dein Profil einzurichten und einige interessante Leute auf Nostr zu finden, denen du folgen kannst.",
@ -61,7 +61,7 @@
"5ykRmX": "Zap senden",
"65BmHb": "Bild von {host} konnte nicht durch Proxy geladen werden, klicke hier, um es direkt zu laden",
"6Yfvvp": "Bekomme eine Identifikation",
"6bgpn+": "Not all clients support this, you may still receive some zaps as if zap splits was not configured",
"6bgpn+": "Nicht alle Clients unterstützen dies, deshalb kann es sein, dass du immer noch einige Zaps erhältst, als ob Zap-Aufteilungen nicht konfiguriert wäre",
"6ewQqw": "Gefällt ({n})",
"6uMqL1": "Nicht bezahlt",
"7+Domh": "Notes",
@ -69,8 +69,8 @@
"7hp70g": "NIP-05",
"8/vBbP": "Reposts ({n})",
"89q5wc": "Reposts bestätigen",
"8QDesP": "Zap {n} sats",
"8Y6bZQ": "Invalid zap split: {input}",
"8QDesP": "{n} sats zappen",
"8Y6bZQ": "Ungültige Zap-Aufteilung: {input}",
"8g2vyB": "Name ist zu lang",
"8v1NN+": "Verbindungsphrase",
"9+Ddtu": "Weiter",
@ -81,7 +81,7 @@
"9pMqYs": "Nostr-Adresse",
"9wO4wJ": "Lightning Zahlungsanforderung",
"ADmfQT": "Vorherige",
"AGNz71": "Zap {n} sats an Alle",
"AGNz71": "Allen {n} sats zappen",
"ASRK0S": "Dieser Autor wurde stummgeschalten",
"Adk34V": "Profil erstellen",
"Ai8VHU": "Unbegrenzte Note Speicherung auf Snort Relais",
@ -91,7 +91,7 @@
"B4C47Y": "Name ist zu kurz",
"B6+XJy": "hat gezappt",
"B6H7eJ": "nsec, npub, nip-05, hex",
"BGCM48": "Schreibe Zugriff auf Snort-Relais mit 1 Jahr Event Speicherung",
"BGCM48": "Schreibzugriff auf Snort Relais, mit 1 Jahr Speicherung von Events",
"BOUMjw": "Keine Nostr-Benutzer gefunden für {twitterUsername}",
"BOr9z/": "Snort ist ein Open-Source-Projekt, von begeisterten in ihrer Freizeit entwickelt",
"BWpuKl": "Aktualisieren",
@ -116,7 +116,7 @@
"EPYwm7": "Dein privater Schlüssel ist dein Passwort. Wenn du diesen Schlüssel verlierst, hast du keinen Zugang mehr zu deinem Konto! Kopiere ihn und bewahre ihn an einem sicheren Ort auf. Es gibt keine Möglichkeit, deinen privaten Schlüssel wiederherzustellen.",
"EWyQH5": "Global",
"Ebl/B2": "Auf {lang} Übersetzen",
"EcZF24": "Benutzerdefinierte Relays",
"EcZF24": "Benutzerdefinierte Relais",
"EcglP9": "Schlüssel",
"EnCOBJ": "Kaufen",
"Eqjl5K": "Nur Snort und unsere integrierten Partner bieten farbige Domainnamen als NIP-05 Kennzeichen. Sie können aber auch gerne andere Dienste nutzen.",
@ -145,7 +145,7 @@
"HOzFdo": "Stummgeschaltet",
"HWbkEK": "Cache leeren und neu laden",
"HbefNb": "Wallet öffnen",
"I9zn6f": "Pubkey",
"I9zn6f": "Öfftl. Schlüssel",
"IDjHJ6": "Danke für die Verwendung von Snort. Wir würden uns über eine Spende freuen.",
"IEwZvs": "Sind sie sicher, dass sie diese Notiz entpinnen möchten?",
"IKKHqV": "Folgt",
@ -155,7 +155,7 @@
"Ix8l+B": "Angesagte Notes",
"J+dIsA": "Abonnements",
"JCIgkj": "Benutzername",
"JGrt9q": "Send sats to {name}",
"JGrt9q": "Sats an {name} senden",
"JHEHCk": "Zaps ({n})",
"JPFYIM": "Keine Lightning-Adresse",
"JeoS4y": "Repost",
@ -175,7 +175,7 @@
"LgbKvU": "Kommentar",
"Lu5/Bj": "In Zapstr öffnen",
"Lw+I+J": "{n,plural,=0{{name} zappte} other{{name} & {n} andere zappten}}",
"LwYmVi": "Zaps on this note will be split to the following users.",
"LwYmVi": "Zaps auf diese Note werden an die folgenden Nutzer aufgeteilt.",
"M3Oirc": "Debug Menüs",
"MBAYRO": "Zeigt \"ID kopieren\" und \"Event JSON kopieren\" im Kontextmenu jeder Nachricht an",
"MI2jkA": "Nicht verfügbar:",
@ -221,7 +221,7 @@
"RoOyAh": "Relais",
"Rs4kCE": "Lesezeichen",
"RwFaYs": "Sortieren",
"SMO+on": "Send zap to {name}",
"SMO+on": "Zap an {name} senden",
"SOqbe9": "Lightning-Adresse aktualisieren",
"SP0+yi": "Abonnement kaufen",
"SX58hM": "Kopieren",
@ -251,10 +251,10 @@
"W2PiAr": "{n} Blockiert",
"W9355R": "Stummschaltung aufheben",
"WONP5O": "Finden Sie Ihre Twitter Kontakte auf Nostr (Daten zur Verfügung gestellt von {provider})",
"WvGmZT": "npub / nprofile / nostr address",
"WvGmZT": "npub / nprofile / Nostr-Adresse",
"WxthCV": "z.B. Jack",
"X7xU8J": "nsec, npub, nip-05, hex, mnemonic",
"XECMfW": "Send usage metrics",
"XECMfW": "Nutzungsmetriken senden",
"XICsE8": "Datei-Hosts",
"XgWvGA": "Reaktionen",
"Xopqkl": "Dein standardmäßiger Zap-Betrag ist {number} sats, Beispielwerte werden daraus berechnet.",
@ -263,7 +263,7 @@
"Y31HTH": "Unterstütze die Entwicklung von Snort",
"YDURw6": "URL des Dienstes",
"YXA3AH": "Reaktionen aktivieren",
"Z0FDj+": "Abonniere Snort {plan} für {price} und erhalte folgende Belohnungen",
"Z0FDj+": "Abonniere Snort {plan} für {price} und erhalte folgende Prämien",
"Z4BMCZ": "Verbindungs-Passphrase eingeben",
"ZKORll": "Jetzt aktivieren",
"ZLmyG9": "Mitwirkende",
@ -340,11 +340,11 @@
"jvo0vs": "Speichern",
"jzgQ2z": "{n} Reaktionen",
"k2veDA": "Schreiben",
"k7sKNy": "Unser eigener NIP-05-Verifizierungsdienst unterstützt die Entwicklung dieser Website. Unterstütze uns und erhalte ein Sonderabzeichen für deine Webseite!",
"k7sKNy": "Unser eigener NIP-05-Verifizierungsdienst unterstützt die Entwicklung dieser Website. Unterstütze uns und erhalte ein Abzeichen auf unserer Seite!",
"kJYo0u": "{n,plural,=0{{name} hat gerepostet} other{{name} & {n} andere haben gerepostet}}",
"kaaf1E": "jetzt",
"kuPHYE": "{n,plural,=0{{name} gefällt das} other{{name} & {n} anderen gefällt das}}",
"l+ikU1": "Alles im {plan}",
"l+ikU1": "Alles aus {plan}",
"lBboHo": "Wenn du ein paar andere ausprobieren möchtest, besuche {link} für mehr!",
"lCILNz": "Jetzt kaufen",
"lD3+8a": "Bezahlen",
@ -380,7 +380,7 @@
"oxCa4R": "Das Erhalten eines Identifikators hilft Menschen, die Sie kennen, Ihre Identität zu bestätigen. Viele Leute können einen Benutzernamen wie @jack haben, aber es kann nur einen jack@cash.app geben.",
"p4N05H": "Hochladen",
"p85Uwy": "Aktive Abonnements",
"pI+77w": "Herunterladbare Backups von Snort Relais",
"pI+77w": "Herunterladbare Backups vom Snort Relais",
"puLNUJ": "Anheften",
"pzTOmv": "Follower",
"qD9EUF": "E-Mail <> DM Brücke für deine Snort Nostr-Adresse",
@ -401,19 +401,19 @@
"rudscU": "Abonnements konnten nicht geladen werden, bitte versuchen Sie es später erneut",
"sUNhQE": "Nutzer",
"sWnYKw": "Snort wurde darauf konzipiert ein Twitter ähnliches Erlebnis zu bieten.",
"sZQzjQ": "Failed to parse zap split: {input}",
"sZQzjQ": "Fehler beim Parsen der Zap-Aufteilung: {input}",
"svOoEH": "Namens-Squatting und Impersonation sind nicht erlaubt. Snort und unsere Partner behalten sich das Recht vor, bei einem Verstoß gegen diese Regel dein Handle zu löschen (nicht dein Konto - das kann dir niemand wegnehmen).",
"tOdNiY": "Dunkel",
"th5lxp": "Sende Note zu einer Untergruppe deiner Schreib-Relays",
"thnRpU": "Eine NIP-05 Verifizierung kann helfen:",
"ttxS0b": "Unterstützer Abzeichen",
"ttxS0b": "Unterstützer-Abzeichen",
"u/vOPu": "Bezahlt",
"u4bHcR": "Sieh dir hier den Code an: {link}",
"uSV4Ti": "Reposts müssen manuell bestätigt werden",
"usAvMr": "Profil anpassen",
"ut+2Cd": "Holen Sie sich einen Partner-Identifikator",
"v8lolG": "Chat starten",
"vOKedj": "{n,plural,one {}=1{& {n} other} other{& {n} andere}}",
"vOKedj": "{n,plural,one {}=1{& {n} anderer} other{& {n} andere}}",
"vU71Ez": "Bezahlen mit {wallet}",
"vZ4quW": "NIP-05 ist eine DNS-basierte Verifizierungsspezifikation, die dabei hilft, dich als echten Benutzer zu validieren.",
"vhlWFg": "Umfrageoptionen",
@ -442,7 +442,7 @@
"y1Z3or": "Sprache",
"yCLnBC": "LNURL oder Lightning-Adresse",
"yCmnnm": "Global lesen von",
"zCb8fX": "Weight",
"zCb8fX": "Gewichtung",
"zFegDD": "Kontakt",
"zINlao": "Eigentümer",
"zQvVDJ": "Alle",