From cfe00845fd734f1f21bec680eb0d56b6c541d958 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fatih=20Kadir=20Ak=C4=B1n?= Date: Wed, 17 Dec 2025 01:26:59 +0300 Subject: [PATCH] feat(messages): add brand assets translations in multiple languages --- messages/ar.json | 25 +++ messages/de.json | 25 +++ messages/el.json | 25 +++ messages/en.json | 25 +++ messages/es.json | 25 +++ messages/fr.json | 25 +++ messages/he.json | 25 +++ messages/it.json | 25 +++ messages/ja.json | 25 +++ messages/ko.json | 25 +++ messages/pt.json | 25 +++ messages/ru.json | 25 +++ messages/tr.json | 25 +++ messages/zh.json | 25 +++ package-lock.json | 85 ++++++++++ package.json | 1 + public/logo-dark.svg | 2 +- public/logo.svg | 2 +- src/app/brand/page.tsx | 73 +++++---- src/components/layout/header.tsx | 118 +++++++------- src/components/ui/context-menu.tsx | 252 +++++++++++++++++++++++++++++ 21 files changed, 791 insertions(+), 92 deletions(-) create mode 100644 src/components/ui/context-menu.tsx diff --git a/messages/ar.json b/messages/ar.json index 8defe5c4..f3e5cfd8 100644 --- a/messages/ar.json +++ b/messages/ar.json @@ -46,6 +46,31 @@ "register": "إنشاء حساب", "logout": "تسجيل الخروج" }, + "brand": { + "copyLogoSvg": "نسخ شعار SVG", + "brandAssets": "موارد العلامة التجارية", + "title": "موارد العلامة التجارية", + "description": "الشعارات الرسمية والألوان وإرشادات العلامة التجارية لـ {name}. مجاني للصحافة والشراكات ومشاريع المجتمع.", + "logos": "الشعارات", + "logo": "الشعار", + "logoWithName": "الشعار مع الاسم", + "forLightBackgrounds": "للخلفيات الفاتحة", + "forDarkBackgrounds": "للخلفيات الداكنة", + "brandColors": "ألوان العلامة التجارية", + "clickToCopy": "انقر لنسخ قيمة hex", + "primary": "لون العلامة التجارية الأساسي", + "background": "خلفية فاتحة", + "accent": "لون التمييز النيلي", + "muted": "لون النص المكتوم", + "usageGuidelines": "إرشادات الاستخدام", + "guideline1": "لا تمدد أو تشوه أو تدور الشعار", + "guideline2": "حافظ على مسافة كافية حول الشعار", + "guideline3": "استخدم الشعار الداكن على الخلفيات الفاتحة والعكس", + "guideline4": "لا تضف تأثيرات مثل الظلال أو التدرجات للشعار", + "guideline5": "يجب أن يكون الشعار مرئيًا بوضوح على الخلفية", + "license": "الترخيص", + "licenseText": "يتم توفير موارد العلامة التجارية {name} بموجب CC0 1.0 Universal. أنت حر في استخدام هذه الموارد لأي غرض دون إسناد." + }, "auth": { "login": "تسجيل الدخول", "loginDescription": "أدخل بياناتك للمتابعة", diff --git a/messages/de.json b/messages/de.json index 4c9e7ce5..a4614373 100644 --- a/messages/de.json +++ b/messages/de.json @@ -46,6 +46,31 @@ "register": "Registrieren", "logout": "Abmelden" }, + "brand": { + "copyLogoSvg": "Logo SVG kopieren", + "brandAssets": "Markenressourcen", + "title": "Markenressourcen", + "description": "Offizielle Logos, Farben und Markenrichtlinien für {name}. Kostenlos für Presse, Partnerschaften und Community-Projekte.", + "logos": "Logos", + "logo": "Logo", + "logoWithName": "Logo mit Namen", + "forLightBackgrounds": "Für helle Hintergründe", + "forDarkBackgrounds": "Für dunkle Hintergründe", + "brandColors": "Markenfarben", + "clickToCopy": "Klicken zum Kopieren des Hex-Werts", + "primary": "Primäre Markenfarbe", + "background": "Heller Hintergrund", + "accent": "Indigo Akzentfarbe", + "muted": "Gedämpfte Textfarbe", + "usageGuidelines": "Verwendungsrichtlinien", + "guideline1": "Das Logo nicht strecken, verzerren oder drehen", + "guideline2": "Ausreichend Abstand um das Logo einhalten", + "guideline3": "Dunkles Logo auf hellen Hintergründen verwenden und umgekehrt", + "guideline4": "Keine Effekte wie Schatten oder Verläufe zum Logo hinzufügen", + "guideline5": "Das Logo sollte vor dem Hintergrund deutlich sichtbar sein", + "license": "Lizenz", + "licenseText": "Die {name} Markenressourcen werden unter CC0 1.0 Universal bereitgestellt. Sie können diese Ressourcen ohne Quellenangabe für jeden Zweck frei verwenden." + }, "auth": { "login": "Anmelden", "loginDescription": "Geben Sie Ihre Anmeldedaten ein, um fortzufahren", diff --git a/messages/el.json b/messages/el.json index fc807358..fa2e98c2 100644 --- a/messages/el.json +++ b/messages/el.json @@ -46,6 +46,31 @@ "register": "Εγγραφή", "logout": "Αποσύνδεση" }, + "brand": { + "copyLogoSvg": "Αντιγραφή Logo SVG", + "brandAssets": "Πόροι μάρκας", + "title": "Πόροι μάρκας", + "description": "Επίσημα λογότυπα, χρώματα και οδηγίες μάρκας για {name}. Δωρεάν για τύπο, συνεργασίες και κοινοτικά έργα.", + "logos": "Λογότυπα", + "logo": "Λογότυπο", + "logoWithName": "Λογότυπο με όνομα", + "forLightBackgrounds": "Για ανοιχτόχρωμα φόντα", + "forDarkBackgrounds": "Για σκούρα φόντα", + "brandColors": "Χρώματα μάρκας", + "clickToCopy": "Κάντε κλικ για αντιγραφή hex τιμής", + "primary": "Κύριο χρώμα μάρκας", + "background": "Ανοιχτόχρωμο φόντο", + "accent": "Χρώμα τονισμού indigo", + "muted": "Απαλό χρώμα κειμένου", + "usageGuidelines": "Οδηγίες χρήσης", + "guideline1": "Μην τεντώνετε, παραμορφώνετε ή περιστρέφετε το λογότυπο", + "guideline2": "Διατηρήστε επαρκή απόσταση γύρω από το λογότυπο", + "guideline3": "Χρησιμοποιήστε το σκούρο λογότυπο σε ανοιχτόχρωμα φόντα και αντίστροφα", + "guideline4": "Μην προσθέτετε εφέ όπως σκιές ή διαβαθμίσεις στο λογότυπο", + "guideline5": "Το λογότυπο πρέπει να είναι ευδιάκριτο στο φόντο", + "license": "Άδεια", + "licenseText": "Οι πόροι μάρκας {name} παρέχονται υπό CC0 1.0 Universal. Είστε ελεύθεροι να χρησιμοποιήσετε αυτούς τους πόρους για οποιονδήποτε σκοπό χωρίς αναφορά." + }, "auth": { "login": "Σύνδεση", "loginDescription": "Εισάγετε τα στοιχεία σας για να συνεχίσετε", diff --git a/messages/en.json b/messages/en.json index d568e70b..e1b426a1 100644 --- a/messages/en.json +++ b/messages/en.json @@ -46,6 +46,31 @@ "register": "Register", "logout": "Logout" }, + "brand": { + "copyLogoSvg": "Copy Logo SVG", + "brandAssets": "Brand Assets", + "title": "Brand Assets", + "description": "Official logos, colors, and brand guidelines for {name}. Free to use for press, partnerships, and community projects.", + "logos": "Logos", + "logo": "Logo", + "logoWithName": "Logo with Name", + "forLightBackgrounds": "For light backgrounds", + "forDarkBackgrounds": "For dark backgrounds", + "brandColors": "Brand Colors", + "clickToCopy": "Click to copy hex value", + "primary": "Primary brand color", + "background": "Light background", + "accent": "Indigo accent color", + "muted": "Muted text color", + "usageGuidelines": "Usage Guidelines", + "guideline1": "Do not stretch, distort, or rotate the logo", + "guideline2": "Maintain adequate spacing around the logo", + "guideline3": "Use the dark logo on light backgrounds and vice versa", + "guideline4": "Do not add effects like shadows or gradients to the logo", + "guideline5": "The logo should be clearly visible against the background", + "license": "License", + "licenseText": "The {name} brand assets are provided under CC0 1.0 Universal. You are free to use these assets for any purpose without attribution." + }, "auth": { "login": "Login", "loginDescription": "Enter your credentials to continue", diff --git a/messages/es.json b/messages/es.json index 75b615d1..b0c831e9 100644 --- a/messages/es.json +++ b/messages/es.json @@ -46,6 +46,31 @@ "register": "Registrarse", "logout": "Cerrar sesión" }, + "brand": { + "copyLogoSvg": "Copiar Logo SVG", + "brandAssets": "Recursos de Marca", + "title": "Recursos de Marca", + "description": "Logotipos oficiales, colores y directrices de marca para {name}. Gratis para prensa, asociaciones y proyectos comunitarios.", + "logos": "Logotipos", + "logo": "Logo", + "logoWithName": "Logo con Nombre", + "forLightBackgrounds": "Para fondos claros", + "forDarkBackgrounds": "Para fondos oscuros", + "brandColors": "Colores de Marca", + "clickToCopy": "Haz clic para copiar el valor hex", + "primary": "Color primario de marca", + "background": "Fondo claro", + "accent": "Color de acento índigo", + "muted": "Color de texto atenuado", + "usageGuidelines": "Directrices de Uso", + "guideline1": "No estires, distorsiones ni gires el logo", + "guideline2": "Mantén un espacio adecuado alrededor del logo", + "guideline3": "Usa el logo oscuro en fondos claros y viceversa", + "guideline4": "No añadas efectos como sombras o degradados al logo", + "guideline5": "El logo debe ser claramente visible contra el fondo", + "license": "Licencia", + "licenseText": "Los recursos de marca de {name} se proporcionan bajo CC0 1.0 Universal. Eres libre de usar estos recursos para cualquier propósito sin atribución." + }, "auth": { "login": "Iniciar sesión", "loginDescription": "Ingresa tus credenciales para continuar", diff --git a/messages/fr.json b/messages/fr.json index 4102b02c..a19a94a1 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -46,6 +46,31 @@ "register": "Inscription", "logout": "Déconnexion" }, + "brand": { + "copyLogoSvg": "Copier le logo SVG", + "brandAssets": "Ressources de marque", + "title": "Ressources de marque", + "description": "Logos officiels, couleurs et directives de marque pour {name}. Gratuit pour la presse, les partenariats et les projets communautaires.", + "logos": "Logos", + "logo": "Logo", + "logoWithName": "Logo avec nom", + "forLightBackgrounds": "Pour fonds clairs", + "forDarkBackgrounds": "Pour fonds sombres", + "brandColors": "Couleurs de marque", + "clickToCopy": "Cliquez pour copier la valeur hex", + "primary": "Couleur de marque principale", + "background": "Fond clair", + "accent": "Couleur d'accentuation indigo", + "muted": "Couleur de texte atténuée", + "usageGuidelines": "Directives d'utilisation", + "guideline1": "Ne pas étirer, déformer ou faire pivoter le logo", + "guideline2": "Maintenir un espacement adéquat autour du logo", + "guideline3": "Utiliser le logo sombre sur les fonds clairs et vice versa", + "guideline4": "Ne pas ajouter d'effets comme des ombres ou des dégradés au logo", + "guideline5": "Le logo doit être clairement visible sur le fond", + "license": "Licence", + "licenseText": "Les ressources de marque {name} sont fournies sous CC0 1.0 Universal. Vous êtes libre d'utiliser ces ressources à toutes fins sans attribution." + }, "auth": { "login": "Connexion", "loginDescription": "Entrez vos identifiants pour continuer", diff --git a/messages/he.json b/messages/he.json index 357c53ce..54910b0b 100644 --- a/messages/he.json +++ b/messages/he.json @@ -46,6 +46,31 @@ "register": "הרשמה", "logout": "התנתקות" }, + "brand": { + "copyLogoSvg": "העתק לוגו SVG", + "brandAssets": "נכסי מותג", + "title": "נכסי מותג", + "description": "לוגואים רשמיים, צבעים והנחיות מותג עבור {name}. חינם לעיתונות, שותפויות ופרויקטים קהילתיים.", + "logos": "לוגואים", + "logo": "לוגו", + "logoWithName": "לוגו עם שם", + "forLightBackgrounds": "לרקעים בהירים", + "forDarkBackgrounds": "לרקעים כהים", + "brandColors": "צבעי מותג", + "clickToCopy": "לחץ להעתקת ערך hex", + "primary": "צבע מותג ראשי", + "background": "רקע בהיר", + "accent": "צבע הדגשה אינדיגו", + "muted": "צבע טקסט מעומעם", + "usageGuidelines": "הנחיות שימוש", + "guideline1": "אל תמתח, תעוות או תסובב את הלוגו", + "guideline2": "שמור על מרווח מספיק סביב הלוגו", + "guideline3": "השתמש בלוגו הכהה על רקעים בהירים ולהיפך", + "guideline4": "אל תוסיף אפקטים כמו צללים או מעברי צבע ללוגו", + "guideline5": "הלוגו צריך להיות נראה בבירור על הרקע", + "license": "רישיון", + "licenseText": "נכסי המותג של {name} מסופקים תחת CC0 1.0 Universal. אתה חופשי להשתמש בנכסים אלה לכל מטרה ללא ייחוס." + }, "auth": { "login": "התחברות", "loginDescription": "הזן את פרטיך כדי להמשיך", diff --git a/messages/it.json b/messages/it.json index 114917e3..90970381 100644 --- a/messages/it.json +++ b/messages/it.json @@ -46,6 +46,31 @@ "register": "Registrati", "logout": "Esci" }, + "brand": { + "copyLogoSvg": "Copia Logo SVG", + "brandAssets": "Risorse del marchio", + "title": "Risorse del marchio", + "description": "Loghi ufficiali, colori e linee guida del marchio per {name}. Gratuito per stampa, partnership e progetti della comunità.", + "logos": "Loghi", + "logo": "Logo", + "logoWithName": "Logo con nome", + "forLightBackgrounds": "Per sfondi chiari", + "forDarkBackgrounds": "Per sfondi scuri", + "brandColors": "Colori del marchio", + "clickToCopy": "Clicca per copiare il valore hex", + "primary": "Colore primario del marchio", + "background": "Sfondo chiaro", + "accent": "Colore accento indaco", + "muted": "Colore testo attenuato", + "usageGuidelines": "Linee guida per l'uso", + "guideline1": "Non allungare, distorcere o ruotare il logo", + "guideline2": "Mantenere una spaziatura adeguata intorno al logo", + "guideline3": "Usare il logo scuro su sfondi chiari e viceversa", + "guideline4": "Non aggiungere effetti come ombre o sfumature al logo", + "guideline5": "Il logo deve essere chiaramente visibile sullo sfondo", + "license": "Licenza", + "licenseText": "Le risorse del marchio {name} sono fornite sotto CC0 1.0 Universal. Sei libero di utilizzare queste risorse per qualsiasi scopo senza attribuzione." + }, "auth": { "login": "Accedi", "loginDescription": "Inserisci le tue credenziali per continuare", diff --git a/messages/ja.json b/messages/ja.json index 651fdee0..d51265ef 100644 --- a/messages/ja.json +++ b/messages/ja.json @@ -46,6 +46,31 @@ "register": "登録", "logout": "ログアウト" }, + "brand": { + "copyLogoSvg": "ロゴSVGをコピー", + "brandAssets": "ブランドアセット", + "title": "ブランドアセット", + "description": "{name}の公式ロゴ、カラー、ブランドガイドライン。プレス、パートナーシップ、コミュニティプロジェクトに無料でご利用いただけます。", + "logos": "ロゴ", + "logo": "ロゴ", + "logoWithName": "名前付きロゴ", + "forLightBackgrounds": "明るい背景用", + "forDarkBackgrounds": "暗い背景用", + "brandColors": "ブランドカラー", + "clickToCopy": "クリックして16進値をコピー", + "primary": "プライマリブランドカラー", + "background": "明るい背景", + "accent": "インディゴアクセントカラー", + "muted": "ミュートテキストカラー", + "usageGuidelines": "使用ガイドライン", + "guideline1": "ロゴを引き伸ばしたり、歪めたり、回転させたりしないでください", + "guideline2": "ロゴの周りに適切な余白を確保してください", + "guideline3": "明るい背景には暗いロゴを、暗い背景には明るいロゴを使用してください", + "guideline4": "ロゴに影やグラデーションなどの効果を追加しないでください", + "guideline5": "ロゴは背景に対してはっきりと見える必要があります", + "license": "ライセンス", + "licenseText": "{name}のブランドアセットはCC0 1.0 Universalの下で提供されています。帰属表示なしで任意の目的にこれらのアセットを自由に使用できます。" + }, "auth": { "login": "ログイン", "loginDescription": "続行するには認証情報を入力してください", diff --git a/messages/ko.json b/messages/ko.json index e01e0342..5dc84b4c 100644 --- a/messages/ko.json +++ b/messages/ko.json @@ -46,6 +46,31 @@ "register": "회원가입", "logout": "로그아웃" }, + "brand": { + "copyLogoSvg": "로고 SVG 복사", + "brandAssets": "브랜드 자산", + "title": "브랜드 자산", + "description": "{name}의 공식 로고, 색상 및 브랜드 가이드라인입니다. 언론, 파트너십 및 커뮤니티 프로젝트에 무료로 사용할 수 있습니다.", + "logos": "로고", + "logo": "로고", + "logoWithName": "이름이 있는 로고", + "forLightBackgrounds": "밝은 배경용", + "forDarkBackgrounds": "어두운 배경용", + "brandColors": "브랜드 색상", + "clickToCopy": "클릭하여 hex 값 복사", + "primary": "기본 브랜드 색상", + "background": "밝은 배경", + "accent": "인디고 강조 색상", + "muted": "음소거 텍스트 색상", + "usageGuidelines": "사용 지침", + "guideline1": "로고를 늘리거나 왜곡하거나 회전하지 마세요", + "guideline2": "로고 주위에 적절한 간격을 유지하세요", + "guideline3": "밝은 배경에는 어두운 로고를, 어두운 배경에는 밝은 로고를 사용하세요", + "guideline4": "로고에 그림자나 그라데이션 같은 효과를 추가하지 마세요", + "guideline5": "로고는 배경에 대해 명확하게 보여야 합니다", + "license": "라이선스", + "licenseText": "{name} 브랜드 자산은 CC0 1.0 Universal 하에 제공됩니다. 귀속 표시 없이 어떤 목적으로든 이러한 자산을 자유롭게 사용할 수 있습니다." + }, "auth": { "login": "로그인", "loginDescription": "계속하려면 자격 증명을 입력하세요", diff --git a/messages/pt.json b/messages/pt.json index 110f7d47..6a28fe29 100644 --- a/messages/pt.json +++ b/messages/pt.json @@ -46,6 +46,31 @@ "register": "Cadastrar", "logout": "Sair" }, + "brand": { + "copyLogoSvg": "Copiar Logo SVG", + "brandAssets": "Recursos da Marca", + "title": "Recursos da Marca", + "description": "Logotipos oficiais, cores e diretrizes de marca para {name}. Gratuito para imprensa, parcerias e projetos comunitários.", + "logos": "Logotipos", + "logo": "Logo", + "logoWithName": "Logo com Nome", + "forLightBackgrounds": "Para fundos claros", + "forDarkBackgrounds": "Para fundos escuros", + "brandColors": "Cores da Marca", + "clickToCopy": "Clique para copiar o valor hex", + "primary": "Cor primária da marca", + "background": "Fundo claro", + "accent": "Cor de destaque índigo", + "muted": "Cor de texto suave", + "usageGuidelines": "Diretrizes de Uso", + "guideline1": "Não estique, distorça ou gire o logo", + "guideline2": "Mantenha espaçamento adequado ao redor do logo", + "guideline3": "Use o logo escuro em fundos claros e vice-versa", + "guideline4": "Não adicione efeitos como sombras ou gradientes ao logo", + "guideline5": "O logo deve ser claramente visível contra o fundo", + "license": "Licença", + "licenseText": "Os recursos de marca {name} são fornecidos sob CC0 1.0 Universal. Você é livre para usar estes recursos para qualquer finalidade sem atribuição." + }, "auth": { "login": "Entrar", "loginDescription": "Digite suas credenciais para continuar", diff --git a/messages/ru.json b/messages/ru.json index 93e8d0af..a54ec892 100644 --- a/messages/ru.json +++ b/messages/ru.json @@ -46,6 +46,31 @@ "register": "Регистрация", "logout": "Выйти" }, + "brand": { + "copyLogoSvg": "Скопировать логотип SVG", + "brandAssets": "Ресурсы бренда", + "title": "Ресурсы бренда", + "description": "Официальные логотипы, цвета и рекомендации по бренду для {name}. Бесплатно для прессы, партнерств и общественных проектов.", + "logos": "Логотипы", + "logo": "Логотип", + "logoWithName": "Логотип с названием", + "forLightBackgrounds": "Для светлого фона", + "forDarkBackgrounds": "Для темного фона", + "brandColors": "Цвета бренда", + "clickToCopy": "Нажмите для копирования hex-значения", + "primary": "Основной цвет бренда", + "background": "Светлый фон", + "accent": "Индиго акцентный цвет", + "muted": "Приглушенный цвет текста", + "usageGuidelines": "Руководство по использованию", + "guideline1": "Не растягивайте, не искажайте и не поворачивайте логотип", + "guideline2": "Соблюдайте достаточный отступ вокруг логотипа", + "guideline3": "Используйте темный логотип на светлом фоне и наоборот", + "guideline4": "Не добавляйте к логотипу эффекты, такие как тени или градиенты", + "guideline5": "Логотип должен быть хорошо виден на фоне", + "license": "Лицензия", + "licenseText": "Ресурсы бренда {name} предоставляются под CC0 1.0 Universal. Вы можете свободно использовать эти ресурсы для любых целей без указания авторства." + }, "auth": { "login": "Войти", "loginDescription": "Введите свои данные для входа", diff --git a/messages/tr.json b/messages/tr.json index 3fc0c3e0..b742a465 100644 --- a/messages/tr.json +++ b/messages/tr.json @@ -46,6 +46,31 @@ "register": "Kayıt Ol", "logout": "Çıkış Yap" }, + "brand": { + "copyLogoSvg": "Logo SVG'sini Kopyala", + "brandAssets": "Marka Varlıkları", + "title": "Marka Varlıkları", + "description": "{name} için resmi logolar, renkler ve marka yönergeleri. Basın, ortaklıklar ve topluluk projeleri için ücretsiz kullanılabilir.", + "logos": "Logolar", + "logo": "Logo", + "logoWithName": "İsimli Logo", + "forLightBackgrounds": "Açık arka planlar için", + "forDarkBackgrounds": "Koyu arka planlar için", + "brandColors": "Marka Renkleri", + "clickToCopy": "Hex değerini kopyalamak için tıklayın", + "primary": "Birincil marka rengi", + "background": "Açık arka plan", + "accent": "İndigo vurgu rengi", + "muted": "Soluk metin rengi", + "usageGuidelines": "Kullanım Yönergeleri", + "guideline1": "Logoyu esnetmeyin, deforme etmeyin veya döndürmeyin", + "guideline2": "Logo etrafında yeterli boşluk bırakın", + "guideline3": "Açık arka planlarda koyu logoyu, koyu arka planlarda açık logoyu kullanın", + "guideline4": "Logoya gölge veya gradyan gibi efektler eklemeyin", + "guideline5": "Logo arka plana karşı açıkça görünür olmalıdır", + "license": "Lisans", + "licenseText": "{name} marka varlıkları CC0 1.0 Universal altında sağlanmaktadır. Bu varlıkları atıf yapmadan herhangi bir amaçla kullanabilirsiniz." + }, "auth": { "login": "Giriş Yap", "loginDescription": "Devam etmek için bilgilerinizi girin", diff --git a/messages/zh.json b/messages/zh.json index 7a50988a..18f88bb6 100644 --- a/messages/zh.json +++ b/messages/zh.json @@ -46,6 +46,31 @@ "register": "注册", "logout": "退出登录" }, + "brand": { + "copyLogoSvg": "复制Logo SVG", + "brandAssets": "品牌资源", + "title": "品牌资源", + "description": "{name}的官方标志、颜色和品牌指南。可免费用于新闻、合作和社区项目。", + "logos": "标志", + "logo": "标志", + "logoWithName": "带名称的标志", + "forLightBackgrounds": "适用于浅色背景", + "forDarkBackgrounds": "适用于深色背景", + "brandColors": "品牌颜色", + "clickToCopy": "点击复制十六进制值", + "primary": "主要品牌颜色", + "background": "浅色背景", + "accent": "靛蓝强调色", + "muted": "柔和文本颜色", + "usageGuidelines": "使用指南", + "guideline1": "请勿拉伸、扭曲或旋转标志", + "guideline2": "保持标志周围有足够的间距", + "guideline3": "在浅色背景上使用深色标志,反之亦然", + "guideline4": "请勿为标志添加阴影或渐变等效果", + "guideline5": "标志应在背景上清晰可见", + "license": "许可证", + "licenseText": "{name}品牌资源根据CC0 1.0 Universal提供。您可以自由使用这些资源,无需署名。" + }, "auth": { "login": "登录", "loginDescription": "输入您的凭据以继续", diff --git a/package-lock.json b/package-lock.json index 4cc87660..425ce161 100644 --- a/package-lock.json +++ b/package-lock.json @@ -18,6 +18,7 @@ "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", @@ -3307,6 +3308,90 @@ } } }, + "node_modules/@radix-ui/react-context-menu": { + "version": "2.2.16", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context-menu/-/react-context-menu-2.2.16.tgz", + "integrity": "sha512-O8morBEW+HsVG28gYDZPTrT9UUovQUlJue5YO836tiTJhuIWBm/zQHc7j388sHWtdH/xUZurK9olD2+pcqx5ww==", + "license": "MIT", + "dependencies": { + "@radix-ui/primitive": "1.1.3", + "@radix-ui/react-context": "1.1.2", + "@radix-ui/react-menu": "2.1.16", + "@radix-ui/react-primitive": "2.1.3", + "@radix-ui/react-use-callback-ref": "1.1.1", + "@radix-ui/react-use-controllable-state": "1.2.2" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-context": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.2.tgz", + "integrity": "sha512-jCi/QKUM2r1Ju5a3J64TH2A5SpKAgh0LpknyqdQ4m6DCV0xJ2HG1xARRwNGPQfi1SLdLWZ1OJz6F4OMBBNiGJA==", + "license": "MIT", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-primitive": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.1.3.tgz", + "integrity": "sha512-m9gTwRkhy2lvCPe6QJp4d3G1TYEUHn/FzJUtq9MjH46an1wJU+GdoGC5VLof8RX8Ft/DlpshApkhswDLZzHIcQ==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-slot": "1.2.3" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-context-menu/node_modules/@radix-ui/react-slot": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.2.3.tgz", + "integrity": "sha512-aeNmHnBxbi2St0au6VBVC7JXFlhLlOnvIIlePNniyUNAClzmtAUEY8/pBiK3iHjufOlwA+c20/8jngo7xcrg8A==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.2" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-dialog": { "version": "1.1.15", "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.15.tgz", diff --git a/package.json b/package.json index e3a361a9..265a6a7b 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "@radix-ui/react-alert-dialog": "^1.1.15", "@radix-ui/react-avatar": "^1.1.11", "@radix-ui/react-checkbox": "^1.3.3", + "@radix-ui/react-context-menu": "^2.2.16", "@radix-ui/react-dialog": "^1.1.15", "@radix-ui/react-dropdown-menu": "^2.1.16", "@radix-ui/react-label": "^2.1.8", diff --git a/public/logo-dark.svg b/public/logo-dark.svg index b832716e..205686a1 100644 --- a/public/logo-dark.svg +++ b/public/logo-dark.svg @@ -1,4 +1,4 @@ - + diff --git a/public/logo.svg b/public/logo.svg index 3f374b18..8bdf4858 100644 --- a/public/logo.svg +++ b/public/logo.svg @@ -1,4 +1,4 @@ - + diff --git a/src/app/brand/page.tsx b/src/app/brand/page.tsx index 2772f438..8ffdbc1a 100644 --- a/src/app/brand/page.tsx +++ b/src/app/brand/page.tsx @@ -3,6 +3,7 @@ import { useState } from "react"; import Image from "next/image"; import { Download, Copy, Check } from "lucide-react"; +import { useTranslations } from "next-intl"; import { Button } from "@/components/ui/button"; import { useBranding } from "@/components/providers/branding-provider"; import { notFound } from "next/navigation"; @@ -102,6 +103,7 @@ function isLight(color: string): boolean { export default function BrandAssetsPage() { const branding = useBranding(); + const t = useTranslations("brand"); // Redirect if using clone branding if (branding.useCloneBranding) { @@ -110,20 +112,20 @@ export default function BrandAssetsPage() { return (
-

Brand Assets

+

{t("title")}

- Official logos, colors, and brand guidelines for {branding.name}. Free to use for press, partnerships, and community projects. + {t("description", { name: branding.name })}

{/* Logos Section */}
-

Logos

+

{t("logos")}

{/* Logo for light backgrounds */} -

Brand Colors

-

Click to copy hex value

+

{t("brandColors")}

+

{t("clickToCopy")}

{/* Usage Guidelines */}
-

Usage Guidelines

+

{t("usageGuidelines")}

    -
  • Do not stretch, distort, or rotate the logo
  • -
  • Maintain adequate spacing around the logo
  • -
  • Use the dark logo on light backgrounds and vice versa
  • -
  • Do not add effects like shadows or gradients to the logo
  • -
  • The logo should be clearly visible against the background
  • +
  • {t("guideline1")}
  • +
  • {t("guideline2")}
  • +
  • {t("guideline3")}
  • +
  • {t("guideline4")}
  • +
  • {t("guideline5")}
{/* License */}
-

License

+

{t("license")}

- The {branding.name} brand assets are provided under{" "} - - CC0 1.0 Universal - - . You are free to use these assets for any purpose without attribution. + {t.rich("licenseText", { + name: branding.name, + link: (chunks) => ( + + {chunks} + + ), + })}

diff --git a/src/components/layout/header.tsx b/src/components/layout/header.tsx index cceecc2a..ce08c556 100644 --- a/src/components/layout/header.tsx +++ b/src/components/layout/header.tsx @@ -34,6 +34,12 @@ import { } from "@/components/ui/dropdown-menu"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"; +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuTrigger, +} from "@/components/ui/context-menu"; import { NotificationBell } from "@/components/layout/notification-bell"; import { setLocale } from "@/lib/i18n/client"; import { useBranding } from "@/components/providers/branding-provider"; @@ -74,15 +80,6 @@ export function Header({ authProvider = "credentials", allowRegistration = true const user = session?.user; const isAdmin = user?.role === "ADMIN"; const [mobileMenuOpen, setMobileMenuOpen] = useState(false); - const [logoMenuOpen, setLogoMenuOpen] = useState(false); - const [logoMenuPosition, setLogoMenuPosition] = useState({ x: 0, y: 0 }); - - const handleLogoContextMenu = (e: React.MouseEvent) => { - if (branding.useCloneBranding) return; - e.preventDefault(); - setLogoMenuPosition({ x: e.clientX, y: e.clientY }); - setLogoMenuOpen(true); - }; const handleCopyLogoSvg = async () => { try { @@ -91,7 +88,6 @@ export function Header({ authProvider = "credentials", allowRegistration = true const response = await fetch(logoUrl); const svgContent = await response.text(); await navigator.clipboard.writeText(svgContent); - setLogoMenuOpen(false); } catch (error) { console.error("Failed to copy logo:", error); } @@ -194,54 +190,64 @@ export function Header({ authProvider = "credentials", allowRegistration = true {/* Logo */} - - {branding.logo && ( - <> - {branding.name} - {branding.name} - - )} - {branding.name} - - - {/* Logo context menu */} - {!branding.useCloneBranding && ( - - - Logo menu - - - + {!branding.useCloneBranding ? ( + + + + {branding.logo && ( + <> + {branding.name} + {branding.name} + + )} + {branding.name} + + + + - Copy Logo SVG - - { - router.push("/brand"); - setLogoMenuOpen(false); - }}> + {t("brand.copyLogoSvg")} + + router.push("/brand")}> - Brand Assets - - - + {t("brand.brandAssets")} + + + + ) : ( + + {branding.logo && ( + <> + {branding.name} + {branding.name} + + )} + {branding.name} + )} {/* Desktop nav */} diff --git a/src/components/ui/context-menu.tsx b/src/components/ui/context-menu.tsx new file mode 100644 index 00000000..f024a9ce --- /dev/null +++ b/src/components/ui/context-menu.tsx @@ -0,0 +1,252 @@ +"use client" + +import * as React from "react" +import * as ContextMenuPrimitive from "@radix-ui/react-context-menu" +import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" + +import { cn } from "@/lib/utils" + +function ContextMenu({ + ...props +}: React.ComponentProps) { + return +} + +function ContextMenuTrigger({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuPortal({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuSub({ + ...props +}: React.ComponentProps) { + return +} + +function ContextMenuRadioGroup({ + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuSubTrigger({ + className, + inset, + children, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + {children} + + + ) +} + +function ContextMenuSubContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuContent({ + className, + ...props +}: React.ComponentProps) { + return ( + + + + ) +} + +function ContextMenuItem({ + className, + inset, + variant = "default", + ...props +}: React.ComponentProps & { + inset?: boolean + variant?: "default" | "destructive" +}) { + return ( + + ) +} + +function ContextMenuCheckboxItem({ + className, + children, + checked, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function ContextMenuRadioItem({ + className, + children, + ...props +}: React.ComponentProps) { + return ( + + + + + + + {children} + + ) +} + +function ContextMenuLabel({ + className, + inset, + ...props +}: React.ComponentProps & { + inset?: boolean +}) { + return ( + + ) +} + +function ContextMenuSeparator({ + className, + ...props +}: React.ComponentProps) { + return ( + + ) +} + +function ContextMenuShortcut({ + className, + ...props +}: React.ComponentProps<"span">) { + return ( + + ) +} + +export { + ContextMenu, + ContextMenuTrigger, + ContextMenuContent, + ContextMenuItem, + ContextMenuCheckboxItem, + ContextMenuRadioItem, + ContextMenuLabel, + ContextMenuSeparator, + ContextMenuShortcut, + ContextMenuGroup, + ContextMenuPortal, + ContextMenuSub, + ContextMenuSubContent, + ContextMenuSubTrigger, + ContextMenuRadioGroup, +}