diff --git a/public/hero/ve-quake-1.jpg b/public/hero/ve-quake-1.jpg new file mode 100644 index 00000000..3b3b94b1 Binary files /dev/null and b/public/hero/ve-quake-1.jpg differ diff --git a/public/hero/ve-quake-2.jpg b/public/hero/ve-quake-2.jpg new file mode 100644 index 00000000..f5410e93 Binary files /dev/null and b/public/hero/ve-quake-2.jpg differ diff --git a/public/hero/ve-quake-3.jpg b/public/hero/ve-quake-3.jpg new file mode 100644 index 00000000..3d01b2f2 Binary files /dev/null and b/public/hero/ve-quake-3.jpg differ diff --git a/src/components/HeroBanner.tsx b/src/components/HeroBanner.tsx index e51c25ed..71050225 100644 --- a/src/components/HeroBanner.tsx +++ b/src/components/HeroBanner.tsx @@ -38,6 +38,14 @@ interface Layer { id: number; /** URL of the image rendered on this layer. */ url: string; + /** + * Whether this layer has been flipped to its visible opacity. A new + * layer mounts with `entered: false` (opacity 0) and is flipped to + * `true` on the next animation frame so the CSS opacity transition + * actually fires — without this two-step the browser paints the layer + * straight at its final opacity and the crossfade looks instant. + */ + entered: boolean; } const FADE_MS = 1500; @@ -61,7 +69,7 @@ export function HeroBanner({ const [index, setIndex] = useState(0); const idRef = useRef(0); const [layers, setLayers] = useState(() => - images.length > 0 ? [{ id: 0, url: images[0] }] : [], + images.length > 0 ? [{ id: 0, url: images[0], entered: true }] : [], ); // Honor the user's reduced-motion preference. We freeze the rotation @@ -90,17 +98,34 @@ export function HeroBanner({ return () => window.clearInterval(id); }, [images, intervalMs]); - // Whenever the active index changes, push a new layer on top. Old - // layers are reaped after the crossfade completes. + // Whenever the active index changes, push a new layer on top. The + // layer mounts hidden (`entered: false`) and is flipped visible on the + // next animation frame so the opacity transition animates instead of + // snapping. Old layers are reaped after the crossfade completes. useEffect(() => { if (images.length === 0) return; const url = images[index % images.length]; const id = ++idRef.current; - setLayers((prev) => [...prev, { id, url }]); + setLayers((prev) => [...prev, { id, url, entered: false }]); + + const raf = window.requestAnimationFrame(() => { + // Second frame guarantees the browser has painted the layer at + // opacity 0 before we transition it to 1. + window.requestAnimationFrame(() => { + setLayers((prev) => + prev.map((l) => (l.id === id ? { ...l, entered: true } : l)), + ); + }); + }); + const timeout = window.setTimeout(() => { setLayers((prev) => prev.filter((l) => l.id === id)); }, FADE_MS + 50); - return () => window.clearTimeout(timeout); + + return () => { + window.cancelAnimationFrame(raf); + window.clearTimeout(timeout); + }; }, [index, images]); // Preload the next image during idle time so the next crossfade @@ -119,14 +144,13 @@ export function HeroBanner({ className={cn('absolute inset-0 overflow-hidden', className)} aria-hidden="true" > - {layers.map((layer, i) => { - const isTop = i === layers.length - 1; + {layers.map((layer) => { return (
diff --git a/src/components/VenezuelaReliefBanner.tsx b/src/components/VenezuelaReliefBanner.tsx new file mode 100644 index 00000000..cb49eccd --- /dev/null +++ b/src/components/VenezuelaReliefBanner.tsx @@ -0,0 +1,182 @@ +import { Link } from 'react-router-dom'; +import { Trans, useTranslation } from 'react-i18next'; +import { HeartHandshake, PlusCircle } from 'lucide-react'; + +import { Button } from '@/components/ui/button'; +import { HeroBanner } from '@/components/HeroBanner'; +import { StartCampaignLink } from '@/components/StartCampaignLink'; +import { cn } from '@/lib/utils'; + +/** + * Ordered set of news photographs from the Venezuela earthquake that + * rotate behind the relief banner. They live in `/public/hero/` and use + * the shared {@link HeroBanner} crossfade + slow-pan treatment, the same + * animation as the site's other page heroes. Photo attributions are + * surfaced generically in the `credit` copy beneath the banner. + */ +const VENEZUELA_RELIEF_IMAGES: readonly string[] = [ + '/hero/ve-quake-1.jpg', // residents embrace near a collapsed building (AFP/Getty) + '/hero/ve-quake-2.jpg', // community + rescue workers search the rubble (AP) + '/hero/ve-quake-3.jpg', // severe building damage in Caracas (AFP/Getty) +]; + +/** + * Full-bleed emergency relief banner pinned to the very top of the + * home page during the Venezuela earthquake response. + * + * This is deliberately loud — a disaster appeal, not a subtle promo: + * + * - A full-bleed crossfading gallery of news photographs from the + * quake (via the shared {@link HeroBanner}: slow pan + crossfade, + * reduced-motion aware) sits behind the copy. A light dark gradient + * keeps the headline and CTAs readable while letting the photos stay + * the focus. + * - A large display headline ("Venezuela needs you") with the final + * word painted inside a solid brand-orange highlighter block — the + * same idiom as the home hero's "unstoppable". + * - Two unmistakable calls to action: **Donate to relief** deep-links + * to the Venezuela-filtered campaign browse (`/campaigns?country=VE`) + * so donors land straight on fundable relief campaigns; **Raise funds + * for Venezuela** routes organizers through `StartCampaignLink` + * (auth-gated) to publish a new fundraiser. + * + * Not dismissible by design — while the appeal is active it stays put + * for every visitor (product decision). When the response winds down, + * remove `` from {@link CampaignsPage}. + * + * All copy lives under `campaigns.home.venezuelaRelief.*` in the + * locale files so every shipped language stays in sync. + */ +export function VenezuelaReliefBanner({ className }: { className?: string }) { + const { t } = useTranslation(); + + return ( +
+ {/* Layer 1 — full-bleed crossfading photo gallery. A long + interval gives a slow, contemplative pacing; HeroBanner's + built-in 1.5s crossfade + slow pan handles the dissolve. */} + + + {/* Layer 2 — readability gradient. Lighter than a typical hero + overlay so the photograph stays the focus: a gentle vertical + darken plus a horizontal start-edge darken. The horizontal + stops are pinned with explicit percentages (rather than the + default even thirds) so the dark backing reliably reaches the + end of the centred content column on ultrawide screens and + fades to a clean transparent on the trailing half. */} +
+ ); +} + +export default VenezuelaReliefBanner; diff --git a/src/locales/ar.json b/src/locales/ar.json index d0cd66ec..f0c9f9ef 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "حملاتك منشورة على Nostr وتعمل التبرعات عبر رابط الحملة. تصفّح كل الحملات على /campaigns؛ ويختار فريق {{appName}} مجموعة منتقاة لعرضها على الصفحة الرئيسية.", "empty": "لا توجد حملات بعد", "emptyHint": "كن أول من يبدأ حملة تمويل على {{appName}}. اروِ قصتك، اختر المستفيدين، وشارك الرابط.", + "venezuelaRelief": { + "title": "فنزويلا بحاجة <0>إليك", + "body": "ضرب زلزال قويّ شمال فنزويلا، وكانت كاراكاس ولا غوايرا الأشدّ تضرّرًا. لا تستطيع العائلات هناك تجاوز هذه المحنة وحدها. تبرّعك يذهب مباشرة إلى حملات الإغاثة على الأرض، فيحوّل رحمتك اليوم إلى مأوى وطعام وأمل.", + "donate": "تبرّع للإغاثة", + "startCampaign": "اجمع التبرّعات من أجل فنزويلا", + "credit": "صور من كاراكاس، فنزويلا. ‏(AP؛ AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "لماذا {{appName}}", "title": "مبني بشكل مختلف.", diff --git a/src/locales/en.json b/src/locales/en.json index 656ead9b..934d9c22 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1442,7 +1442,7 @@ "home": { "seoTitle": "Fundraisers", "seoDescription": "Connecting the world to unstoppable funding.", - "heroTagline": "Connecting the\u00a0world to<1><0>unstoppable funding.", + "heroTagline": "Connecting the world to<1><0>unstoppable funding.", "heroBody": "Raise Bitcoin directly from supporters around the world. Every donation settles straight to your wallet, with no middlemen, no chargebacks, and no platform holding your funds.", "startCampaign": "Start a campaign", "verifyCampaigns": "Verify campaigns", @@ -1463,6 +1463,13 @@ "yourCampaignsDesc": "Your campaigns are live on Nostr and donations work via the campaign link. Browse all campaigns at /campaigns; the {{appName}} team features a curated selection on the homepage.", "empty": "No campaigns yet", "emptyHint": "Be the first to start a fundraiser on {{appName}}. Tell your story, choose your beneficiaries, and share the link.", + "venezuelaRelief": { + "title": "Venezuela needs <0>you", + "body": "A powerful earthquake has struck northern Venezuela, hitting Caracas and La Guaira hardest. Families there can't get through this alone. Your donation goes straight to relief campaigns on the ground, turning your compassion into shelter, food, and hope today.", + "donate": "Donate to relief", + "startCampaign": "Raise funds for Venezuela", + "credit": "Photos from Caracas, Venezuela. (AP; AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Why {{appName}}", "title": "Built different.", diff --git a/src/locales/es.json b/src/locales/es.json index 1c9e86f2..38d06556 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "Tus campañas están activas en Nostr y las donaciones funcionan mediante el enlace de la campaña. Explora todas las campañas en /campaigns; el equipo de {{appName}} destaca una selección curada en la página de inicio.", "empty": "Aún no hay campañas", "emptyHint": "Sé el primero en iniciar una recaudación en {{appName}}. Cuenta tu historia, elige a los beneficiarios y comparte el enlace.", + "venezuelaRelief": { + "title": "Venezuela <0>te necesita", + "body": "Un fuerte terremoto ha sacudido el norte de Venezuela, golpeando con mayor dureza a Caracas y La Guaira. Las familias de allí no pueden salir adelante solas. Tu donación va directa a las campañas de ayuda sobre el terreno, transformando hoy mismo tu compasión en refugio, alimento y esperanza.", + "donate": "Donar a la ayuda", + "startCampaign": "Recauda fondos para Venezuela", + "credit": "Fotos de Caracas, Venezuela. (AP; AFP vía Getty Images)" + }, "whyDifferent": { "eyebrow": "Por qué {{appName}}", "title": "Construido diferente.", diff --git a/src/locales/fa.json b/src/locales/fa.json index c5400c3a..c9bf6819 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "کمپین‌های شما در Nostr فعال هستند و کمک‌های مالی از طریق لینک کمپین کار می‌کنند. همه کمپین‌ها را در /campaigns مرور کنید؛ تیم {{appName}} مجموعه‌ای منتخب را در صفحه اصلی معرفی می‌کند.", "empty": "هنوز کمپینی وجود ندارد", "emptyHint": "اولین نفری باشید که در {{appName}} کمپین راه‌اندازی می‌کند. داستان خود را بگویید، ذی‌نفعان را انتخاب کنید، و لینک را به اشتراک بگذارید.", + "venezuelaRelief": { + "title": "Venezuela به <0>شما نیاز دارد", + "body": "زمین‌لرزه‌ای ویرانگر شمال Venezuela را لرزانده و بیش از همه Caracas و La Guaira را در هم کوبیده است. خانواده‌های آنجا نمی‌توانند به‌تنهایی از این مصیبت عبور کنند. کمک شما مستقیماً به کمپین‌های امدادرسانی در محل می‌رسد و دلسوزی‌تان را همین امروز به سرپناه، غذا و امید بدل می‌کند.", + "donate": "کمک به امدادرسانی", + "startCampaign": "جمع‌آوری کمک برای Venezuela", + "credit": "تصاویری از Caracas، ونزوئلا. ‏(AP؛ AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "چرا {{appName}}", "title": "متفاوت ساخته شده است.", diff --git a/src/locales/fr.json b/src/locales/fr.json index e5248cd0..1e2a9955 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1369,6 +1369,13 @@ "yourCampaignsDesc": "Vos campagnes sont en ligne sur Nostr et les dons fonctionnent via le lien de la campagne. Parcourez toutes les campagnes sur /campaigns ; l'équipe de {{appName}} met en avant une sélection sur la page d'accueil.", "empty": "Aucune campagne pour l'instant", "emptyHint": "Soyez le premier à démarrer une collecte de fonds sur {{appName}}. Racontez votre histoire, choisissez vos bénéficiaires et partagez le lien.", + "venezuelaRelief": { + "title": "Le Venezuela a besoin de <0>vous", + "body": "Un puissant séisme a frappé le nord du Venezuela, touchant le plus durement Caracas et La Guaira. Là-bas, les familles ne peuvent pas surmonter cette épreuve seules. Votre don va directement aux campagnes de secours sur le terrain et transforme votre compassion en abri, en nourriture et en espoir, dès aujourd'hui.", + "donate": "Faire un don aux secours", + "startCampaign": "Récolter des fonds pour le Venezuela", + "credit": "Photos de Caracas, au Venezuela. (AP ; AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Pourquoi {{appName}}", "title": "Conçu différemment.", diff --git a/src/locales/hi.json b/src/locales/hi.json index 04e97256..7df69a14 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -1373,6 +1373,13 @@ "searchAriaLabel": "कैंपेन खोजें", "noMatch": "“{{query}}” से मेल खाने वाला कोई कैंपेन नहीं", "noMatchHint": "अलग खोज शब्द आज़माएँ, या खोज साफ़ करें।", + "venezuelaRelief": { + "title": "Venezuela को <0>आपकी ज़रूरत है", + "body": "उत्तरी Venezuela में एक भीषण भूकंप आया है, जिसने Caracas और La Guaira को सबसे ज़्यादा तबाह किया है। वहाँ के परिवार इस मुश्किल वक़्त से अकेले नहीं उबर सकते। आपका दान सीधे ज़मीन पर चल रहे राहत अभियानों तक पहुँचता है, और आज ही आपकी करुणा को आसरा, भोजन और उम्मीद में बदल देता है।", + "donate": "राहत के लिए दान करें", + "startCampaign": "Venezuela के लिए धन जुटाएँ", + "credit": "Caracas, Venezuela की तस्वीरें। (AP; AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "क्यों {{appName}}", "title": "अलग ढंग से बना।", diff --git a/src/locales/id.json b/src/locales/id.json index ce01a9ac..adf25fe4 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -1373,6 +1373,13 @@ "searchAriaLabel": "Cari kampanye", "noMatch": "Tidak ada kampanye yang cocok dengan “{{query}}”", "noMatchHint": "Coba kata pencarian lain, atau bersihkan pencarian.", + "venezuelaRelief": { + "title": "Venezuela membutuhkan <0>Anda", + "body": "Gempa bumi dahsyat telah mengguncang Venezuela bagian utara, dengan dampak terparah di Caracas dan La Guaira. Keluarga-keluarga di sana tidak bisa melewati cobaan ini sendirian. Donasi Anda langsung mengalir ke kampanye bantuan di lapangan, mengubah belas kasih Anda menjadi tempat berlindung, makanan, dan harapan hari ini.", + "donate": "Donasi untuk bantuan", + "startCampaign": "Galang dana untuk Venezuela", + "credit": "Foto dari Caracas, Venezuela. (AP; AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Mengapa {{appName}}", "title": "Dibangun berbeda.", diff --git a/src/locales/km.json b/src/locales/km.json index fa938a52..8607465b 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "យុទ្ធនាការរបស់អ្នកនៅរស់នៅលើ Nostr ហើយការបរិច្ចាគដំណើរការតាមរយៈតំណយុទ្ធនាការ។ រកមើលយុទ្ធនាការទាំងអស់នៅ /campaigns; ក្រុម {{appName}} បង្ហាញការជ្រើសរើសដែលបានសម្រិតសម្រាំងនៅទំព័រដើម។", "empty": "មិនទាន់មានយុទ្ធនាការនៅឡើយ", "emptyHint": "ធ្វើជាមនុស្សដំបូងដែលចាប់ផ្ដើមការប្រមូលមូលនិធិនៅ {{appName}}។ ប្រាប់រឿងរបស់អ្នក ជ្រើសរើសអ្នកទទួលផល និងចែករំលែកតំណ។", + "venezuelaRelief": { + "title": "Venezuela ត្រូវការ<0>អ្នក", + "body": "រញ្ជួយដីដ៏ខ្លាំងមួយបានវាយប្រហារភាគខាងជើងនៃ Venezuela ដោយធ្វើឱ្យ Caracas និង La Guaira រងគ្រោះធ្ងន់ធ្ងរបំផុត។ គ្រួសារនៅទីនោះមិនអាចឆ្លងផុតវិបត្តិនេះតែម្នាក់ឯងបានឡើយ។ ការបរិច្ចាគរបស់អ្នកនឹងទៅដល់ដោយផ្ទាល់ទៅកាន់យុទ្ធនាការសង្គ្រោះនៅនឹងកន្លែង ប្រែក្លាយក្ដីមេត្តាករុណារបស់អ្នកទៅជាជម្រក អាហារ និងក្ដីសង្ឃឹមនៅថ្ងៃនេះ។", + "donate": "បរិច្ចាគដើម្បីសង្គ្រោះ", + "startCampaign": "ប្រមូលមូលនិធិសម្រាប់ Venezuela", + "credit": "រូបថតពី Caracas ប្រទេសវេណេស៊ុយអេឡា។ (AP; AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "ហេតុអ្វី {{appName}}", "title": "សាងសង់ខុសប្លែក។", diff --git a/src/locales/ps.json b/src/locales/ps.json index 62ecdfde..b079b8c6 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "ستاسو کمپاینونه په Nostr کې ژوندي دي او مرستې د کمپاین له لینک څخه کار کوي. ټول کمپاینونه په /campaigns کې وګورئ؛ د {{appName}} ټیم په کور پاڼه کې یوه ټاکل شوې ټولګه ښیي.", "empty": "تر اوسه کوم کمپاین نشته", "emptyHint": "په {{appName}} کې د مرستو راټولولو کمپاین پیل کوونکی لومړی شئ. خپله کیسه ووایاست، ګټه اخیستونکي وټاکئ، او لینک شریک کړئ.", + "venezuelaRelief": { + "title": "Venezuela <0>تاسو ته اړتیا لري", + "body": "یوې زورورې زلزلې د Venezuela شمال ولړزاوه، چې تر ټولو سخت زیان يې Caracas او La Guaira ته ورساوه. هلته کورنۍ يوازې له دې کړاو څخه نشي خلاصېدلی. ستاسو ډالۍ مستقیماً پر ځمکه فعالو مرستندویه کمپاینونو ته رسیږي، او ستاسو زړه‌سوی نن په سرپناه، خوراک او هیله بدلوي.", + "donate": "مرستې ته ډالۍ ورکړئ", + "startCampaign": "د Venezuela لپاره مرسته راټوله کړئ", + "credit": "انځور: اوسېدونکي د Caracas په یوه نړېدلې ودانۍ ترڅنګ یو بل غېږ کې نیسي. ‏(AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "ولې {{appName}}", "title": "په بل ډول جوړ شوی.", diff --git a/src/locales/pt.json b/src/locales/pt.json index bc1f3667..ee7d2926 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -1369,6 +1369,13 @@ "yourCampaignsDesc": "Suas campanhas estão no ar no Nostr e as doações funcionam através do link da campanha. Navegue por todas as campanhas em /campaigns; a equipe do {{appName}} apresenta uma seleção curada na página inicial.", "empty": "Nenhuma campanha ainda", "emptyHint": "Seja o primeiro a iniciar uma arrecadação no {{appName}}. Conte sua história, escolha seus beneficiários e compartilhe o link.", + "venezuelaRelief": { + "title": "A Venezuela precisa de <0>você", + "body": "Um forte terremoto atingiu o norte da Venezuela, castigando com mais força Caracas e La Guaira. As famílias de lá não conseguem superar isso sozinhas. Sua doação vai diretamente para as campanhas de ajuda no local, transformando hoje a sua compaixão em abrigo, comida e esperança.", + "donate": "Doar para a ajuda", + "startCampaign": "Arrecadar fundos para a Venezuela", + "credit": "Foto: moradores se abraçam perto de um prédio desabado em Caracas. (AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Por que o {{appName}}", "title": "Construído diferente.", diff --git a/src/locales/ru.json b/src/locales/ru.json index 9b231ad1..a94b6cbb 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1369,6 +1369,13 @@ "yourCampaignsDesc": "Ваши кампании уже в эфире в Nostr, и пожертвования работают через ссылку кампании. Просмотрите все кампании на /campaigns; команда {{appName}} выделяет отобранную подборку на главной странице.", "empty": "Пока нет кампаний", "emptyHint": "Будьте первым, кто запустит сбор средств на {{appName}}. Расскажите свою историю, выберите бенефициаров и поделитесь ссылкой.", + "venezuelaRelief": { + "title": "Венесуэле нужна <0>ваша помощь", + "body": "Мощное землетрясение обрушилось на север Венесуэлы, сильнее всего пострадали Caracas и La Guaira. Семьям там не справиться в одиночку. Ваше пожертвование идёт напрямую в кампании помощи на месте, превращая ваше сострадание в кров, еду и надежду уже сегодня.", + "donate": "Пожертвовать на помощь", + "startCampaign": "Собрать средства для Венесуэлы", + "credit": "Фото: жители обнимаются рядом с обрушившимся зданием в Caracas. (AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Почему {{appName}}", "title": "Сделано по-другому.", diff --git a/src/locales/sn.json b/src/locales/sn.json index 5501eed0..157d0eb9 100644 --- a/src/locales/sn.json +++ b/src/locales/sn.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "Mishandirapamwe yako iri panetwork yeNostr uye mipiro inoshanda kuburikidza nemurawu wemushandirapamwe. Tarisa mishandirapamwe yose pa/campaigns; boka re{{appName}} rinosarudza yakananga papeji rekutanga.", "empty": "Hapana mishandirapamwe parizvino", "emptyHint": "Iva wekutanga kutanga kuunganidza mari pa{{appName}}. Taura nyaya yako, sarudza vanobatsirwa, uchipa rwumwe rwekugovera.", + "venezuelaRelief": { + "title": "Venezuela <0>inokuda", + "body": "Kudengenyeka kwenyika kune simba kwakarova kuchamhembe kweVenezuela, kuchikuvadza Caracas neLa Guaira zvakanyanya. Mhuri dziri ikoko hadzigoni kupfuura mudambudziko iri dzega. Chipo chako chinonanga kumishandirapamwe yekubatsira iri panzvimbo, ichishandura tsitsi dzako kuva pekugara, chikafu, netariro nhasi.", + "donate": "Ipa kubatsira", + "startCampaign": "Unganidza mari yeVenezuela", + "credit": "Mufananidzo: vagari vachimbundirana pedyo nechivako chakawira muCaracas. (AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Sei {{appName}}", "title": "Yakavakwa zvakasiyana.", diff --git a/src/locales/sw.json b/src/locales/sw.json index 6d15a097..45716cad 100644 --- a/src/locales/sw.json +++ b/src/locales/sw.json @@ -1373,6 +1373,13 @@ "searchAriaLabel": "Tafuta kampeni", "noMatch": "Hakuna kampeni zinazolingana na “{{query}}”", "noMatchHint": "Jaribu neno tofauti la utafutaji, au futa utafutaji.", + "venezuelaRelief": { + "title": "Venezuela <0>inakuhitaji", + "body": "Tetemeko kubwa la ardhi limeikumba kaskazini mwa Venezuela, likiathiri vibaya zaidi maeneo ya Caracas na La Guaira. Familia zilizoko huko haziwezi kupita katika dhiki hii peke yao. Mchango wako unawafikia moja kwa moja wahanga kupitia kampeni za misaada zilizoko eneo la tukio, ukigeuza huruma yako kuwa makao, chakula, na matumaini leo.", + "donate": "Changia misaada", + "startCampaign": "Changisha fedha kwa ajili ya Venezuela", + "credit": "Picha: wakazi wakikumbatiana karibu na jengo lililoporomoka mjini Caracas. (AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Kwa nini {{appName}}", "title": "Imejengwa tofauti.", diff --git a/src/locales/tr.json b/src/locales/tr.json index 5990b714..c8fcbd73 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -1373,6 +1373,13 @@ "searchAriaLabel": "Kampanyaları ara", "noMatch": "“{{query}}” ile eşleşen kampanya yok", "noMatchHint": "Farklı bir arama terimi deneyin ya da aramayı temizleyin.", + "venezuelaRelief": { + "title": "Venezuela <0>size ihtiyaç duyuyor", + "body": "Kuzey Venezuela'yı şiddetli bir deprem vurdu; en ağır darbeyi Caracas ve La Guaira aldı. Oradaki aileler bu acıyı tek başlarına atlatamaz. Bağışınız doğrudan sahadaki yardım kampanyalarına ulaşır ve şefkatinizi bugün barınağa, gıdaya ve umuda dönüştürür.", + "donate": "Yardıma bağış yap", + "startCampaign": "Venezuela için fon toplayın", + "credit": "Fotoğraf: Caracas'ta çöken bir binanın yakınında kucaklaşan halk. (AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "Neden {{appName}}", "title": "Farklı inşa edildi.", diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json index fa0f4061..0bbe9cfb 100644 --- a/src/locales/zh-Hant.json +++ b/src/locales/zh-Hant.json @@ -931,6 +931,13 @@ "searchAriaLabel": "搜尋活動", "noMatch": "沒有活動符合「{{query}}」", "noMatchHint": "請嘗試不同的搜尋字詞,或清除搜尋。", + "venezuelaRelief": { + "title": "委內瑞拉需要<0>你", + "body": "一場強烈地震襲擊了 Venezuela 北部,其中 Caracas 與 La Guaira 受創最重。當地的家庭無法獨自撐過這場災難。你的捐款將直接送達當地的救援活動,讓你的關懷在今天就化為遮風避雨的住所、溫飽的食物,以及繼續走下去的希望。", + "donate": "捐助救援", + "startCampaign": "為委內瑞拉募款", + "credit": "照片:居民在 Caracas 一棟倒塌建築附近相擁。(AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "為什麼選擇 {{appName}}", "title": "生來不同。", diff --git a/src/locales/zh.json b/src/locales/zh.json index 722b854e..315d8f77 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -927,6 +927,13 @@ "yourCampaignsDesc": "你的活动已在 Nostr 上线,通过活动链接即可接收捐款。在 /campaigns 浏览所有活动;{{appName}} 团队会在首页展示精选活动。", "empty": "暂无活动", "emptyHint": "成为在 {{appName}} 发起众筹的第一人。讲述你的故事、选择受益人、并分享链接。", + "venezuelaRelief": { + "title": "委内瑞拉需要<0>你", + "body": "一场强烈地震袭击了委内瑞拉北部,Caracas 与 La Guaira 受灾最为严重。那里的家庭无法独自挺过这一切。你的捐款将直接送达灾区一线的救援活动,把你的善意化作今天的栖身之所、食物与希望。", + "donate": "为救援捐款", + "startCampaign": "为委内瑞拉筹款", + "credit": "图片:居民在 Caracas 一栋倒塌建筑附近相拥。(AFP via Getty Images)" + }, "whyDifferent": { "eyebrow": "为什么选 {{appName}}", "title": "我们与众不同。", diff --git a/src/pages/CampaignsPage.tsx b/src/pages/CampaignsPage.tsx index b1342f04..9255c1d1 100644 --- a/src/pages/CampaignsPage.tsx +++ b/src/pages/CampaignsPage.tsx @@ -19,6 +19,7 @@ import { CampaignListsStrip } from '@/components/campaign-lists/CampaignListsStr import { HeroLightningMap } from '@/components/HeroLightningMap'; import { StartCampaignLink } from '@/components/StartCampaignLink'; import { AppDownloadNudge } from '@/components/AppDownloadNudge'; +import { VenezuelaReliefBanner } from '@/components/VenezuelaReliefBanner'; import { useCampaigns } from '@/hooks/useCampaigns'; import { useCampaignList } from '@/hooks/useCampaignLists'; import { useAppContext } from '@/hooks/useAppContext'; @@ -129,6 +130,7 @@ export function CampaignsPage() { return (
+