feat(i18n): 为评论系统添加国际化支持
- 在管理后台引入 vue-i18n 并添加多语言文件 - 为前端评论组件添加翻译功能,支持自动语言检测 - 在功能设置中新增管理后台和组件语言配置选项 - 更新 API 接口以支持语言设置存储 - 优化菜单项文本溢出显示样式
This commit is contained in:
@@ -11,6 +11,7 @@
|
||||
"@phosphor-icons/vue": "^2.2.1",
|
||||
"echarts": "^5.5.0",
|
||||
"vue": "^3.5.13",
|
||||
"vue-i18n": "^9.14.5",
|
||||
"vue-router": "^4.4.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -20,4 +21,4 @@
|
||||
"vite": "^6.0.11",
|
||||
"vue-tsc": "^2.1.10"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
41
cwd-admin/src/i18n.ts
Normal file
41
cwd-admin/src/i18n.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
import { createI18n } from 'vue-i18n';
|
||||
import zhCN from './locales/zh-CN.json';
|
||||
import enUS from './locales/en-US.json';
|
||||
import zhTW from './locales/zh-TW.json';
|
||||
import es from './locales/es.json';
|
||||
import pt from './locales/pt.json';
|
||||
import fr from './locales/fr.json';
|
||||
import de from './locales/de.json';
|
||||
import ja from './locales/ja.json';
|
||||
import ko from './locales/ko.json';
|
||||
import ru from './locales/ru.json';
|
||||
import it from './locales/it.json';
|
||||
import nl from './locales/nl.json';
|
||||
import ar from './locales/ar.json';
|
||||
import hi from './locales/hi.json';
|
||||
import id from './locales/id.json';
|
||||
|
||||
const i18n = createI18n({
|
||||
legacy: false, // 使用 Composition API
|
||||
locale: localStorage.getItem('admin_language') || 'zh-CN', // 默认语言
|
||||
fallbackLocale: 'zh-CN',
|
||||
messages: {
|
||||
'zh-CN': zhCN,
|
||||
'en-US': enUS,
|
||||
'zh-TW': zhTW,
|
||||
'es': es,
|
||||
'pt': pt,
|
||||
'fr': fr,
|
||||
'de': de,
|
||||
'ja': ja,
|
||||
'ko': ko,
|
||||
'ru': ru,
|
||||
'it': it,
|
||||
'nl': nl,
|
||||
'ar': ar,
|
||||
'hi': hi,
|
||||
'id': id,
|
||||
},
|
||||
});
|
||||
|
||||
export default i18n;
|
||||
304
cwd-admin/src/locales/ar.json
Normal file
304
cwd-admin/src/locales/ar.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "إدارة التعليقات",
|
||||
"stats": "لوحة المعلومات",
|
||||
"analytics": "إحصائيات الزيارات",
|
||||
"settings": "إعدادات الموقع",
|
||||
"data": "إدارة البيانات"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "تبديل القائمة",
|
||||
"docs": "الوثائق",
|
||||
"logout": "تسجيل الخروج",
|
||||
"moreActions": "المزيد من الإجراءات",
|
||||
"defaultSite": "الموقع الافتراضي",
|
||||
"theme": {
|
||||
"light": "فاتح",
|
||||
"dark": "داكن",
|
||||
"system": "النظام"
|
||||
},
|
||||
"version": {
|
||||
"title": "معلومات الإصدار",
|
||||
"apiAddress": "عنوان API",
|
||||
"apiVersion": "إصدار الواجهة",
|
||||
"adminVersion": "إصدار الإدارة",
|
||||
"match": "إصدار الإدارة الحالي متطابق مع إصدار الواجهة، يمكنك استخدامه بشكل طبيعي.",
|
||||
"mismatch": "إصدار الإدارة الحالي غير متطابق مع إصدار الواجهة، يوصى بتحديث خدمة API لتجنب مشاكل التوافق.",
|
||||
"fetchError": "فشل في جلب إصدار الواجهة:",
|
||||
"loading": "جارٍ التحميل...",
|
||||
"notConfigured": "غير مكون",
|
||||
"notFetched": "لم يتم الجلب",
|
||||
"ok": "حسناً"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "لوحة المعلومات",
|
||||
"overview": "نظرة عامة",
|
||||
"total": "إجمالي التعليقات",
|
||||
"approved": "تمت الموافقة",
|
||||
"pending": "قيد الانتظار",
|
||||
"rejected": "مرفوض",
|
||||
"trend": "اتجاه التعليقات",
|
||||
"bySite": "الإحصائيات حسب الموقع",
|
||||
"last7Days": "آخر 7 أيام",
|
||||
"last30Days": "آخر 30 يوماً",
|
||||
"noData": "لا توجد بيانات تعليقات",
|
||||
"table": {
|
||||
"domain": "النطاق",
|
||||
"total": "الإجمالي",
|
||||
"approved": "تمت الموافقة",
|
||||
"pending": "قيد الانتظار",
|
||||
"rejected": "مرفوض"
|
||||
},
|
||||
"loadError": "فشل تحميل الإحصائيات"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "إحصائيات الزيارات",
|
||||
"overview": "نظرة عامة",
|
||||
"totalPv": "إجمالي الزيارات",
|
||||
"todayPv": "زيارات اليوم",
|
||||
"weekPv": "زيارات الأسبوع",
|
||||
"monthPv": "زيارات الشهر",
|
||||
"totalPages": "الصفحات التي تمت زيارتها",
|
||||
"trend": "اتجاه الزيارات",
|
||||
"pageDetail": "تفاصيل الصفحة",
|
||||
"likeRank": "أعلى الصفحات إعجاباً",
|
||||
"last7Days": "آخر 7 أيام",
|
||||
"last30Days": "آخر 30 يوماً",
|
||||
"sort": {
|
||||
"pv": "ترتيب حسب المشاهدات",
|
||||
"latest": "أحدث زيارة"
|
||||
},
|
||||
"table": {
|
||||
"title": "عنوان الصفحة",
|
||||
"pv": "المشاهدات",
|
||||
"time": "آخر زيارة",
|
||||
"url": "رابط الصفحة",
|
||||
"rank": "الترتيب",
|
||||
"like": "الإعجابات"
|
||||
},
|
||||
"noData": "لا توجد بيانات زيارة",
|
||||
"noLikeData": "لا توجد بيانات إعجاب",
|
||||
"loadError": "فشل تحميل إحصائيات الزيارات"
|
||||
},
|
||||
"data": {
|
||||
"title": "إدارة البيانات",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "بيانات التعليقات",
|
||||
"desc": "إدارة محتوى التعليقات، يدعم نقل البيانات من أنظمة التعليقات الأخرى.",
|
||||
"exportLabel": "تصدير:",
|
||||
"exporting": "جارٍ التصدير...",
|
||||
"exportJson": "تصدير JSON",
|
||||
"importLabel": "استيراد:",
|
||||
"importButton": "استيراد التعليقات",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "تكوين النظام",
|
||||
"desc": "إدارة إعدادات الخلفية، تكوين البريد الإلكتروني، القوائم السوداء، إلخ.",
|
||||
"export": "تصدير التكوين",
|
||||
"import": "استيراد التكوين"
|
||||
},
|
||||
"stats": {
|
||||
"title": "إحصائيات الزيارات",
|
||||
"desc": "إدارة زيارات المقالات، الإعجابات، واتجاهات الزيارة اليومية.",
|
||||
"export": "تصدير الإحصائيات",
|
||||
"import": "استيراد الإحصائيات"
|
||||
},
|
||||
"backup": {
|
||||
"title": "نسخ احتياطي كامل",
|
||||
"desc": "نسخ احتياطي أو استعادة جميع بيانات النظام (التعليقات + التكوين + الإحصائيات).",
|
||||
"export": "تصدير كامل",
|
||||
"import": "استعادة كاملة"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "سجلات العمليات"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "بادئة URL مفقودة",
|
||||
"descPart1": "تم اكتشاف ",
|
||||
"descPart2": " تعليق بدون بادئة النطاق (http/https).",
|
||||
"descPart3": "هل تريد إضافتها أثناء الاستيراد؟",
|
||||
"label": "بادئة النطاق (مثال: https://example.me)",
|
||||
"placeholder": "الرجاء إدخال بادئة النطاق",
|
||||
"skip": "استيراد مباشر (بدون إضافة)",
|
||||
"confirm": "إضافة واستيراد"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "تم التصدير بنجاح",
|
||||
"exportFailed": "فشل التصدير",
|
||||
"fileReadFailed": "فشل قراءة الملف",
|
||||
"jsonParseFailed": "فشل تحليل JSON، يرجى التحقق من تنسيق الملف",
|
||||
"importConfigSuccess": "تم استيراد التكوين بنجاح",
|
||||
"importStatsSuccess": "تم استيراد بيانات الإحصائيات بنجاح",
|
||||
"importBackupSuccess": "تمت الاستعادة الكاملة بنجاح",
|
||||
"importCommentsSuccess": "تم استيراد التعليقات بنجاح",
|
||||
"prefixRequired": "الرجاء إدخال بادئة النطاق",
|
||||
"importStart": "بدء الاستيراد: {name} (الوضع: {mode})",
|
||||
"fileParseSuccess": "تم تحليل الملف بنجاح، جارٍ المعالجة...",
|
||||
"errorWithMessage": "خطأ: {msg}",
|
||||
"parsedCommentsCount": "تم تحليل {count} تعليق",
|
||||
"detectMissingPrefix": "تم اكتشاف {count} رابط بدون بادئة، في انتظار تأكيد المستخدم...",
|
||||
"prefixAdded": "تمت إضافة البادئة، متابعة الاستيراد...",
|
||||
"skipPrefix": "تخطى المستخدم إضافة البادئة",
|
||||
"readFileFailedLog": "فشل قراءة الملف",
|
||||
"importCommentsDone": "اكتمل الاستيراد: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "إدارة التعليقات",
|
||||
"statusFilter": {
|
||||
"all": "كل الحالات",
|
||||
"approved": "تمت الموافقة",
|
||||
"pending": "قيد الانتظار",
|
||||
"rejected": "مرفوض"
|
||||
},
|
||||
"refresh": "تحديث",
|
||||
"table": {
|
||||
"author": "المستخدم",
|
||||
"content": "المحتوى",
|
||||
"path": "المسار",
|
||||
"status": "الحالة",
|
||||
"actions": "إجراءات",
|
||||
"admin": "المسؤول",
|
||||
"time": "الوقت",
|
||||
"ip": "IP",
|
||||
"email": "البريد الإلكتروني"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "موافقة",
|
||||
"pending": "انتظار",
|
||||
"reject": "رفض",
|
||||
"edit": "تحرير",
|
||||
"delete": "حذف",
|
||||
"blockIp": "حظر IP",
|
||||
"blockEmail": "حظر البريد الإلكتروني",
|
||||
"pin": "تثبيت"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "السابق",
|
||||
"next": "التالي",
|
||||
"jumpTo": "انتقال إلى",
|
||||
"page": "صفحة",
|
||||
"confirm": "تأكيد"
|
||||
},
|
||||
"confirmDelete": "هل أنت متأكد من حذف التعليق {id}؟",
|
||||
"confirmBlockIp": "هل أنت متأكد من إضافة IP {ip} إلى القائمة السوداء؟",
|
||||
"confirmBlockEmail": "هل أنت متأكد من إضافة البريد الإلكتروني {email} إلى القائمة السوداء؟",
|
||||
"successBlockIp": "تمت إضافة IP إلى القائمة السوداء",
|
||||
"successBlockEmail": "تمت إضافة البريد الإلكتروني إلى القائمة السوداء",
|
||||
"empty": "لا توجد بيانات",
|
||||
"editModal": {
|
||||
"title": "تحرير التعليق",
|
||||
"name": "اسم الزائر",
|
||||
"email": "بريد الزائر",
|
||||
"url": "رابط الزائر",
|
||||
"postSlug": "معرف الصفحة",
|
||||
"postUrl": "رابط التعليق",
|
||||
"content": "محتوى التعليق",
|
||||
"status": "الحالة",
|
||||
"priority": "الأولوية (1 افتراضي، الرقم الأكبر يظهر أولاً)",
|
||||
"cancel": "إلغاء",
|
||||
"save": "حفظ",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "إعدادات الموقع",
|
||||
"tabs": {
|
||||
"comment": "التعليقات والأمان",
|
||||
"feature": "مفاتيح الميزات",
|
||||
"emailNotify": "إشعارات البريد",
|
||||
"telegramNotify": "إشعارات Telegram",
|
||||
"display": "العرض"
|
||||
},
|
||||
"comment": {
|
||||
"title": "تكوين عرض التعليقات",
|
||||
"adminEmail": "بريد المسؤول",
|
||||
"adminBadge": "نص شارة المسؤول (اتركه فارغاً لاستخدام الرمز الافتراضي)",
|
||||
"adminEnabled": "تمكين عرض شارة المسؤول",
|
||||
"avatarPrefix": "بادئة الصورة الرمزية (الافتراضي: https://gravatar.com/avatar)",
|
||||
"securityTitle": "إعدادات الأمان",
|
||||
"requireReview": "هل تتطلب التعليقات الجديدة مراجعة قبل العرض",
|
||||
"adminKey": "مفتاح تعليق المسؤول (مطلوب عند استخدام بريد المسؤول للتعليق)",
|
||||
"adminKeyPlaceholder": "أدخل المفتاح للإعداد أو التعديل",
|
||||
"allowedDomains": "النطاقات المسموح بها (اتركه فارغاً للسماح للكل، افصل بفواصل أو مسافات)",
|
||||
"blockedIps": "القائمة السوداء لـ IP (افصل بفواصل أو أسطر جديدة)",
|
||||
"blockedEmails": "القائمة السوداء للبريد الإلكتروني (افصل بفواصل أو أسطر جديدة)",
|
||||
"save": "حفظ",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "مفاتيح الميزات",
|
||||
"articleLike": "تمكين إعجاب المقال",
|
||||
"articleLikeHint": "عند التمكين، سيظهر زر الإعجاب بالمقال أعلى قسم التعليقات.",
|
||||
"commentLike": "تمكين إعجاب التعليق",
|
||||
"commentLikeHint": "عند التمكين، سيظهر زر إعجاب لكل تعليق.",
|
||||
"imageLightbox": "وضع الصندوق المضيء للصور",
|
||||
"imageLightboxHint": "عند التمكين، سيؤدي النقر على الصور في التعليقات إلى تكبيرها بملء الشاشة.",
|
||||
"placeholder": "نص العنصر النائب لمربع التعليق",
|
||||
"placeholderHint": "نص مخصص لمربع الإدخال. اتركه فارغاً لاستخدام الافتراضي.",
|
||||
"widgetLanguage": "لغة الأداة",
|
||||
"widgetLanguageHint": "تعيين لغة أداة التعليقات في الواجهة الأمامية.",
|
||||
"save": "حفظ",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "إعدادات البريد الإلكتروني",
|
||||
"enable": "تمكين إشعارات البريد",
|
||||
"smtpTitle": "1. تكوين SMTP",
|
||||
"provider": "مقدم الخدمة",
|
||||
"host": "خادم SMTP",
|
||||
"port": "منفذ SMTP",
|
||||
"secure": "اتصال SSL آمن",
|
||||
"user": "حساب البريد الإلكتروني",
|
||||
"pass": "كلمة المرور/رمز التفويض",
|
||||
"qqHint": "ملاحظة: لبريد QQ، استخدم رمز التفويض بدلاً من كلمة المرور.",
|
||||
"163Hint": "ملاحظة: لبريد 163، استخدم رمز التفويض بدلاً من كلمة المرور.",
|
||||
"templateTitle": "2. قوالب البريد الإلكتروني",
|
||||
"adminTemplate": "قالب إشعار المسؤول (HTML)",
|
||||
"adminTemplateHint": "المتغيرات المتاحة: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "قالب إشعار الرد (HTML)",
|
||||
"replyTemplateHint": "المتغيرات المتاحة: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "إرسال بريد تجريبي",
|
||||
"testingBtn": "جارٍ الإرسال...",
|
||||
"resetBtn": "استعادة القوالب الافتراضية",
|
||||
"save": "حفظ التكوين",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "إعدادات Telegram",
|
||||
"enable": "تمكين إشعارات Telegram",
|
||||
"botToken": "رمز البوت (Bot Token)",
|
||||
"botTokenHint": "ابحث عن @BotFather في Telegram لإنشاء بوت والحصول على الرمز",
|
||||
"chatId": "معرف المحادثة (Chat ID)",
|
||||
"chatIdHint": "معرف المستخدم أو المجموعة. أرسل رسالة للبوت واستخدم API أو @userinfobot للعثور عليه.",
|
||||
"webhookBtn": "إعداد Webhook",
|
||||
"webhookSetting": "جارٍ الإعداد...",
|
||||
"testBtn": "إرسال رسالة تجريبية",
|
||||
"testingBtn": "جارٍ الإرسال...",
|
||||
"save": "حفظ",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
},
|
||||
"display": {
|
||||
"title": "إعدادات العرض",
|
||||
"layoutTitle": "عنوان الخلفية",
|
||||
"layoutTitleHint": "يظهر في شريط التنقل العلوي.",
|
||||
"adminLanguage": "لغة الخلفية",
|
||||
"adminLanguageHint": "تعيين لغة نظام الإدارة.",
|
||||
"save": "حفظ",
|
||||
"saving": "جارٍ الحفظ..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "تم الحفظ بنجاح",
|
||||
"saveFailed": "فشل الحفظ",
|
||||
"loading": "جارٍ التحميل..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/de.json
Normal file
304
cwd-admin/src/locales/de.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Kommentarverwaltung",
|
||||
"stats": "Dashboard",
|
||||
"analytics": "Statistiken",
|
||||
"settings": "Einstellungen",
|
||||
"data": "Datenverwaltung"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Menü umschalten",
|
||||
"docs": "Dokumentation",
|
||||
"logout": "Abmelden",
|
||||
"moreActions": "Mehr Aktionen",
|
||||
"defaultSite": "Standardseite",
|
||||
"theme": {
|
||||
"light": "Hell",
|
||||
"dark": "Dunkel",
|
||||
"system": "System"
|
||||
},
|
||||
"version": {
|
||||
"title": "Versionsinfo",
|
||||
"apiAddress": "API-Adresse",
|
||||
"apiVersion": "API-Version",
|
||||
"adminVersion": "Admin-Version",
|
||||
"match": "Admin- und API-Versionen stimmen überein.",
|
||||
"mismatch": "Versionskonflikt. Bitte aktualisieren Sie den API-Dienst.",
|
||||
"fetchError": "Versionsabruf fehlgeschlagen:",
|
||||
"loading": "Laden...",
|
||||
"notConfigured": "Nicht konfiguriert",
|
||||
"notFetched": "Nicht abgerufen",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dashboard",
|
||||
"overview": "Übersicht",
|
||||
"total": "Gesamtkommentare",
|
||||
"approved": "Genehmigt",
|
||||
"pending": "Ausstehend",
|
||||
"rejected": "Abgelehnt",
|
||||
"trend": "Kommentartrend",
|
||||
"bySite": "Nach Seite",
|
||||
"last7Days": "Letzte 7 Tage",
|
||||
"last30Days": "Letzte 30 Tage",
|
||||
"noData": "Keine Daten",
|
||||
"table": {
|
||||
"domain": "Domain",
|
||||
"total": "Gesamt",
|
||||
"approved": "Genehmigt",
|
||||
"pending": "Ausstehend",
|
||||
"rejected": "Abgelehnt"
|
||||
},
|
||||
"loadError": "Fehler beim Laden der Statistiken"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Statistiken",
|
||||
"overview": "Übersicht",
|
||||
"totalPv": "Gesamt-PV",
|
||||
"todayPv": "Heute PV",
|
||||
"weekPv": "Woche PV",
|
||||
"monthPv": "Monat PV",
|
||||
"totalPages": "Besuchte Seiten",
|
||||
"trend": "Traffic-Trend",
|
||||
"pageDetail": "Seitendetails",
|
||||
"likeRank": "Top-Likes",
|
||||
"last7Days": "Letzte 7 Tage",
|
||||
"last30Days": "Letzte 30 Tage",
|
||||
"sort": {
|
||||
"pv": "Nach PV sortieren",
|
||||
"latest": "Zuletzt besucht"
|
||||
},
|
||||
"table": {
|
||||
"title": "Seitentitel",
|
||||
"pv": "PV",
|
||||
"time": "Letzter Besuch",
|
||||
"url": "URL",
|
||||
"rank": "Rang",
|
||||
"like": "Likes"
|
||||
},
|
||||
"noData": "Keine Daten",
|
||||
"noLikeData": "Keine Like-Daten",
|
||||
"loadError": "Fehler beim Laden der Analysen"
|
||||
},
|
||||
"data": {
|
||||
"title": "Datenverwaltung",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Kommentardaten",
|
||||
"desc": "Kommentare verwalten und importieren.",
|
||||
"exportLabel": "Export:",
|
||||
"exporting": "Export läuft...",
|
||||
"exportJson": "JSON exportieren",
|
||||
"importLabel": "Import:",
|
||||
"importButton": "Kommentare importieren",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Systemkonfig",
|
||||
"desc": "Einstellungen, E-Mail, Blocklisten, etc.",
|
||||
"export": "Konfig exportieren",
|
||||
"import": "Konfig importieren"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Analysedaten",
|
||||
"desc": "Aufrufe, Likes und Trends.",
|
||||
"export": "Statistiken exportieren",
|
||||
"import": "Statistiken importieren"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Vollbackup",
|
||||
"desc": "Alles sichern oder wiederherstellen (Kommentare + Konfig + Stats).",
|
||||
"export": "Vollexport",
|
||||
"import": "Vollwiederherstellung"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Betriebsprotokolle"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "URL-Präfix fehlt",
|
||||
"descPart1": "Erkannt: ",
|
||||
"descPart2": " Kommentare ohne Protokoll-Präfix (http/https).",
|
||||
"descPart3": "Beim Import hinzufügen?",
|
||||
"label": "Domain-Präfix (z.B. https://example.me)",
|
||||
"placeholder": "Präfix eingeben",
|
||||
"skip": "Überspringen",
|
||||
"confirm": "Hinzufügen & Importieren"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Export erfolgreich",
|
||||
"exportFailed": "Export fehlgeschlagen",
|
||||
"fileReadFailed": "Dateilesefehler",
|
||||
"jsonParseFailed": "JSON-Parse-Fehler",
|
||||
"importConfigSuccess": "Konfig importiert",
|
||||
"importStatsSuccess": "Statistiken importiert",
|
||||
"importBackupSuccess": "Vollwiederherstellung erfolgreich",
|
||||
"importCommentsSuccess": "Kommentare importiert",
|
||||
"prefixRequired": "Bitte Präfix eingeben",
|
||||
"importStart": "Import: {name} (Modus: {mode})",
|
||||
"fileParseSuccess": "Datei geparst, verarbeite...",
|
||||
"errorWithMessage": "Fehler: {msg}",
|
||||
"parsedCommentsCount": "{count} Kommentare geparst",
|
||||
"detectMissingPrefix": "{count} URLs ohne Präfix, warte auf Bestätigung...",
|
||||
"prefixAdded": "Präfix hinzugefügt, fahre fort...",
|
||||
"skipPrefix": "Präfix übersprungen",
|
||||
"readFileFailedLog": "Dateilesefehler",
|
||||
"importCommentsDone": "Import fertig: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Kommentarverwaltung",
|
||||
"statusFilter": {
|
||||
"all": "Alle",
|
||||
"approved": "Genehmigt",
|
||||
"pending": "Ausstehend",
|
||||
"rejected": "Abgelehnt"
|
||||
},
|
||||
"refresh": "Aktualisieren",
|
||||
"table": {
|
||||
"author": "Benutzer",
|
||||
"content": "Kommentar",
|
||||
"path": "Pfad",
|
||||
"status": "Status",
|
||||
"actions": "Aktionen",
|
||||
"admin": "Admin",
|
||||
"time": "Zeit",
|
||||
"ip": "IP",
|
||||
"email": "E-Mail"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Genehmigen",
|
||||
"pending": "Zurückstellen",
|
||||
"reject": "Ablehnen",
|
||||
"edit": "Bearbeiten",
|
||||
"delete": "Löschen",
|
||||
"blockIp": "IP blockieren",
|
||||
"blockEmail": "E-Mail blockieren",
|
||||
"pin": "Anpinnen"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Zurück",
|
||||
"next": "Weiter",
|
||||
"jumpTo": "Gehe zu",
|
||||
"page": "Seite",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "Kommentar {id} löschen?",
|
||||
"confirmBlockIp": "IP {ip} blockieren?",
|
||||
"confirmBlockEmail": "E-Mail {email} blockieren?",
|
||||
"successBlockIp": "IP blockiert",
|
||||
"successBlockEmail": "E-Mail blockiert",
|
||||
"empty": "Keine Daten",
|
||||
"editModal": {
|
||||
"title": "Kommentar bearbeiten",
|
||||
"name": "Name",
|
||||
"email": "E-Mail",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "Post-URL",
|
||||
"content": "Inhalt",
|
||||
"status": "Status",
|
||||
"priority": "Priorität (1=Normal, höher=Oben)",
|
||||
"cancel": "Abbrechen",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Einstellungen",
|
||||
"tabs": {
|
||||
"comment": "Kommentare & Sicherheit",
|
||||
"feature": "Funktionen",
|
||||
"emailNotify": "E-Mail-Benachrichtigung",
|
||||
"telegramNotify": "Telegram-Benachrichtigung",
|
||||
"display": "Anzeige"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Kommentaranzeige",
|
||||
"adminEmail": "Admin-E-Mail",
|
||||
"adminBadge": "Admin-Badge-Text (Leer für Standard-Icon)",
|
||||
"adminEnabled": "Admin-Badge anzeigen",
|
||||
"avatarPrefix": "Avatar-Präfix (Standard: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Sicherheit",
|
||||
"requireReview": "Überprüfung für neue Kommentare erforderlich",
|
||||
"adminKey": "Admin-Schlüssel (Erforderlich für Admin-E-Mail-Kommentare)",
|
||||
"adminKeyPlaceholder": "Schlüssel eingeben",
|
||||
"allowedDomains": "Erlaubte Domains (Leer für alle. Trennung durch Leerzeichen/Komma)",
|
||||
"blockedIps": "Blockierte IPs (Trennung durch Komma/Zeilenumbruch)",
|
||||
"blockedEmails": "Blockierte E-Mails (Trennung durch Komma/Zeilenumbruch)",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Funktionen",
|
||||
"articleLike": "Artikel-Likes aktivieren",
|
||||
"articleLikeHint": "Like-Button oben im Kommentarbereich anzeigen.",
|
||||
"commentLike": "Kommentar-Likes aktivieren",
|
||||
"commentLikeHint": "Like-Button bei jedem Kommentar anzeigen.",
|
||||
"imageLightbox": "Bild-Lightbox",
|
||||
"imageLightboxHint": "Vollbildvorschau für Bilder in Kommentaren.",
|
||||
"placeholder": "Platzhaltertext",
|
||||
"placeholderHint": "Benutzerdefinierter Platzhalter für Kommentareingabe.",
|
||||
"widgetLanguage": "Widget-Sprache",
|
||||
"widgetLanguageHint": "Sprache für das Frontend-Widget.",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "E-Mail-Benachrichtigung",
|
||||
"enable": "E-Mail-Benachrichtigung aktivieren",
|
||||
"smtpTitle": "1. SMTP-Konfig",
|
||||
"provider": "Anbieter",
|
||||
"host": "SMTP-Host",
|
||||
"port": "SMTP-Port",
|
||||
"secure": "SSL-Sicherheit",
|
||||
"user": "E-Mail-Benutzer",
|
||||
"pass": "Passwort/App-Token",
|
||||
"qqHint": "Hinweis: Für QQ Mail App-Token verwenden.",
|
||||
"163Hint": "Hinweis: Für 163 Mail App-Token verwenden.",
|
||||
"templateTitle": "2. Vorlagen-Konfig",
|
||||
"adminTemplate": "Admin-Vorlage (HTML)",
|
||||
"adminTemplateHint": "Vars: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Antwort-Vorlage (HTML)",
|
||||
"replyTemplateHint": "Vars: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Test-E-Mail senden",
|
||||
"testingBtn": "Sendet...",
|
||||
"resetBtn": "Vorlagen zurücksetzen",
|
||||
"save": "Konfig speichern",
|
||||
"saving": "Speichert..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram-Benachrichtigung",
|
||||
"enable": "Telegram-Benachrichtigung aktivieren",
|
||||
"botToken": "Bot-Token",
|
||||
"botTokenHint": "Von @BotFather erhalten",
|
||||
"chatId": "Chat-ID",
|
||||
"chatIdHint": "Benutzer-ID oder Gruppen-ID. @userinfobot verwenden.",
|
||||
"webhookBtn": "Webhook setzen",
|
||||
"webhookSetting": "Setze...",
|
||||
"testBtn": "Testnachricht senden",
|
||||
"testingBtn": "Sendet...",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Anzeigeeinstellungen",
|
||||
"layoutTitle": "Admin-Titel",
|
||||
"layoutTitleHint": "Wird in der oberen Navigationsleiste angezeigt.",
|
||||
"adminLanguage": "Admin-Sprache",
|
||||
"adminLanguageHint": "Sprache für das Admin-Panel.",
|
||||
"save": "Speichern",
|
||||
"saving": "Speichert..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Erfolgreich gespeichert",
|
||||
"saveFailed": "Speichern fehlgeschlagen",
|
||||
"loading": "Laden..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/en-US.json
Normal file
304
cwd-admin/src/locales/en-US.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Comments",
|
||||
"stats": "Dashboard",
|
||||
"analytics": "Analytics",
|
||||
"settings": "Settings",
|
||||
"data": "Data"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Toggle Menu",
|
||||
"docs": "Documentation",
|
||||
"logout": "Logout",
|
||||
"moreActions": "More Actions",
|
||||
"defaultSite": "Default Site",
|
||||
"theme": {
|
||||
"light": "Light",
|
||||
"dark": "Dark",
|
||||
"system": "System"
|
||||
},
|
||||
"version": {
|
||||
"title": "Version Info",
|
||||
"apiAddress": "API Address",
|
||||
"apiVersion": "API Version",
|
||||
"adminVersion": "Admin Version",
|
||||
"match": "Admin and API versions match.",
|
||||
"mismatch": "Version mismatch. Please update API service to match Admin version.",
|
||||
"fetchError": "Failed to fetch version:",
|
||||
"loading": "Loading...",
|
||||
"notConfigured": "Not Configured",
|
||||
"notFetched": "Not Fetched",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dashboard",
|
||||
"overview": "Overview",
|
||||
"total": "Total Comments",
|
||||
"approved": "Approved",
|
||||
"pending": "Pending",
|
||||
"rejected": "Rejected",
|
||||
"trend": "Comment Trend",
|
||||
"bySite": "By Site",
|
||||
"last7Days": "Last 7 Days",
|
||||
"last30Days": "Last 30 Days",
|
||||
"noData": "No Data",
|
||||
"table": {
|
||||
"domain": "Domain",
|
||||
"total": "Total",
|
||||
"approved": "Approved",
|
||||
"pending": "Pending",
|
||||
"rejected": "Rejected"
|
||||
},
|
||||
"loadError": "Failed to load stats"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analytics",
|
||||
"overview": "Overview",
|
||||
"totalPv": "Total PV",
|
||||
"todayPv": "Today PV",
|
||||
"weekPv": "Week PV",
|
||||
"monthPv": "Month PV",
|
||||
"totalPages": "Pages Visited",
|
||||
"trend": "Traffic Trend",
|
||||
"pageDetail": "Page Details",
|
||||
"likeRank": "Top Liked Pages",
|
||||
"last7Days": "Last 7 Days",
|
||||
"last30Days": "Last 30 Days",
|
||||
"sort": {
|
||||
"pv": "Sort by PV",
|
||||
"latest": "Latest Visited"
|
||||
},
|
||||
"table": {
|
||||
"title": "Page Title",
|
||||
"pv": "PV",
|
||||
"time": "Last Visit",
|
||||
"url": "URL",
|
||||
"rank": "Rank",
|
||||
"like": "Likes"
|
||||
},
|
||||
"noData": "No Data",
|
||||
"noLikeData": "No Like Data",
|
||||
"loadError": "Failed to load analytics"
|
||||
},
|
||||
"data": {
|
||||
"title": "Data Management",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Comments",
|
||||
"desc": "Manage comments and import from other frameworks.",
|
||||
"exportLabel": "Export:",
|
||||
"exporting": "Exporting...",
|
||||
"exportJson": "Export JSON",
|
||||
"importLabel": "Import:",
|
||||
"importButton": "Import Comments",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "System Config",
|
||||
"desc": "Manage settings, email config, blocklists, etc.",
|
||||
"export": "Export Config",
|
||||
"import": "Import Config"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Analytics Data",
|
||||
"desc": "Manage page views, likes, and trends.",
|
||||
"export": "Export Stats",
|
||||
"import": "Import Stats"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Full Backup",
|
||||
"desc": "Backup or restore all system data (Comments + Config + Stats).",
|
||||
"export": "Full Export",
|
||||
"import": "Full Restore"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Operation Logs"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Missing URL Prefix Detected",
|
||||
"descPart1": "Detected ",
|
||||
"descPart2": " comments with URL missing protocol prefix (http/https).",
|
||||
"descPart3": "Add prefix during import?",
|
||||
"label": "Domain Prefix (e.g. https://example.me)",
|
||||
"placeholder": "Enter domain prefix",
|
||||
"skip": "Skip (Don't Add)",
|
||||
"confirm": "Add & Import"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Export Success",
|
||||
"exportFailed": "Export Failed",
|
||||
"fileReadFailed": "File Read Failed",
|
||||
"jsonParseFailed": "JSON Parse Failed",
|
||||
"importConfigSuccess": "Config Imported",
|
||||
"importStatsSuccess": "Stats Imported",
|
||||
"importBackupSuccess": "Full Restore Success",
|
||||
"importCommentsSuccess": "Comments Imported",
|
||||
"prefixRequired": "Please enter domain prefix",
|
||||
"importStart": "Importing: {name} (Mode: {mode})",
|
||||
"fileParseSuccess": "File parsed, processing...",
|
||||
"errorWithMessage": "Error: {msg}",
|
||||
"parsedCommentsCount": "Parsed {count} comments",
|
||||
"detectMissingPrefix": "Detected {count} URLs missing prefix, waiting for confirmation...",
|
||||
"prefixAdded": "Prefix added, continuing...",
|
||||
"skipPrefix": "Skipped prefix addition",
|
||||
"readFileFailedLog": "Read file failed",
|
||||
"importCommentsDone": "Import Done: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Comment Management",
|
||||
"statusFilter": {
|
||||
"all": "All",
|
||||
"approved": "Approved",
|
||||
"pending": "Pending",
|
||||
"rejected": "Rejected"
|
||||
},
|
||||
"refresh": "Refresh",
|
||||
"table": {
|
||||
"author": "User",
|
||||
"content": "Comment",
|
||||
"path": "Path",
|
||||
"status": "Status",
|
||||
"actions": "Actions",
|
||||
"admin": "Admin",
|
||||
"time": "Time",
|
||||
"ip": "IP",
|
||||
"email": "Email"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Approve",
|
||||
"pending": "Pending",
|
||||
"reject": "Reject",
|
||||
"edit": "Edit",
|
||||
"delete": "Delete",
|
||||
"blockIp": "Block IP",
|
||||
"blockEmail": "Block Email",
|
||||
"pin": "Pin"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Prev",
|
||||
"next": "Next",
|
||||
"jumpTo": "Go to",
|
||||
"page": "Page",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "Delete comment {id}?",
|
||||
"confirmBlockIp": "Block IP {ip}?",
|
||||
"confirmBlockEmail": "Block Email {email}?",
|
||||
"successBlockIp": "IP Blocked",
|
||||
"successBlockEmail": "Email Blocked",
|
||||
"empty": "No Data",
|
||||
"editModal": {
|
||||
"title": "Edit Comment",
|
||||
"name": "Nickname",
|
||||
"email": "Email",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "Post URL",
|
||||
"content": "Content",
|
||||
"status": "Status",
|
||||
"priority": "Priority (1=Normal, higher=Top)",
|
||||
"cancel": "Cancel",
|
||||
"save": "Save",
|
||||
"saving": "Saving..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Settings",
|
||||
"tabs": {
|
||||
"comment": "Comments & Security",
|
||||
"feature": "Features",
|
||||
"emailNotify": "Email Notify",
|
||||
"telegramNotify": "Telegram Notify",
|
||||
"display": "Display"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Comment Display",
|
||||
"adminEmail": "Admin Email",
|
||||
"adminBadge": "Admin Badge Text (Empty for default icon)",
|
||||
"adminEnabled": "Show Admin Badge",
|
||||
"avatarPrefix": "Avatar Prefix (Default: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Security",
|
||||
"requireReview": "Require Review for New Comments",
|
||||
"adminKey": "Admin Key (Required for admin email comments)",
|
||||
"adminKeyPlaceholder": "Enter key to set or change",
|
||||
"allowedDomains": "Allowed Domains (Empty to allow all. Split by space or comma)",
|
||||
"blockedIps": "Blocked IPs (Split by comma or newline)",
|
||||
"blockedEmails": "Blocked Emails (Split by comma or newline)",
|
||||
"save": "Save",
|
||||
"saving": "Saving..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Features",
|
||||
"articleLike": "Enable Article Likes",
|
||||
"articleLikeHint": "Show like button at top of comments.",
|
||||
"commentLike": "Enable Comment Likes",
|
||||
"commentLikeHint": "Show like button on each comment.",
|
||||
"imageLightbox": "Image Lightbox",
|
||||
"imageLightboxHint": "Enable fullscreen preview for images in comments.",
|
||||
"placeholder": "Placeholder Text",
|
||||
"placeholderHint": "Custom placeholder for comment input.",
|
||||
"widgetLanguage": "Widget Language",
|
||||
"widgetLanguageHint": "Language for the frontend widget.",
|
||||
"save": "Save",
|
||||
"saving": "Saving..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Email Notification",
|
||||
"enable": "Enable Email Notify",
|
||||
"smtpTitle": "1. SMTP Config",
|
||||
"provider": "Provider",
|
||||
"host": "SMTP Host",
|
||||
"port": "SMTP Port",
|
||||
"secure": "SSL Secure",
|
||||
"user": "Email User",
|
||||
"pass": "Password/App Token",
|
||||
"qqHint": "Note: For QQ Mail, use App Token instead of password.",
|
||||
"163Hint": "Note: For 163 Mail, use App Token instead of password.",
|
||||
"templateTitle": "2. Template Config",
|
||||
"adminTemplate": "Admin Template (HTML)",
|
||||
"adminTemplateHint": "Vars: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Reply Template (HTML)",
|
||||
"replyTemplateHint": "Vars: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Send Test Email",
|
||||
"testingBtn": "Sending...",
|
||||
"resetBtn": "Reset Templates",
|
||||
"save": "Save Config",
|
||||
"saving": "Saving..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram Notification",
|
||||
"enable": "Enable Telegram Notify",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "Get from @BotFather",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "User ID or Group ID. Use @userinfobot to find.",
|
||||
"webhookBtn": "Set Webhook",
|
||||
"webhookSetting": "Setting...",
|
||||
"testBtn": "Send Test Message",
|
||||
"testingBtn": "Sending...",
|
||||
"save": "Save",
|
||||
"saving": "Saving..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Display Settings",
|
||||
"layoutTitle": "Admin Title",
|
||||
"layoutTitleHint": "Displayed in top navigation bar.",
|
||||
"adminLanguage": "Admin Language",
|
||||
"adminLanguageHint": "Language for the admin panel.",
|
||||
"save": "Save",
|
||||
"saving": "Saving..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Saved Successfully",
|
||||
"saveFailed": "Save Failed",
|
||||
"loading": "Loading..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/es.json
Normal file
304
cwd-admin/src/locales/es.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Gestión de Comentarios",
|
||||
"stats": "Panel de Control",
|
||||
"analytics": "Analítica",
|
||||
"settings": "Ajustes",
|
||||
"data": "Datos"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Alternar Menú",
|
||||
"docs": "Documentación",
|
||||
"logout": "Cerrar Sesión",
|
||||
"moreActions": "Más Acciones",
|
||||
"defaultSite": "Sitio Predeterminado",
|
||||
"theme": {
|
||||
"light": "Claro",
|
||||
"dark": "Oscuro",
|
||||
"system": "Sistema"
|
||||
},
|
||||
"version": {
|
||||
"title": "Info de Versión",
|
||||
"apiAddress": "Dirección API",
|
||||
"apiVersion": "Versión API",
|
||||
"adminVersion": "Versión Admin",
|
||||
"match": "Las versiones Admin y API coinciden.",
|
||||
"mismatch": "Versión no coincidente. Actualice el servicio API.",
|
||||
"fetchError": "Error al obtener versión:",
|
||||
"loading": "Cargando...",
|
||||
"notConfigured": "No Configurado",
|
||||
"notFetched": "No Obtenido",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Panel de Control",
|
||||
"overview": "Resumen",
|
||||
"total": "Total Comentarios",
|
||||
"approved": "Aprobados",
|
||||
"pending": "Pendientes",
|
||||
"rejected": "Rechazados",
|
||||
"trend": "Tendencia",
|
||||
"bySite": "Por Sitio",
|
||||
"last7Days": "Últimos 7 Días",
|
||||
"last30Days": "Últimos 30 Días",
|
||||
"noData": "Sin Datos",
|
||||
"table": {
|
||||
"domain": "Dominio",
|
||||
"total": "Total",
|
||||
"approved": "Aprobados",
|
||||
"pending": "Pendientes",
|
||||
"rejected": "Rechazados"
|
||||
},
|
||||
"loadError": "Error al cargar estadísticas"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analítica",
|
||||
"overview": "Resumen",
|
||||
"totalPv": "PV Total",
|
||||
"todayPv": "PV Hoy",
|
||||
"weekPv": "PV Semana",
|
||||
"monthPv": "PV Mes",
|
||||
"totalPages": "Páginas Visitadas",
|
||||
"trend": "Tendencia Tráfico",
|
||||
"pageDetail": "Detalles Página",
|
||||
"likeRank": "Top Likes",
|
||||
"last7Days": "Últimos 7 Días",
|
||||
"last30Days": "Últimos 30 Días",
|
||||
"sort": {
|
||||
"pv": "Ordenar por PV",
|
||||
"latest": "Última Visita"
|
||||
},
|
||||
"table": {
|
||||
"title": "Título Página",
|
||||
"pv": "PV",
|
||||
"time": "Última Visita",
|
||||
"url": "URL",
|
||||
"rank": "Rango",
|
||||
"like": "Me gusta"
|
||||
},
|
||||
"noData": "Sin Datos",
|
||||
"noLikeData": "Sin Datos de Me gusta",
|
||||
"loadError": "Error al cargar analítica"
|
||||
},
|
||||
"data": {
|
||||
"title": "Gestión de Datos",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Datos Comentarios",
|
||||
"desc": "Gestionar e importar comentarios.",
|
||||
"exportLabel": "Exportar:",
|
||||
"exporting": "Exportando...",
|
||||
"exportJson": "Exportar JSON",
|
||||
"importLabel": "Importar:",
|
||||
"importButton": "Importar Comentarios",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Config Sistema",
|
||||
"desc": "Ajustes, correo, lista negra, etc.",
|
||||
"export": "Exportar Config",
|
||||
"import": "Importar Config"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Datos Analíticos",
|
||||
"desc": "Vistas, likes y tendencias.",
|
||||
"export": "Exportar Stats",
|
||||
"import": "Importar Stats"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Copia de Seguridad Completa",
|
||||
"desc": "Copia o restaura todo (Comentarios + Config + Stats).",
|
||||
"export": "Exportación Completa",
|
||||
"import": "Restauración Completa"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Registros de Operación"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Prefijo URL Faltante",
|
||||
"descPart1": "Detectados ",
|
||||
"descPart2": " comentarios sin prefijo de protocolo (http/https).",
|
||||
"descPart3": "¿Añadir al importar?",
|
||||
"label": "Prefijo Dominio (ej. https://example.me)",
|
||||
"placeholder": "Introducir prefijo",
|
||||
"skip": "Omitir",
|
||||
"confirm": "Añadir e Importar"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Exportación Exitosa",
|
||||
"exportFailed": "Fallo Exportación",
|
||||
"fileReadFailed": "Fallo Lectura Archivo",
|
||||
"jsonParseFailed": "Fallo Análisis JSON",
|
||||
"importConfigSuccess": "Config Importada",
|
||||
"importStatsSuccess": "Stats Importadas",
|
||||
"importBackupSuccess": "Restauración Completa Exitosa",
|
||||
"importCommentsSuccess": "Comentarios Importados",
|
||||
"prefixRequired": "Por favor introduzca prefijo",
|
||||
"importStart": "Importando: {name} (Modo: {mode})",
|
||||
"fileParseSuccess": "Archivo analizado, procesando...",
|
||||
"errorWithMessage": "Error: {msg}",
|
||||
"parsedCommentsCount": "{count} comentarios analizados",
|
||||
"detectMissingPrefix": "{count} URLs sin prefijo, esperando confirmación...",
|
||||
"prefixAdded": "Prefijo añadido, continuando...",
|
||||
"skipPrefix": "Adición prefijo omitida",
|
||||
"readFileFailedLog": "Fallo lectura archivo",
|
||||
"importCommentsDone": "Importación Hecha: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Gestión Comentarios",
|
||||
"statusFilter": {
|
||||
"all": "Todos",
|
||||
"approved": "Aprobados",
|
||||
"pending": "Pendientes",
|
||||
"rejected": "Rechazados"
|
||||
},
|
||||
"refresh": "Refrescar",
|
||||
"table": {
|
||||
"author": "Usuario",
|
||||
"content": "Comentario",
|
||||
"path": "Ruta",
|
||||
"status": "Estado",
|
||||
"actions": "Acciones",
|
||||
"admin": "Admin",
|
||||
"time": "Hora",
|
||||
"ip": "IP",
|
||||
"email": "Correo"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Aprobar",
|
||||
"pending": "Pendiente",
|
||||
"reject": "Rechazar",
|
||||
"edit": "Editar",
|
||||
"delete": "Eliminar",
|
||||
"blockIp": "Bloquear IP",
|
||||
"blockEmail": "Bloquear Correo",
|
||||
"pin": "Fijar"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Ant",
|
||||
"next": "Sig",
|
||||
"jumpTo": "Ir a",
|
||||
"page": "Página",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "¿Eliminar comentario {id}?",
|
||||
"confirmBlockIp": "¿Bloquear IP {ip}?",
|
||||
"confirmBlockEmail": "¿Bloquear correo {email}?",
|
||||
"successBlockIp": "IP Bloqueada",
|
||||
"successBlockEmail": "Correo Bloqueado",
|
||||
"empty": "Sin Datos",
|
||||
"editModal": {
|
||||
"title": "Editar Comentario",
|
||||
"name": "Nombre",
|
||||
"email": "Correo",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "URL Post",
|
||||
"content": "Contenido",
|
||||
"status": "Estado",
|
||||
"priority": "Prioridad (1=Normal, mayor=Arriba)",
|
||||
"cancel": "Cancelar",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Ajustes",
|
||||
"tabs": {
|
||||
"comment": "Comentarios y Seguridad",
|
||||
"feature": "Características",
|
||||
"emailNotify": "Notificación Correo",
|
||||
"telegramNotify": "Notificación Telegram",
|
||||
"display": "Visualización"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Visualización Comentarios",
|
||||
"adminEmail": "Correo Admin",
|
||||
"adminBadge": "Texto Insignia Admin (Vacío para icono por defecto)",
|
||||
"adminEnabled": "Mostrar Insignia Admin",
|
||||
"avatarPrefix": "Prefijo Avatar (Defecto: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Seguridad",
|
||||
"requireReview": "Requerir Revisión para Nuevos Comentarios",
|
||||
"adminKey": "Clave Admin (Requerida para comentarios con correo admin)",
|
||||
"adminKeyPlaceholder": "Introducir clave",
|
||||
"allowedDomains": "Dominios Permitidos (Vacío para todos. Separar por espacio/coma)",
|
||||
"blockedIps": "IPs Bloqueadas (Separar por coma/nueva línea)",
|
||||
"blockedEmails": "Correos Bloqueados (Separar por coma/nueva línea)",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Características",
|
||||
"articleLike": "Habilitar Me gusta Artículo",
|
||||
"articleLikeHint": "Mostrar botón Me gusta arriba de comentarios.",
|
||||
"commentLike": "Habilitar Me gusta Comentario",
|
||||
"commentLikeHint": "Mostrar botón Me gusta en cada comentario.",
|
||||
"imageLightbox": "Lightbox Imagen",
|
||||
"imageLightboxHint": "Habilitar vista pantalla completa para imágenes.",
|
||||
"placeholder": "Texto Marcador",
|
||||
"placeholderHint": "Marcador personalizado para entrada de comentarios.",
|
||||
"widgetLanguage": "Idioma Widget",
|
||||
"widgetLanguageHint": "Idioma para el widget frontend.",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Notificación Correo",
|
||||
"enable": "Habilitar Notificación Correo",
|
||||
"smtpTitle": "1. Config SMTP",
|
||||
"provider": "Proveedor",
|
||||
"host": "Host SMTP",
|
||||
"port": "Puerto SMTP",
|
||||
"secure": "Seguridad SSL",
|
||||
"user": "Usuario Correo",
|
||||
"pass": "Contraseña/Token App",
|
||||
"qqHint": "Nota: Para QQ Mail, usar Token App.",
|
||||
"163Hint": "Nota: Para 163 Mail, usar Token App.",
|
||||
"templateTitle": "2. Config Plantillas",
|
||||
"adminTemplate": "Plantilla Admin (HTML)",
|
||||
"adminTemplateHint": "Vars: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Plantilla Respuesta (HTML)",
|
||||
"replyTemplateHint": "Vars: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Enviar Correo Prueba",
|
||||
"testingBtn": "Enviando...",
|
||||
"resetBtn": "Restablecer Plantillas",
|
||||
"save": "Guardar Config",
|
||||
"saving": "Guardando..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Notificación Telegram",
|
||||
"enable": "Habilitar Notificación Telegram",
|
||||
"botToken": "Token Bot",
|
||||
"botTokenHint": "Obtener de @BotFather",
|
||||
"chatId": "ID Chat",
|
||||
"chatIdHint": "ID Usuario o Grupo. Usar @userinfobot.",
|
||||
"webhookBtn": "Establecer Webhook",
|
||||
"webhookSetting": "Configurando...",
|
||||
"testBtn": "Enviar Mensaje Prueba",
|
||||
"testingBtn": "Enviando...",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Ajustes Visualización",
|
||||
"layoutTitle": "Título Admin",
|
||||
"layoutTitleHint": "Mostrado en barra navegación superior.",
|
||||
"adminLanguage": "Idioma Admin",
|
||||
"adminLanguageHint": "Idioma para el panel de administración.",
|
||||
"save": "Guardar",
|
||||
"saving": "Guardando..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Guardado Exitosamente",
|
||||
"saveFailed": "Fallo al Guardar",
|
||||
"loading": "Cargando..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/fr.json
Normal file
304
cwd-admin/src/locales/fr.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Gestion des Commentaires",
|
||||
"stats": "Tableau de Bord",
|
||||
"analytics": "Analytique",
|
||||
"settings": "Paramètres",
|
||||
"data": "Données"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Basculer le Menu",
|
||||
"docs": "Documentation",
|
||||
"logout": "Déconnexion",
|
||||
"moreActions": "Plus d'Actions",
|
||||
"defaultSite": "Site par Défaut",
|
||||
"theme": {
|
||||
"light": "Clair",
|
||||
"dark": "Sombre",
|
||||
"system": "Système"
|
||||
},
|
||||
"version": {
|
||||
"title": "Infos Version",
|
||||
"apiAddress": "Adresse API",
|
||||
"apiVersion": "Version API",
|
||||
"adminVersion": "Version Admin",
|
||||
"match": "Les versions Admin et API correspondent.",
|
||||
"mismatch": "Version incompatible. Veuillez mettre à jour le service API.",
|
||||
"fetchError": "Échec de récupération de version :",
|
||||
"loading": "Chargement...",
|
||||
"notConfigured": "Non Configuré",
|
||||
"notFetched": "Non Récupéré",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Tableau de Bord",
|
||||
"overview": "Aperçu",
|
||||
"total": "Total Commentaires",
|
||||
"approved": "Approuvés",
|
||||
"pending": "En Attente",
|
||||
"rejected": "Rejetés",
|
||||
"trend": "Tendance",
|
||||
"bySite": "Par Site",
|
||||
"last7Days": "7 Derniers Jours",
|
||||
"last30Days": "30 Derniers Jours",
|
||||
"noData": "Aucune Donnée",
|
||||
"table": {
|
||||
"domain": "Domaine",
|
||||
"total": "Total",
|
||||
"approved": "Approuvés",
|
||||
"pending": "En Attente",
|
||||
"rejected": "Rejetés"
|
||||
},
|
||||
"loadError": "Erreur chargement stats"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analytique",
|
||||
"overview": "Aperçu",
|
||||
"totalPv": "Total PV",
|
||||
"todayPv": "PV Aujourd'hui",
|
||||
"weekPv": "PV Semaine",
|
||||
"monthPv": "PV Mois",
|
||||
"totalPages": "Pages Visitées",
|
||||
"trend": "Tendance Trafic",
|
||||
"pageDetail": "Détails Page",
|
||||
"likeRank": "Top Likes",
|
||||
"last7Days": "7 Derniers Jours",
|
||||
"last30Days": "30 Derniers Jours",
|
||||
"sort": {
|
||||
"pv": "Trier par PV",
|
||||
"latest": "Dernière Visite"
|
||||
},
|
||||
"table": {
|
||||
"title": "Titre Page",
|
||||
"pv": "PV",
|
||||
"time": "Dernière Visite",
|
||||
"url": "URL",
|
||||
"rank": "Rang",
|
||||
"like": "J'aime"
|
||||
},
|
||||
"noData": "Aucune Donnée",
|
||||
"noLikeData": "Aucune Donnée de Like",
|
||||
"loadError": "Erreur chargement analytique"
|
||||
},
|
||||
"data": {
|
||||
"title": "Gestion des Données",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Données Commentaires",
|
||||
"desc": "Gérer et importer des commentaires.",
|
||||
"exportLabel": "Exporter :",
|
||||
"exporting": "Export en cours...",
|
||||
"exportJson": "Exporter JSON",
|
||||
"importLabel": "Importer :",
|
||||
"importButton": "Importer Commentaires",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Config Système",
|
||||
"desc": "Paramètres, e-mail, liste noire, etc.",
|
||||
"export": "Exporter Config",
|
||||
"import": "Importer Config"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Données Analytiques",
|
||||
"desc": "Vues, likes et tendances.",
|
||||
"export": "Exporter Stats",
|
||||
"import": "Importer Stats"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Sauvegarde Complète",
|
||||
"desc": "Sauvegarder ou restaurer tout (Commentaires + Config + Stats).",
|
||||
"export": "Export Complet",
|
||||
"import": "Restauration Complète"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Journal d'Opérations"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Préfixe URL Manquant",
|
||||
"descPart1": "Détecté ",
|
||||
"descPart2": " commentaires sans préfixe (http/https).",
|
||||
"descPart3": "Ajouter lors de l'import ?",
|
||||
"label": "Préfixe Domaine (ex: https://example.me)",
|
||||
"placeholder": "Entrer le préfixe",
|
||||
"skip": "Ignorer",
|
||||
"confirm": "Ajouter & Importer"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Export Réussi",
|
||||
"exportFailed": "Échec Export",
|
||||
"fileReadFailed": "Échec Lecture Fichier",
|
||||
"jsonParseFailed": "Échec Analyse JSON",
|
||||
"importConfigSuccess": "Config Importée",
|
||||
"importStatsSuccess": "Stats Importées",
|
||||
"importBackupSuccess": "Restauration Complète Réussie",
|
||||
"importCommentsSuccess": "Commentaires Importés",
|
||||
"prefixRequired": "Veuillez entrer le préfixe",
|
||||
"importStart": "Import : {name} (Mode : {mode})",
|
||||
"fileParseSuccess": "Fichier analysé, traitement...",
|
||||
"errorWithMessage": "Erreur : {msg}",
|
||||
"parsedCommentsCount": "{count} commentaires analysés",
|
||||
"detectMissingPrefix": "{count} URL sans préfixe, en attente...",
|
||||
"prefixAdded": "Préfixe ajouté, continuation...",
|
||||
"skipPrefix": "Ajout préfixe ignoré",
|
||||
"readFileFailedLog": "Échec lecture fichier",
|
||||
"importCommentsDone": "Import Terminé : {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Gestion Commentaires",
|
||||
"statusFilter": {
|
||||
"all": "Tous",
|
||||
"approved": "Approuvés",
|
||||
"pending": "En Attente",
|
||||
"rejected": "Rejetés"
|
||||
},
|
||||
"refresh": "Actualiser",
|
||||
"table": {
|
||||
"author": "Utilisateur",
|
||||
"content": "Commentaire",
|
||||
"path": "Chemin",
|
||||
"status": "Statut",
|
||||
"actions": "Actions",
|
||||
"admin": "Admin",
|
||||
"time": "Date",
|
||||
"ip": "IP",
|
||||
"email": "E-mail"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Approuver",
|
||||
"pending": "Mettre en Attente",
|
||||
"reject": "Rejeter",
|
||||
"edit": "Éditer",
|
||||
"delete": "Supprimer",
|
||||
"blockIp": "Bloquer IP",
|
||||
"blockEmail": "Bloquer E-mail",
|
||||
"pin": "Épingler"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Préc",
|
||||
"next": "Suiv",
|
||||
"jumpTo": "Aller à",
|
||||
"page": "Page",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "Supprimer le commentaire {id} ?",
|
||||
"confirmBlockIp": "Bloquer l'IP {ip} ?",
|
||||
"confirmBlockEmail": "Bloquer l'e-mail {email} ?",
|
||||
"successBlockIp": "IP Bloquée",
|
||||
"successBlockEmail": "E-mail Bloqué",
|
||||
"empty": "Aucune Donnée",
|
||||
"editModal": {
|
||||
"title": "Éditer Commentaire",
|
||||
"name": "Pseudo",
|
||||
"email": "E-mail",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "URL Article",
|
||||
"content": "Contenu",
|
||||
"status": "Statut",
|
||||
"priority": "Priorité (1=Normal, plus élevé=Haut)",
|
||||
"cancel": "Annuler",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Paramètres",
|
||||
"tabs": {
|
||||
"comment": "Commentaires & Sécurité",
|
||||
"feature": "Fonctionnalités",
|
||||
"emailNotify": "Notifications E-mail",
|
||||
"telegramNotify": "Notifications Telegram",
|
||||
"display": "Affichage"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Affichage Commentaires",
|
||||
"adminEmail": "E-mail Admin",
|
||||
"adminBadge": "Badge Admin (Vide pour icône par défaut)",
|
||||
"adminEnabled": "Afficher Badge Admin",
|
||||
"avatarPrefix": "Préfixe Avatar (Défaut : https://gravatar.com/avatar)",
|
||||
"securityTitle": "Sécurité",
|
||||
"requireReview": "Approbation Requise pour Nouveaux Commentaires",
|
||||
"adminKey": "Clé Admin (Requise pour commentaires via e-mail admin)",
|
||||
"adminKeyPlaceholder": "Entrer clé",
|
||||
"allowedDomains": "Domaines Autorisés (Vide pour tous. Séparer par espace/virgule)",
|
||||
"blockedIps": "IP Bloquées (Séparer par virgule/nouvelle ligne)",
|
||||
"blockedEmails": "E-mails Bloqués (Séparer par virgule/nouvelle ligne)",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Fonctionnalités",
|
||||
"articleLike": "Activer J'aime Article",
|
||||
"articleLikeHint": "Afficher bouton J'aime en haut des commentaires.",
|
||||
"commentLike": "Activer J'aime Commentaire",
|
||||
"commentLikeHint": "Afficher bouton J'aime sur chaque commentaire.",
|
||||
"imageLightbox": "Lightbox Image",
|
||||
"imageLightboxHint": "Aperçu plein écran des images.",
|
||||
"placeholder": "Texte Placeholder",
|
||||
"placeholderHint": "Texte d'invite pour la saisie de commentaire.",
|
||||
"widgetLanguage": "Langue Widget",
|
||||
"widgetLanguageHint": "Langue pour le widget frontend.",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Notification E-mail",
|
||||
"enable": "Activer Notifications E-mail",
|
||||
"smtpTitle": "1. Config SMTP",
|
||||
"provider": "Fournisseur",
|
||||
"host": "Hôte SMTP",
|
||||
"port": "Port SMTP",
|
||||
"secure": "Sécurité SSL",
|
||||
"user": "Utilisateur",
|
||||
"pass": "Mot de passe/Token",
|
||||
"qqHint": "Note : Pour QQ Mail, utilisez un Token d'App.",
|
||||
"163Hint": "Note : Pour 163 Mail, utilisez un Token d'App.",
|
||||
"templateTitle": "2. Config Modèles",
|
||||
"adminTemplate": "Modèle Admin (HTML)",
|
||||
"adminTemplateHint": "Vars : ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Modèle Réponse (HTML)",
|
||||
"replyTemplateHint": "Vars : ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Envoyer Test",
|
||||
"testingBtn": "Envoi...",
|
||||
"resetBtn": "Réinitialiser Modèles",
|
||||
"save": "Sauvegarder Config",
|
||||
"saving": "Sauvegarde..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Notification Telegram",
|
||||
"enable": "Activer Notifications Telegram",
|
||||
"botToken": "Token Bot",
|
||||
"botTokenHint": "Obtenir via @BotFather",
|
||||
"chatId": "ID Chat",
|
||||
"chatIdHint": "ID Utilisateur ou Groupe. Utiliser @userinfobot.",
|
||||
"webhookBtn": "Définir Webhook",
|
||||
"webhookSetting": "Configuration...",
|
||||
"testBtn": "Envoyer Message Test",
|
||||
"testingBtn": "Envoi...",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Paramètres Affichage",
|
||||
"layoutTitle": "Titre Admin",
|
||||
"layoutTitleHint": "Affiché dans la barre de navigation.",
|
||||
"adminLanguage": "Langue Admin",
|
||||
"adminLanguageHint": "Langue du panneau d'administration.",
|
||||
"save": "Sauvegarder",
|
||||
"saving": "Sauvegarde..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Sauvegarde Réussie",
|
||||
"saveFailed": "Échec Sauvegarde",
|
||||
"loading": "Chargement..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/hi.json
Normal file
304
cwd-admin/src/locales/hi.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "टिप्पणी प्रबंधन",
|
||||
"stats": "डेटा डैशबोर्ड",
|
||||
"analytics": "विज़िट विश्लेषण",
|
||||
"settings": "साइट सेटिंग्स",
|
||||
"data": "डेटा प्रबंधन"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "मेनू टॉगल करें",
|
||||
"docs": "दस्तावेज़ीकरण",
|
||||
"logout": "लॉग आउट",
|
||||
"moreActions": "अधिक क्रियाएं",
|
||||
"defaultSite": "डिफ़ॉल्ट साइट",
|
||||
"theme": {
|
||||
"light": "लाइट",
|
||||
"dark": "डार्क",
|
||||
"system": "सिस्टम"
|
||||
},
|
||||
"version": {
|
||||
"title": "संस्करण जानकारी",
|
||||
"apiAddress": "API पता",
|
||||
"apiVersion": "इंटरफ़ेस संस्करण",
|
||||
"adminVersion": "बैकएंड संस्करण",
|
||||
"match": "वर्तमान बैकएंड संस्करण इंटरफ़ेस संस्करण से मेल खाता है, आप इसे सामान्य रूप से उपयोग कर सकते हैं।",
|
||||
"mismatch": "वर्तमान बैकएंड संस्करण इंटरफ़ेस संस्करण से मेल नहीं खाता है। संगतता समस्याओं से बचने के लिए API सेवा को अपडेट करने की अनुशंसा की जाती है।",
|
||||
"fetchError": "इंटरफ़ेस संस्करण प्राप्त करने में विफल:",
|
||||
"loading": "लोड हो रहा है...",
|
||||
"notConfigured": "कॉन्फ़िगर नहीं किया गया",
|
||||
"notFetched": "प्राप्त नहीं किया गया",
|
||||
"ok": "समझ गया"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "डेटा डैशबोर्ड",
|
||||
"overview": "अवलोकन",
|
||||
"total": "कुल टिप्पणियाँ",
|
||||
"approved": "स्वीकृत",
|
||||
"pending": "लंबित",
|
||||
"rejected": "अस्वीकृत",
|
||||
"trend": "टिप्पणी रुझान",
|
||||
"bySite": "साइट द्वारा आँकड़े",
|
||||
"last7Days": "पिछले 7 दिन",
|
||||
"last30Days": "पिछले 30 दिन",
|
||||
"noData": "कोई टिप्पणी डेटा नहीं",
|
||||
"table": {
|
||||
"domain": "डोमेन",
|
||||
"total": "कुल",
|
||||
"approved": "स्वीकृत",
|
||||
"pending": "लंबित",
|
||||
"rejected": "अस्वीकृत"
|
||||
},
|
||||
"loadError": "आँकड़े लोड करने में विफल"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "विज़िट विश्लेषण",
|
||||
"overview": "अवलोकन",
|
||||
"totalPv": "कुल विज़िट",
|
||||
"todayPv": "आज की विज़िट",
|
||||
"weekPv": "इस सप्ताह की विज़िट",
|
||||
"monthPv": "इस महीने की विज़िट",
|
||||
"totalPages": "विज़िट किए गए पेज",
|
||||
"trend": "विज़िट रुझान",
|
||||
"pageDetail": "पेज विवरण",
|
||||
"likeRank": "लाइक रैंकिंग",
|
||||
"last7Days": "पिछले 7 दिन",
|
||||
"last30Days": "पिछले 30 दिन",
|
||||
"sort": {
|
||||
"pv": "PV द्वारा क्रमबद्ध करें",
|
||||
"latest": "नवीनतम विज़िट"
|
||||
},
|
||||
"table": {
|
||||
"title": "पेज शीर्षक",
|
||||
"pv": "विज़िट",
|
||||
"time": "अंतिम विज़िट",
|
||||
"url": "पेज URL",
|
||||
"rank": "रैंक",
|
||||
"like": "लाइक"
|
||||
},
|
||||
"noData": "कोई विज़िट डेटा नहीं",
|
||||
"noLikeData": "कोई लाइक डेटा नहीं",
|
||||
"loadError": "विज़िट आँकड़े लोड करने में विफल"
|
||||
},
|
||||
"data": {
|
||||
"title": "डेटा प्रबंधन",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "टिप्पणी डेटा",
|
||||
"desc": "टिप्पणी सामग्री प्रबंधित करें, अन्य टिप्पणी प्रणालियों से माइग्रेशन का समर्थन करें।",
|
||||
"exportLabel": "निर्यात:",
|
||||
"exporting": "निर्यात हो रहा है...",
|
||||
"exportJson": "JSON निर्यात करें",
|
||||
"importLabel": "आयात:",
|
||||
"importButton": "टिप्पणियाँ आयात करें",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "सिस्टम कॉन्फ़िगरेशन",
|
||||
"desc": "बैकएंड सेटिंग्स, ईमेल कॉन्फ़िगरेशन, ब्लैकलिस्ट आदि प्रबंधित करें।",
|
||||
"export": "कॉन्फ़िगरेशन निर्यात करें",
|
||||
"import": "कॉन्फ़िगरेशन आयात करें"
|
||||
},
|
||||
"stats": {
|
||||
"title": "विज़िट आँकड़े",
|
||||
"desc": "लेख विज़िट, लाइक और दैनिक रुझान प्रबंधित करें।",
|
||||
"export": "आँकड़े निर्यात करें",
|
||||
"import": "आँकड़े आयात करें"
|
||||
},
|
||||
"backup": {
|
||||
"title": "पूर्ण बैकअप",
|
||||
"desc": "सभी सिस्टम डेटा (टिप्पणियाँ + कॉन्फ़िगरेशन + आँकड़े) का बैकअप लें या पुनर्स्थापित करें।",
|
||||
"export": "पूर्ण निर्यात",
|
||||
"import": "पूर्ण पुनर्स्थापना"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "ऑपरेशन लॉग"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "URL उपसर्ग गायब है",
|
||||
"descPart1": "पता चला ",
|
||||
"descPart2": " डोमेन उपसर्ग (http/https) के बिना टिप्पणियाँ।",
|
||||
"descPart3": "क्या आप आयात करते समय इसे जोड़ना चाहते हैं?",
|
||||
"label": "डोमेन उपसर्ग (उदाहरण: https://example.me)",
|
||||
"placeholder": "डोमेन उपसर्ग दर्ज करें",
|
||||
"skip": "सीधे आयात करें (बिना जोड़े)",
|
||||
"confirm": "जोड़ें और आयात करें"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "निर्यात सफल",
|
||||
"exportFailed": "निर्यात विफल",
|
||||
"fileReadFailed": "फ़ाइल पढ़ने में विफल",
|
||||
"jsonParseFailed": "JSON पार्सिंग विफल, कृपया फ़ाइल प्रारूप की जाँच करें",
|
||||
"importConfigSuccess": "कॉन्फ़िगरेशन आयात सफल",
|
||||
"importStatsSuccess": "आँकड़े आयात सफल",
|
||||
"importBackupSuccess": "पूर्ण पुनर्स्थापना सफल",
|
||||
"importCommentsSuccess": "टिप्पणी आयात सफल",
|
||||
"prefixRequired": "कृपया डोमेन उपसर्ग दर्ज करें",
|
||||
"importStart": "आयात शुरू: {name} (मोड: {mode})",
|
||||
"fileParseSuccess": "फ़ाइल पार्स सफल, प्रसंस्करण...",
|
||||
"errorWithMessage": "त्रुटि: {msg}",
|
||||
"parsedCommentsCount": "{count} टिप्पणी डेटा पार्स किया गया",
|
||||
"detectMissingPrefix": "{count} URL बिना उपसर्ग के पाए गए, उपयोगकर्ता की पुष्टि की प्रतीक्षा में...",
|
||||
"prefixAdded": "उपसर्ग जोड़ा गया, आयात जारी...",
|
||||
"skipPrefix": "उपयोगकर्ता ने उपसर्ग जोड़ना छोड़ दिया",
|
||||
"readFileFailedLog": "फ़ाइल पढ़ने में विफल",
|
||||
"importCommentsDone": "आयात पूर्ण: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "टिप्पणी प्रबंधन",
|
||||
"statusFilter": {
|
||||
"all": "सभी स्थितियाँ",
|
||||
"approved": "स्वीकृत",
|
||||
"pending": "लंबित",
|
||||
"rejected": "अस्वीकृत"
|
||||
},
|
||||
"refresh": "ताज़ा करें",
|
||||
"table": {
|
||||
"author": "उपयोगकर्ता",
|
||||
"content": "सामग्री",
|
||||
"path": "पथ",
|
||||
"status": "स्थिति",
|
||||
"actions": "क्रियाएं",
|
||||
"admin": "व्यवस्थापक",
|
||||
"time": "समय",
|
||||
"ip": "IP",
|
||||
"email": "ईमेल"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "स्वीकृत करें",
|
||||
"pending": "लंबित",
|
||||
"reject": "अस्वीकार करें",
|
||||
"edit": "संपादित करें",
|
||||
"delete": "हटाएं",
|
||||
"blockIp": "IP ब्लॉक करें",
|
||||
"blockEmail": "ईमेल ब्लॉक करें",
|
||||
"pin": "पिन करें"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "पिछला",
|
||||
"next": "अगला",
|
||||
"jumpTo": "पर जाएं",
|
||||
"page": "पेज",
|
||||
"confirm": "पुष्टि करें"
|
||||
},
|
||||
"confirmDelete": "क्या आप वाकई टिप्पणी {id} हटाना चाहते हैं?",
|
||||
"confirmBlockIp": "क्या आप वाकई IP {ip} को ब्लैकलिस्ट करना चाहते हैं?",
|
||||
"confirmBlockEmail": "क्या आप वाकई ईमेल {email} को ब्लैकलिस्ट करना चाहते हैं?",
|
||||
"successBlockIp": "IP को ब्लैकलिस्ट में जोड़ा गया",
|
||||
"successBlockEmail": "ईमेल को ब्लैकलिस्ट में जोड़ा गया",
|
||||
"empty": "कोई डेटा नहीं",
|
||||
"editModal": {
|
||||
"title": "टिप्पणी संपादित करें",
|
||||
"name": "आगंतुक का नाम",
|
||||
"email": "आगंतुक का ईमेल",
|
||||
"url": "आगंतुक का URL",
|
||||
"postSlug": "पेज ID",
|
||||
"postUrl": "टिप्पणी URL",
|
||||
"content": "सामग्री",
|
||||
"status": "स्थिति",
|
||||
"priority": "प्राथमिकता (1 डिफ़ॉल्ट है, उच्चतर पहले)",
|
||||
"cancel": "रद्द करें",
|
||||
"save": "सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "साइट सेटिंग्स",
|
||||
"tabs": {
|
||||
"comment": "टिप्पणियाँ और सुरक्षा",
|
||||
"feature": "सुविधाएँ",
|
||||
"emailNotify": "ईमेल सूचनाएँ",
|
||||
"telegramNotify": "Telegram सूचनाएँ",
|
||||
"display": "प्रदर्शन"
|
||||
},
|
||||
"comment": {
|
||||
"title": "टिप्पणी प्रदर्शन कॉन्फ़िगरेशन",
|
||||
"adminEmail": "व्यवस्थापक ईमेल",
|
||||
"adminBadge": "व्यवस्थापक बैज टेक्स्ट (डिफ़ॉल्ट आइकन के लिए खाली छोड़ें)",
|
||||
"adminEnabled": "व्यवस्थापक बैज प्रदर्शन सक्षम करें",
|
||||
"avatarPrefix": "अवतार उपसर्ग (डिफ़ॉल्ट: https://gravatar.com/avatar)",
|
||||
"securityTitle": "सुरक्षा सेटिंग्स",
|
||||
"requireReview": "नई टिप्पणियों को प्रदर्शन से पहले समीक्षा की आवश्यकता है",
|
||||
"adminKey": "व्यवस्थापक टिप्पणी कुंजी (व्यवस्थापक ईमेल का उपयोग करते समय आवश्यक)",
|
||||
"adminKeyPlaceholder": "सेट या संशोधित करने के लिए कुंजी दर्ज करें",
|
||||
"allowedDomains": "अनुमत डोमेन (सभी के लिए खाली छोड़ें, अल्पविराम या स्थान से अलग करें)",
|
||||
"blockedIps": "IP ब्लैकलिस्ट (अल्पविराम या नई लाइन से अलग करें)",
|
||||
"blockedEmails": "ईमेल ब्लैकलिस्ट (अल्पविराम या नई लाइन से अलग करें)",
|
||||
"save": "सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "सुविधाएँ",
|
||||
"articleLike": "लेख लाइक सक्षम करें",
|
||||
"articleLikeHint": "सक्षम होने पर, टिप्पणी अनुभाग के ऊपर एक लेख लाइक बटन प्रदर्शित होगा।",
|
||||
"commentLike": "टिप्पणी लाइक सक्षम करें",
|
||||
"commentLikeHint": "सक्षम होने पर, प्रत्येक टिप्पणी के साथ एक लाइक बटन प्रदर्शित होगा।",
|
||||
"imageLightbox": "छवि लाइटबॉक्स",
|
||||
"imageLightboxHint": "सक्षम होने पर, टिप्पणियों में छवियों पर क्लिक करने से वे पूर्ण स्क्रीन में दिखाई देंगी।",
|
||||
"placeholder": "टिप्पणी बॉक्स प्लेसहोल्डर टेक्स्ट",
|
||||
"placeholderHint": "इनपुट बॉक्स के लिए कस्टम टेक्स्ट। डिफ़ॉल्ट के लिए खाली छोड़ें।",
|
||||
"widgetLanguage": "विजेट भाषा",
|
||||
"widgetLanguageHint": "फ्रंटएंड टिप्पणी विजेट की भाषा सेट करें।",
|
||||
"save": "सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "ईमेल सेटिंग्स",
|
||||
"enable": "ईमेल सूचनाएँ सक्षम करें",
|
||||
"smtpTitle": "1. SMTP कॉन्फ़िगरेशन",
|
||||
"provider": "प्रदाता",
|
||||
"host": "SMTP होस्ट",
|
||||
"port": "SMTP पोर्ट",
|
||||
"secure": "SSL कनेक्शन",
|
||||
"user": "ईमेल खाता",
|
||||
"pass": "पासवर्ड/ऐप पासवर्ड",
|
||||
"qqHint": "नोट: QQ मेल के लिए, पासवर्ड के बजाय प्राधिकरण कोड का उपयोग करें।",
|
||||
"163Hint": "नोट: 163 मेल के लिए, पासवर्ड के बजाय प्राधिकरण कोड का उपयोग करें।",
|
||||
"templateTitle": "2. ईमेल टेम्प्लेट",
|
||||
"adminTemplate": "व्यवस्थापक अधिसूचना (HTML)",
|
||||
"adminTemplateHint": "चर: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "उत्तर अधिसूचना (HTML)",
|
||||
"replyTemplateHint": "चर: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "परीक्षण ईमेल भेजें",
|
||||
"testingBtn": "भेजा जा रहा है...",
|
||||
"resetBtn": "टेम्प्लेट रीसेट करें",
|
||||
"save": "कॉन्फ़िगरेशन सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram सेटिंग्स",
|
||||
"enable": "Telegram सूचनाएँ सक्षम करें",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "Bot बनाने और Token प्राप्त करने के लिए Telegram में @BotFather खोजें",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "उपयोगकर्ता या समूह ID। बॉट को संदेश भेजें और इसे खोजने के लिए API या @userinfobot का उपयोग करें।",
|
||||
"webhookBtn": "Webhook सेट करें",
|
||||
"webhookSetting": "सेट हो रहा है...",
|
||||
"testBtn": "परीक्षण संदेश भेजें",
|
||||
"testingBtn": "भेजा जा रहा है...",
|
||||
"save": "सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
},
|
||||
"display": {
|
||||
"title": "प्रदर्शन सेटिंग्स",
|
||||
"layoutTitle": "व्यवस्थापक पैनल शीर्षक",
|
||||
"layoutTitleHint": "शीर्ष नेविगेशन बार में प्रदर्शित होता है।",
|
||||
"adminLanguage": "व्यवस्थापक पैनल भाषा",
|
||||
"adminLanguageHint": "व्यवस्थापक सिस्टम की भाषा सेट करें।",
|
||||
"save": "सहेजें",
|
||||
"saving": "सहेजा जा रहा है..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "सफलतापूर्वक सहेजा गया",
|
||||
"saveFailed": "सहेजने में विफल",
|
||||
"loading": "लोड हो रहा है..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/id.json
Normal file
304
cwd-admin/src/locales/id.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Manajemen Komentar",
|
||||
"stats": "Dasbor",
|
||||
"analytics": "Analitik Kunjungan",
|
||||
"settings": "Pengaturan Situs",
|
||||
"data": "Manajemen Data"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Alihkan Menu",
|
||||
"docs": "Dokumentasi",
|
||||
"logout": "Keluar",
|
||||
"moreActions": "Tindakan Lainnya",
|
||||
"defaultSite": "Situs Default",
|
||||
"theme": {
|
||||
"light": "Terang",
|
||||
"dark": "Gelap",
|
||||
"system": "Sistem"
|
||||
},
|
||||
"version": {
|
||||
"title": "Informasi Versi",
|
||||
"apiAddress": "Alamat API",
|
||||
"apiVersion": "Versi API",
|
||||
"adminVersion": "Versi Admin",
|
||||
"match": "Versi admin saat ini cocok dengan versi API, Anda dapat menggunakannya dengan normal.",
|
||||
"mismatch": "Versi admin saat ini tidak cocok dengan versi API. Disarankan untuk memperbarui layanan API untuk menghindari masalah kompatibilitas.",
|
||||
"fetchError": "Gagal mengambil versi API:",
|
||||
"loading": "Memuat...",
|
||||
"notConfigured": "Belum Dikonfigurasi",
|
||||
"notFetched": "Tidak Diambil",
|
||||
"ok": "Mengerti"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dasbor",
|
||||
"overview": "Ikhtisar",
|
||||
"total": "Total Komentar",
|
||||
"approved": "Disetujui",
|
||||
"pending": "Tertunda",
|
||||
"rejected": "Ditolak",
|
||||
"trend": "Tren Komentar",
|
||||
"bySite": "Statistik per Situs",
|
||||
"last7Days": "7 Hari Terakhir",
|
||||
"last30Days": "30 Hari Terakhir",
|
||||
"noData": "Tidak ada data komentar",
|
||||
"table": {
|
||||
"domain": "Domain",
|
||||
"total": "Total",
|
||||
"approved": "Disetujui",
|
||||
"pending": "Tertunda",
|
||||
"rejected": "Ditolak"
|
||||
},
|
||||
"loadError": "Gagal memuat statistik"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analitik Kunjungan",
|
||||
"overview": "Ikhtisar",
|
||||
"totalPv": "Total Kunjungan",
|
||||
"todayPv": "Kunjungan Hari Ini",
|
||||
"weekPv": "Kunjungan Minggu Ini",
|
||||
"monthPv": "Kunjungan Bulan Ini",
|
||||
"totalPages": "Halaman Dikunjungi",
|
||||
"trend": "Tren Kunjungan",
|
||||
"pageDetail": "Detail Halaman",
|
||||
"likeRank": "Peringkat Suka",
|
||||
"last7Days": "7 Hari Terakhir",
|
||||
"last30Days": "30 Hari Terakhir",
|
||||
"sort": {
|
||||
"pv": "Urutkan berdasarkan PV",
|
||||
"latest": "Kunjungan Terbaru"
|
||||
},
|
||||
"table": {
|
||||
"title": "Judul Halaman",
|
||||
"pv": "Kunjungan",
|
||||
"time": "Kunjungan Terakhir",
|
||||
"url": "URL Halaman",
|
||||
"rank": "Peringkat",
|
||||
"like": "Suka"
|
||||
},
|
||||
"noData": "Tidak ada data kunjungan",
|
||||
"noLikeData": "Tidak ada data suka",
|
||||
"loadError": "Gagal memuat analitik kunjungan"
|
||||
},
|
||||
"data": {
|
||||
"title": "Manajemen Data",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Data Komentar",
|
||||
"desc": "Kelola konten komentar, dukung migrasi dari sistem komentar lain.",
|
||||
"exportLabel": "Ekspor:",
|
||||
"exporting": "Mengekspor...",
|
||||
"exportJson": "Ekspor JSON",
|
||||
"importLabel": "Impor:",
|
||||
"importButton": "Impor Komentar",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Konfigurasi Sistem",
|
||||
"desc": "Kelola pengaturan admin, konfigurasi email, daftar hitam, dll.",
|
||||
"export": "Ekspor Konfigurasi",
|
||||
"import": "Impor Konfigurasi"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Statistik Kunjungan",
|
||||
"desc": "Kelola kunjungan artikel, suka, dan tren kunjungan harian.",
|
||||
"export": "Ekspor Statistik",
|
||||
"import": "Impor Statistik"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Cadangan Lengkap",
|
||||
"desc": "Cadangkan atau pulihkan semua data sistem (Komentar + Konfigurasi + Statistik).",
|
||||
"export": "Ekspor Lengkap",
|
||||
"import": "Pulihkan Lengkap"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Log Operasi"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Awalan URL Hilang",
|
||||
"descPart1": "Terdeteksi ",
|
||||
"descPart2": " komentar tanpa awalan domain (http/https).",
|
||||
"descPart3": "Apakah Anda ingin menambahkannya saat mengimpor?",
|
||||
"label": "Awalan Domain (contoh: https://example.me)",
|
||||
"placeholder": "Masukkan awalan domain",
|
||||
"skip": "Impor Langsung (Tanpa Menambahkan)",
|
||||
"confirm": "Tambahkan dan Impor"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Ekspor Berhasil",
|
||||
"exportFailed": "Ekspor Gagal",
|
||||
"fileReadFailed": "Gagal Membaca File",
|
||||
"jsonParseFailed": "Gagal Mengurai JSON, silakan periksa format file",
|
||||
"importConfigSuccess": "Impor Konfigurasi Berhasil",
|
||||
"importStatsSuccess": "Impor Statistik Berhasil",
|
||||
"importBackupSuccess": "Pemulihan Lengkap Berhasil",
|
||||
"importCommentsSuccess": "Impor Komentar Berhasil",
|
||||
"prefixRequired": "Silakan masukkan awalan domain",
|
||||
"importStart": "Mulai Impor: {name} (Mode: {mode})",
|
||||
"fileParseSuccess": "File berhasil diurai, memproses...",
|
||||
"errorWithMessage": "Kesalahan: {msg}",
|
||||
"parsedCommentsCount": "Mengurai {count} data komentar",
|
||||
"detectMissingPrefix": "Terdeteksi {count} URL tanpa awalan, menunggu konfirmasi pengguna...",
|
||||
"prefixAdded": "Awalan ditambahkan, melanjutkan impor...",
|
||||
"skipPrefix": "Pengguna melewati penambahan awalan",
|
||||
"readFileFailedLog": "Gagal membaca file",
|
||||
"importCommentsDone": "Impor Selesai: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Manajemen Komentar",
|
||||
"statusFilter": {
|
||||
"all": "Semua Status",
|
||||
"approved": "Disetujui",
|
||||
"pending": "Tertunda",
|
||||
"rejected": "Ditolak"
|
||||
},
|
||||
"refresh": "Segarkan",
|
||||
"table": {
|
||||
"author": "Pengguna",
|
||||
"content": "Konten",
|
||||
"path": "Jalur",
|
||||
"status": "Status",
|
||||
"actions": "Tindakan",
|
||||
"admin": "Admin",
|
||||
"time": "Waktu",
|
||||
"ip": "IP",
|
||||
"email": "Email"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Setujui",
|
||||
"pending": "Tunda",
|
||||
"reject": "Tolak",
|
||||
"edit": "Edit",
|
||||
"delete": "Hapus",
|
||||
"blockIp": "Blokir IP",
|
||||
"blockEmail": "Blokir Email",
|
||||
"pin": "Sematkan"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Sebelumnya",
|
||||
"next": "Berikutnya",
|
||||
"jumpTo": "Lompat ke",
|
||||
"page": "Halaman",
|
||||
"confirm": "Konfirmasi"
|
||||
},
|
||||
"confirmDelete": "Apakah Anda yakin ingin menghapus komentar {id}?",
|
||||
"confirmBlockIp": "Apakah Anda yakin ingin memblokir IP {ip}?",
|
||||
"confirmBlockEmail": "Apakah Anda yakin ingin memblokir email {email}?",
|
||||
"successBlockIp": "IP telah ditambahkan ke daftar hitam",
|
||||
"successBlockEmail": "Email telah ditambahkan ke daftar hitam",
|
||||
"empty": "Tidak ada data",
|
||||
"editModal": {
|
||||
"title": "Edit Komentar",
|
||||
"name": "Nama Pengunjung",
|
||||
"email": "Email Pengunjung",
|
||||
"url": "URL Pengunjung",
|
||||
"postSlug": "ID Halaman",
|
||||
"postUrl": "URL Komentar",
|
||||
"content": "Konten",
|
||||
"status": "Status",
|
||||
"priority": "Prioritas (1 default, lebih tinggi lebih dulu)",
|
||||
"cancel": "Batal",
|
||||
"save": "Simpan",
|
||||
"saving": "Menyimpan..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Pengaturan Situs",
|
||||
"tabs": {
|
||||
"comment": "Komentar & Keamanan",
|
||||
"feature": "Fitur",
|
||||
"emailNotify": "Notifikasi Email",
|
||||
"telegramNotify": "Notifikasi Telegram",
|
||||
"display": "Tampilan"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Konfigurasi Tampilan Komentar",
|
||||
"adminEmail": "Email Admin",
|
||||
"adminBadge": "Teks Lencana Admin (kosongkan untuk ikon default)",
|
||||
"adminEnabled": "Tampilkan Lencana Admin",
|
||||
"avatarPrefix": "Awalan Avatar (Default: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Pengaturan Keamanan",
|
||||
"requireReview": "Komentar baru memerlukan persetujuan",
|
||||
"adminKey": "Kunci Komentar Admin (diperlukan saat menggunakan email admin)",
|
||||
"adminKeyPlaceholder": "Masukkan kunci untuk mengatur atau mengubah",
|
||||
"allowedDomains": "Domain yang Diizinkan (kosongkan untuk semua, pisahkan dengan koma atau spasi)",
|
||||
"blockedIps": "Daftar Hitam IP (pisahkan dengan koma atau baris baru)",
|
||||
"blockedEmails": "Daftar Hitam Email (pisahkan dengan koma atau baris baru)",
|
||||
"save": "Simpan",
|
||||
"saving": "Menyimpan..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Fitur",
|
||||
"articleLike": "Aktifkan Suka Artikel",
|
||||
"articleLikeHint": "Menampilkan tombol suka artikel di atas bagian komentar.",
|
||||
"commentLike": "Aktifkan Suka Komentar",
|
||||
"commentLikeHint": "Menampilkan tombol suka pada setiap komentar.",
|
||||
"imageLightbox": "Lightbox Gambar",
|
||||
"imageLightboxHint": "Klik gambar dalam komentar untuk melihat layar penuh.",
|
||||
"placeholder": "Teks Placeholder Komentar",
|
||||
"placeholderHint": "Teks kustom untuk kotak input. Kosongkan untuk default.",
|
||||
"widgetLanguage": "Bahasa Widget",
|
||||
"widgetLanguageHint": "Atur bahasa widget komentar frontend.",
|
||||
"save": "Simpan",
|
||||
"saving": "Menyimpan..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Pengaturan Email",
|
||||
"enable": "Aktifkan Notifikasi Email",
|
||||
"smtpTitle": "1. Konfigurasi SMTP",
|
||||
"provider": "Penyedia",
|
||||
"host": "Host SMTP",
|
||||
"port": "Port SMTP",
|
||||
"secure": "Koneksi SSL",
|
||||
"user": "Akun Email",
|
||||
"pass": "Kata Sandi/Kata Sandi Aplikasi",
|
||||
"qqHint": "Catatan: Untuk QQ Mail, gunakan kode otorisasi, bukan kata sandi.",
|
||||
"163Hint": "Catatan: Untuk 163 Mail, gunakan kode otorisasi, bukan kata sandi.",
|
||||
"templateTitle": "2. Template Email",
|
||||
"adminTemplate": "Notifikasi Admin (HTML)",
|
||||
"adminTemplateHint": "Variabel: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Notifikasi Balasan (HTML)",
|
||||
"replyTemplateHint": "Variabel: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Kirim Email Uji",
|
||||
"testingBtn": "Mengirim...",
|
||||
"resetBtn": "Atur Ulang Template",
|
||||
"save": "Simpan Konfigurasi",
|
||||
"saving": "Menyimpan..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Pengaturan Telegram",
|
||||
"enable": "Aktifkan Notifikasi Telegram",
|
||||
"botToken": "Token Bot",
|
||||
"botTokenHint": "Cari @BotFather di Telegram untuk membuat bot dan mendapatkan token",
|
||||
"chatId": "ID Obrolan",
|
||||
"chatIdHint": "ID Pengguna atau Grup. Kirim pesan ke bot dan gunakan API atau @userinfobot untuk menemukannya.",
|
||||
"webhookBtn": "Atur Webhook",
|
||||
"webhookSetting": "Mengatur...",
|
||||
"testBtn": "Kirim Pesan Uji",
|
||||
"testingBtn": "Mengirim...",
|
||||
"save": "Simpan",
|
||||
"saving": "Menyimpan..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Pengaturan Tampilan",
|
||||
"layoutTitle": "Judul Panel Admin",
|
||||
"layoutTitleHint": "Ditampilkan di bilah navigasi atas.",
|
||||
"adminLanguage": "Bahasa Panel Admin",
|
||||
"adminLanguageHint": "Atur bahasa sistem admin.",
|
||||
"save": "Simpan",
|
||||
"saving": "Menyimpan..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Berhasil Disimpan",
|
||||
"saveFailed": "Gagal Disimpan",
|
||||
"loading": "Memuat..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/it.json
Normal file
304
cwd-admin/src/locales/it.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Gestione Commenti",
|
||||
"stats": "Dashboard",
|
||||
"analytics": "Analitica",
|
||||
"settings": "Impostazioni",
|
||||
"data": "Dati"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Attiva/Disattiva Menu",
|
||||
"docs": "Documentazione",
|
||||
"logout": "Esci",
|
||||
"moreActions": "Altre Azioni",
|
||||
"defaultSite": "Sito Predefinito",
|
||||
"theme": {
|
||||
"light": "Chiaro",
|
||||
"dark": "Scuro",
|
||||
"system": "Sistema"
|
||||
},
|
||||
"version": {
|
||||
"title": "Info Versione",
|
||||
"apiAddress": "Indirizzo API",
|
||||
"apiVersion": "Versione API",
|
||||
"adminVersion": "Versione Admin",
|
||||
"match": "Le versioni Admin e API corrispondono.",
|
||||
"mismatch": "Versione non corrispondente. Aggiorna il servizio API.",
|
||||
"fetchError": "Errore recupero versione:",
|
||||
"loading": "Caricamento...",
|
||||
"notConfigured": "Non Configurato",
|
||||
"notFetched": "Non Recuperato",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dashboard",
|
||||
"overview": "Panoramica",
|
||||
"total": "Totale Commenti",
|
||||
"approved": "Approvati",
|
||||
"pending": "In Attesa",
|
||||
"rejected": "Rifiutati",
|
||||
"trend": "Tendenza",
|
||||
"bySite": "Per Sito",
|
||||
"last7Days": "Ultimi 7 Giorni",
|
||||
"last30Days": "Ultimi 30 Giorni",
|
||||
"noData": "Nessun Dato",
|
||||
"table": {
|
||||
"domain": "Dominio",
|
||||
"total": "Totale",
|
||||
"approved": "Approvati",
|
||||
"pending": "In Attesa",
|
||||
"rejected": "Rifiutati"
|
||||
},
|
||||
"loadError": "Errore caricamento statistiche"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analitica",
|
||||
"overview": "Panoramica",
|
||||
"totalPv": "Totale PV",
|
||||
"todayPv": "PV Oggi",
|
||||
"weekPv": "PV Settimana",
|
||||
"monthPv": "PV Mese",
|
||||
"totalPages": "Pagine Visitate",
|
||||
"trend": "Tendenza Traffico",
|
||||
"pageDetail": "Dettagli Pagina",
|
||||
"likeRank": "Top Mi Piace",
|
||||
"last7Days": "Ultimi 7 Giorni",
|
||||
"last30Days": "Ultimi 30 Giorni",
|
||||
"sort": {
|
||||
"pv": "Ordina per PV",
|
||||
"latest": "Ultima Visita"
|
||||
},
|
||||
"table": {
|
||||
"title": "Titolo Pagina",
|
||||
"pv": "PV",
|
||||
"time": "Ultima Visita",
|
||||
"url": "URL",
|
||||
"rank": "Rango",
|
||||
"like": "Mi Piace"
|
||||
},
|
||||
"noData": "Nessun Dato",
|
||||
"noLikeData": "Nessun Dato Mi Piace",
|
||||
"loadError": "Errore caricamento analitica"
|
||||
},
|
||||
"data": {
|
||||
"title": "Gestione Dati",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Dati Commenti",
|
||||
"desc": "Gestisci e importa commenti.",
|
||||
"exportLabel": "Esporta:",
|
||||
"exporting": "Esportazione...",
|
||||
"exportJson": "Esporta JSON",
|
||||
"importLabel": "Importa:",
|
||||
"importButton": "Importa Commenti",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Config Sistema",
|
||||
"desc": "Impostazioni, email, blacklist, ecc.",
|
||||
"export": "Esporta Config",
|
||||
"import": "Importa Config"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dati Analitici",
|
||||
"desc": "Visualizzazioni, mi piace e tendenze.",
|
||||
"export": "Esporta Stats",
|
||||
"import": "Importa Stats"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Backup Completo",
|
||||
"desc": "Backup o ripristino completo (Commenti + Config + Stats).",
|
||||
"export": "Esportazione Completa",
|
||||
"import": "Ripristino Completo"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Log Operazioni"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Prefisso URL Mancante",
|
||||
"descPart1": "Rilevati ",
|
||||
"descPart2": " commenti senza prefisso protocollo (http/https).",
|
||||
"descPart3": "Aggiungere durante importazione?",
|
||||
"label": "Prefisso Dominio (es. https://example.me)",
|
||||
"placeholder": "Inserisci prefisso",
|
||||
"skip": "Salta",
|
||||
"confirm": "Aggiungi & Importa"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Esportazione Riuscita",
|
||||
"exportFailed": "Esportazione Fallita",
|
||||
"fileReadFailed": "Lettura File Fallita",
|
||||
"jsonParseFailed": "Analisi JSON Fallita",
|
||||
"importConfigSuccess": "Config Importata",
|
||||
"importStatsSuccess": "Stats Importate",
|
||||
"importBackupSuccess": "Ripristino Completo Riuscito",
|
||||
"importCommentsSuccess": "Commenti Importati",
|
||||
"prefixRequired": "Inserisci prefisso",
|
||||
"importStart": "Importazione: {name} (Modo: {mode})",
|
||||
"fileParseSuccess": "File analizzato, elaborazione...",
|
||||
"errorWithMessage": "Errore: {msg}",
|
||||
"parsedCommentsCount": "{count} commenti analizzati",
|
||||
"detectMissingPrefix": "{count} URL senza prefisso, in attesa...",
|
||||
"prefixAdded": "Prefisso aggiunto, continuo...",
|
||||
"skipPrefix": "Aggiunta prefisso saltata",
|
||||
"readFileFailedLog": "Lettura file fallita",
|
||||
"importCommentsDone": "Importazione Completata: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Gestione Commenti",
|
||||
"statusFilter": {
|
||||
"all": "Tutti",
|
||||
"approved": "Approvati",
|
||||
"pending": "In Attesa",
|
||||
"rejected": "Rifiutati"
|
||||
},
|
||||
"refresh": "Aggiorna",
|
||||
"table": {
|
||||
"author": "Utente",
|
||||
"content": "Commento",
|
||||
"path": "Percorso",
|
||||
"status": "Stato",
|
||||
"actions": "Azioni",
|
||||
"admin": "Admin",
|
||||
"time": "Ora",
|
||||
"ip": "IP",
|
||||
"email": "Email"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Approva",
|
||||
"pending": "Sospendi",
|
||||
"reject": "Rifiuta",
|
||||
"edit": "Modifica",
|
||||
"delete": "Elimina",
|
||||
"blockIp": "Blocca IP",
|
||||
"blockEmail": "Blocca Email",
|
||||
"pin": "Fissa"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Prec",
|
||||
"next": "Succ",
|
||||
"jumpTo": "Vai a",
|
||||
"page": "Pagina",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "Eliminare commento {id}?",
|
||||
"confirmBlockIp": "Bloccare IP {ip}?",
|
||||
"confirmBlockEmail": "Bloccare email {email}?",
|
||||
"successBlockIp": "IP Bloccato",
|
||||
"successBlockEmail": "Email Bloccata",
|
||||
"empty": "Nessun Dato",
|
||||
"editModal": {
|
||||
"title": "Modifica Commento",
|
||||
"name": "Nome",
|
||||
"email": "Email",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "URL Post",
|
||||
"content": "Contenuto",
|
||||
"status": "Stato",
|
||||
"priority": "Priorità (1=Normale, maggiore=Alto)",
|
||||
"cancel": "Annulla",
|
||||
"save": "Salva",
|
||||
"saving": "Salvataggio..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Impostazioni",
|
||||
"tabs": {
|
||||
"comment": "Commenti & Sicurezza",
|
||||
"feature": "Funzionalità",
|
||||
"emailNotify": "Notifica Email",
|
||||
"telegramNotify": "Notifica Telegram",
|
||||
"display": "Visualizzazione"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Visualizzazione Commenti",
|
||||
"adminEmail": "Email Admin",
|
||||
"adminBadge": "Testo Badge Admin (Vuoto per icona default)",
|
||||
"adminEnabled": "Mostra Badge Admin",
|
||||
"avatarPrefix": "Prefisso Avatar (Default: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Sicurezza",
|
||||
"requireReview": "Richiedi Revisione per Nuovi Commenti",
|
||||
"adminKey": "Chiave Admin (Richiesta per commenti con email admin)",
|
||||
"adminKeyPlaceholder": "Inserisci chiave",
|
||||
"allowedDomains": "Domini Consentiti (Vuoto per tutti. Separare con spazio/virgola)",
|
||||
"blockedIps": "IP Bloccati (Separare con virgola/nuova riga)",
|
||||
"blockedEmails": "Email Bloccate (Separare con virgola/nuova riga)",
|
||||
"save": "Salva",
|
||||
"saving": "Salvataggio..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Funzionalità",
|
||||
"articleLike": "Abilita Mi Piace Articolo",
|
||||
"articleLikeHint": "Mostra pulsante Mi Piace sopra i commenti.",
|
||||
"commentLike": "Abilita Mi Piace Commento",
|
||||
"commentLikeHint": "Mostra pulsante Mi Piace su ogni commento.",
|
||||
"imageLightbox": "Lightbox Immagine",
|
||||
"imageLightboxHint": "Abilita anteprima a schermo intero per le immagini.",
|
||||
"placeholder": "Testo Placeholder",
|
||||
"placeholderHint": "Placeholder personalizzato per input commenti.",
|
||||
"widgetLanguage": "Lingua Widget",
|
||||
"widgetLanguageHint": "Lingua per il widget frontend.",
|
||||
"save": "Salva",
|
||||
"saving": "Salvataggio..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Notifica Email",
|
||||
"enable": "Abilita Notifica Email",
|
||||
"smtpTitle": "1. Config SMTP",
|
||||
"provider": "Provider",
|
||||
"host": "Host SMTP",
|
||||
"port": "Porta SMTP",
|
||||
"secure": "Sicurezza SSL",
|
||||
"user": "Utente Email",
|
||||
"pass": "Password/Token App",
|
||||
"qqHint": "Nota: Per QQ Mail, usa Token App.",
|
||||
"163Hint": "Nota: Per 163 Mail, usa Token App.",
|
||||
"templateTitle": "2. Config Template",
|
||||
"adminTemplate": "Template Admin (HTML)",
|
||||
"adminTemplateHint": "Vars: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Template Risposta (HTML)",
|
||||
"replyTemplateHint": "Vars: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Invia Email Test",
|
||||
"testingBtn": "Invio...",
|
||||
"resetBtn": "Reimposta Template",
|
||||
"save": "Salva Config",
|
||||
"saving": "Salvataggio..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Notifica Telegram",
|
||||
"enable": "Abilita Notifica Telegram",
|
||||
"botToken": "Token Bot",
|
||||
"botTokenHint": "Ottieni da @BotFather",
|
||||
"chatId": "ID Chat",
|
||||
"chatIdHint": "ID Utente o Gruppo. Usa @userinfobot.",
|
||||
"webhookBtn": "Imposta Webhook",
|
||||
"webhookSetting": "Configurazione...",
|
||||
"testBtn": "Invia Messaggio Test",
|
||||
"testingBtn": "Invio...",
|
||||
"save": "Salva",
|
||||
"saving": "Salvataggio..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Impostazioni Visualizzazione",
|
||||
"layoutTitle": "Titolo Admin",
|
||||
"layoutTitleHint": "Visualizzato nella barra di navigazione superiore.",
|
||||
"adminLanguage": "Lingua Admin",
|
||||
"adminLanguageHint": "Lingua per il pannello di amministrazione.",
|
||||
"save": "Salva",
|
||||
"saving": "Salvataggio..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Salvato con Successo",
|
||||
"saveFailed": "Salvataggio Fallito",
|
||||
"loading": "Caricamento..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/ja.json
Normal file
304
cwd-admin/src/locales/ja.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "コメント管理",
|
||||
"stats": "ダッシュボード",
|
||||
"analytics": "アクセス統計",
|
||||
"settings": "サイト設定",
|
||||
"data": "データ管理"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "メニュー切り替え",
|
||||
"docs": "ドキュメント",
|
||||
"logout": "ログアウト",
|
||||
"moreActions": "その他の操作",
|
||||
"defaultSite": "デフォルトサイト",
|
||||
"theme": {
|
||||
"light": "ライト",
|
||||
"dark": "ダーク",
|
||||
"system": "システム"
|
||||
},
|
||||
"version": {
|
||||
"title": "バージョン情報",
|
||||
"apiAddress": "API アドレス",
|
||||
"apiVersion": "API バージョン",
|
||||
"adminVersion": "管理画面バージョン",
|
||||
"match": "管理画面とAPIのバージョンが一致しています。",
|
||||
"mismatch": "バージョンが一致しません。互換性の問題を避けるため、APIサービスを更新してください。",
|
||||
"fetchError": "バージョン情報の取得に失敗しました:",
|
||||
"loading": "読み込み中...",
|
||||
"notConfigured": "未設定",
|
||||
"notFetched": "未取得",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "ダッシュボード",
|
||||
"overview": "概要",
|
||||
"total": "総コメント数",
|
||||
"approved": "承認済み",
|
||||
"pending": "承認待ち",
|
||||
"rejected": "却下済み",
|
||||
"trend": "コメント傾向",
|
||||
"bySite": "サイト別統計",
|
||||
"last7Days": "過去7日間",
|
||||
"last30Days": "過去30日間",
|
||||
"noData": "データなし",
|
||||
"table": {
|
||||
"domain": "ドメイン",
|
||||
"total": "合計",
|
||||
"approved": "承認済み",
|
||||
"pending": "承認待ち",
|
||||
"rejected": "却下済み"
|
||||
},
|
||||
"loadError": "統計データの読み込みに失敗しました"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "アクセス統計",
|
||||
"overview": "概要",
|
||||
"totalPv": "総PV",
|
||||
"todayPv": "今日のPV",
|
||||
"weekPv": "今週のPV",
|
||||
"monthPv": "今月のPV",
|
||||
"totalPages": "訪問ページ数",
|
||||
"trend": "アクセス傾向",
|
||||
"pageDetail": "ページ詳細",
|
||||
"likeRank": "いいねランキング",
|
||||
"last7Days": "過去7日間",
|
||||
"last30Days": "過去30日間",
|
||||
"sort": {
|
||||
"pv": "PV順",
|
||||
"latest": "最新の訪問"
|
||||
},
|
||||
"table": {
|
||||
"title": "ページタイトル",
|
||||
"pv": "PV",
|
||||
"time": "最終訪問",
|
||||
"url": "URL",
|
||||
"rank": "順位",
|
||||
"like": "いいね"
|
||||
},
|
||||
"noData": "データなし",
|
||||
"noLikeData": "いいねデータなし",
|
||||
"loadError": "統計データの読み込みに失敗しました"
|
||||
},
|
||||
"data": {
|
||||
"title": "データ管理",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "コメントデータ",
|
||||
"desc": "コメントの管理と他のフレームワークからのインポート。",
|
||||
"exportLabel": "エクスポート:",
|
||||
"exporting": "エクスポート中...",
|
||||
"exportJson": "JSONエクスポート",
|
||||
"importLabel": "インポート:",
|
||||
"importButton": "コメントをインポート",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "システム設定",
|
||||
"desc": "管理画面設定、メール設定、ブラックリストなど。",
|
||||
"export": "設定エクスポート",
|
||||
"import": "設定インポート"
|
||||
},
|
||||
"stats": {
|
||||
"title": "アクセス統計",
|
||||
"desc": "PV、いいね、アクセス傾向の管理。",
|
||||
"export": "統計エクスポート",
|
||||
"import": "統計インポート"
|
||||
},
|
||||
"backup": {
|
||||
"title": "完全バックアップ",
|
||||
"desc": "全システムデータのバックアップと復元(コメント+設定+統計)。",
|
||||
"export": "完全エクスポート",
|
||||
"import": "完全復元"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "操作ログ"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "URLプレフィックス欠落を検出",
|
||||
"descPart1": "検出された ",
|
||||
"descPart2": " 件のコメントURLにプロトコルプレフィックス(http/https)がありません。",
|
||||
"descPart3": "インポート時に追加しますか?",
|
||||
"label": "ドメインプレフィックス (例: https://example.me)",
|
||||
"placeholder": "プレフィックスを入力",
|
||||
"skip": "スキップ (追加しない)",
|
||||
"confirm": "追加してインポート"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "エクスポート成功",
|
||||
"exportFailed": "エクスポート失敗",
|
||||
"fileReadFailed": "ファイル読み込み失敗",
|
||||
"jsonParseFailed": "JSON解析失敗",
|
||||
"importConfigSuccess": "設定インポート成功",
|
||||
"importStatsSuccess": "統計インポート成功",
|
||||
"importBackupSuccess": "完全復元成功",
|
||||
"importCommentsSuccess": "コメントインポート成功",
|
||||
"prefixRequired": "ドメインプレフィックスを入力してください",
|
||||
"importStart": "インポート開始: {name} (モード: {mode})",
|
||||
"fileParseSuccess": "ファイル解析成功、処理中...",
|
||||
"errorWithMessage": "エラー: {msg}",
|
||||
"parsedCommentsCount": "{count} 件のコメントを解析しました",
|
||||
"detectMissingPrefix": "{count} 件のURL欠落を検出、確認待ち...",
|
||||
"prefixAdded": "プレフィックス追加済み、続行中...",
|
||||
"skipPrefix": "プレフィックス追加をスキップ",
|
||||
"readFileFailedLog": "ファイル読み込み失敗",
|
||||
"importCommentsDone": "インポート完了: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "コメント管理",
|
||||
"statusFilter": {
|
||||
"all": "すべて",
|
||||
"approved": "承認済み",
|
||||
"pending": "承認待ち",
|
||||
"rejected": "却下済み"
|
||||
},
|
||||
"refresh": "更新",
|
||||
"table": {
|
||||
"author": "ユーザー",
|
||||
"content": "コメント",
|
||||
"path": "パス",
|
||||
"status": "ステータス",
|
||||
"actions": "操作",
|
||||
"admin": "管理者",
|
||||
"time": "時間",
|
||||
"ip": "IP",
|
||||
"email": "メール"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "承認",
|
||||
"pending": "保留",
|
||||
"reject": "却下",
|
||||
"edit": "編集",
|
||||
"delete": "削除",
|
||||
"blockIp": "IPブロック",
|
||||
"blockEmail": "メールブロック",
|
||||
"pin": "固定"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "前へ",
|
||||
"next": "次へ",
|
||||
"jumpTo": "移動",
|
||||
"page": "ページ",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "コメント {id} を削除しますか?",
|
||||
"confirmBlockIp": "IP {ip} をブラックリストに追加しますか?",
|
||||
"confirmBlockEmail": "メール {email} をブラックリストに追加しますか?",
|
||||
"successBlockIp": "IPをブロックしました",
|
||||
"successBlockEmail": "メールをブロックしました",
|
||||
"empty": "データなし",
|
||||
"editModal": {
|
||||
"title": "コメント編集",
|
||||
"name": "名前",
|
||||
"email": "メール",
|
||||
"url": "URL",
|
||||
"postSlug": "スラッグ",
|
||||
"postUrl": "記事URL",
|
||||
"content": "内容",
|
||||
"status": "ステータス",
|
||||
"priority": "優先度 (1=通常, 大きいほど上)",
|
||||
"cancel": "キャンセル",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "設定",
|
||||
"tabs": {
|
||||
"comment": "コメントとセキュリティ",
|
||||
"feature": "機能設定",
|
||||
"emailNotify": "メール通知",
|
||||
"telegramNotify": "Telegram通知",
|
||||
"display": "表示設定"
|
||||
},
|
||||
"comment": {
|
||||
"title": "コメント表示設定",
|
||||
"adminEmail": "管理者メール",
|
||||
"adminBadge": "管理者バッジ文字 (空の場合はデフォルトアイコン)",
|
||||
"adminEnabled": "管理者バッジを表示",
|
||||
"avatarPrefix": "アバタープレフィックス (デフォルト: https://gravatar.com/avatar)",
|
||||
"securityTitle": "セキュリティ設定",
|
||||
"requireReview": "新規コメントを承認制にする",
|
||||
"adminKey": "管理者キー (管理者メールでのコメントに必要)",
|
||||
"adminKeyPlaceholder": "キーを入力",
|
||||
"allowedDomains": "許可ドメイン (空の場合は制限なし。スペースまたはカンマ区切り)",
|
||||
"blockedIps": "ブロックIP (カンマまたは改行区切り)",
|
||||
"blockedEmails": "ブロックメール (カンマまたは改行区切り)",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "機能設定",
|
||||
"articleLike": "記事へのいいねを有効化",
|
||||
"articleLikeHint": "コメント欄上部に記事へのいいねボタンを表示します。",
|
||||
"commentLike": "コメントへのいいねを有効化",
|
||||
"commentLikeHint": "各コメントにいいねボタンを表示します。",
|
||||
"imageLightbox": "画像ライトボックス",
|
||||
"imageLightboxHint": "コメント内の画像を全画面プレビューします。",
|
||||
"placeholder": "プレースホルダー",
|
||||
"placeholderHint": "コメント入力欄のヒントテキスト。",
|
||||
"widgetLanguage": "ウィジェット言語",
|
||||
"widgetLanguageHint": "フロントエンドウィジェットの言語。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "メール通知設定",
|
||||
"enable": "メール通知を有効化",
|
||||
"smtpTitle": "1. SMTP設定",
|
||||
"provider": "プロバイダー",
|
||||
"host": "SMTPホスト",
|
||||
"port": "SMTPポート",
|
||||
"secure": "SSL接続",
|
||||
"user": "メールユーザー",
|
||||
"pass": "パスワード/アプリパスワード",
|
||||
"qqHint": "注意: QQメールはパスワードではなく認証コードを使用してください。",
|
||||
"163Hint": "注意: 163メールはパスワードではなく認証コードを使用してください。",
|
||||
"templateTitle": "2. テンプレート設定",
|
||||
"adminTemplate": "管理者通知テンプレート (HTML)",
|
||||
"adminTemplateHint": "変数: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "返信通知テンプレート (HTML)",
|
||||
"replyTemplateHint": "変数: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "テストメール送信",
|
||||
"testingBtn": "送信中...",
|
||||
"resetBtn": "テンプレートをリセット",
|
||||
"save": "設定を保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram通知設定",
|
||||
"enable": "Telegram通知を有効化",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "@BotFather から取得",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "ユーザーIDまたはグループID。@userinfobot で確認できます。",
|
||||
"webhookBtn": "Webhook設定",
|
||||
"webhookSetting": "設定中...",
|
||||
"testBtn": "テストメッセージ送信",
|
||||
"testingBtn": "送信中...",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"display": {
|
||||
"title": "表示設定",
|
||||
"layoutTitle": "管理画面タイトル",
|
||||
"layoutTitleHint": "トップナビゲーションバーに表示されます。",
|
||||
"adminLanguage": "管理画面言語",
|
||||
"adminLanguageHint": "管理パネルの言語設定。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "保存成功",
|
||||
"saveFailed": "保存失敗",
|
||||
"loading": "読み込み中..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/ko.json
Normal file
304
cwd-admin/src/locales/ko.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "댓글 관리",
|
||||
"stats": "대시보드",
|
||||
"analytics": "방문 통계",
|
||||
"settings": "사이트 설정",
|
||||
"data": "데이터 관리"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "메뉴 전환",
|
||||
"docs": "문서",
|
||||
"logout": "로그아웃",
|
||||
"moreActions": "더보기",
|
||||
"defaultSite": "기본 사이트",
|
||||
"theme": {
|
||||
"light": "라이트 모드",
|
||||
"dark": "다크 모드",
|
||||
"system": "시스템 설정"
|
||||
},
|
||||
"version": {
|
||||
"title": "버전 정보",
|
||||
"apiAddress": "API 주소",
|
||||
"apiVersion": "API 버전",
|
||||
"adminVersion": "관리자 버전",
|
||||
"match": "관리자와 API 버전이 일치합니다.",
|
||||
"mismatch": "버전 불일치. 호환성 문제를 방지하기 위해 API 서비스를 업데이트하세요.",
|
||||
"fetchError": "버전 정보를 가져올 수 없습니다:",
|
||||
"loading": "로딩 중...",
|
||||
"notConfigured": "설정되지 않음",
|
||||
"notFetched": "가져오지 못함",
|
||||
"ok": "확인"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "대시보드",
|
||||
"overview": "개요",
|
||||
"total": "총 댓글 수",
|
||||
"approved": "승인됨",
|
||||
"pending": "대기 중",
|
||||
"rejected": "거절됨",
|
||||
"trend": "댓글 추세",
|
||||
"bySite": "사이트별 통계",
|
||||
"last7Days": "최근 7일",
|
||||
"last30Days": "최근 30일",
|
||||
"noData": "데이터 없음",
|
||||
"table": {
|
||||
"domain": "도메인",
|
||||
"total": "합계",
|
||||
"approved": "승인됨",
|
||||
"pending": "대기 중",
|
||||
"rejected": "거절됨"
|
||||
},
|
||||
"loadError": "통계 로드 실패"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "방문 통계",
|
||||
"overview": "개요",
|
||||
"totalPv": "총 PV",
|
||||
"todayPv": "오늘 PV",
|
||||
"weekPv": "이번 주 PV",
|
||||
"monthPv": "이번 달 PV",
|
||||
"totalPages": "방문한 페이지 수",
|
||||
"trend": "트래픽 추세",
|
||||
"pageDetail": "페이지 상세",
|
||||
"likeRank": "좋아요 순위",
|
||||
"last7Days": "최근 7일",
|
||||
"last30Days": "최근 30일",
|
||||
"sort": {
|
||||
"pv": "PV순 정렬",
|
||||
"latest": "최신 방문"
|
||||
},
|
||||
"table": {
|
||||
"title": "페이지 제목",
|
||||
"pv": "PV",
|
||||
"time": "마지막 방문",
|
||||
"url": "URL",
|
||||
"rank": "순위",
|
||||
"like": "좋아요"
|
||||
},
|
||||
"noData": "데이터 없음",
|
||||
"noLikeData": "좋아요 데이터 없음",
|
||||
"loadError": "통계 로드 실패"
|
||||
},
|
||||
"data": {
|
||||
"title": "데이터 관리",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "댓글 데이터",
|
||||
"desc": "댓글 관리 및 타 프레임워크에서 가져오기.",
|
||||
"exportLabel": "내보내기:",
|
||||
"exporting": "내보내는 중...",
|
||||
"exportJson": "JSON 내보내기",
|
||||
"importLabel": "가져오기:",
|
||||
"importButton": "댓글 가져오기",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "시스템 설정",
|
||||
"desc": "관리자 설정, 이메일 설정, 차단 목록 등.",
|
||||
"export": "설정 내보내기",
|
||||
"import": "설정 가져오기"
|
||||
},
|
||||
"stats": {
|
||||
"title": "통계 데이터",
|
||||
"desc": "페이지 조회수, 좋아요, 추세 관리.",
|
||||
"export": "통계 내보내기",
|
||||
"import": "통계 가져오기"
|
||||
},
|
||||
"backup": {
|
||||
"title": "전체 백업",
|
||||
"desc": "시스템 전체 데이터 백업 및 복원 (댓글 + 설정 + 통계).",
|
||||
"export": "전체 내보내기",
|
||||
"import": "전체 복원"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "작업 로그"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "URL 접두사 누락 감지됨",
|
||||
"descPart1": "감지됨: ",
|
||||
"descPart2": "개의 댓글 URL에 프로토콜 접두사(http/https)가 없습니다.",
|
||||
"descPart3": "가져올 때 추가하시겠습니까?",
|
||||
"label": "도메인 접두사 (예: https://example.me)",
|
||||
"placeholder": "접두사 입력",
|
||||
"skip": "건너뛰기 (추가 안 함)",
|
||||
"confirm": "추가 및 가져오기"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "내보내기 성공",
|
||||
"exportFailed": "내보내기 실패",
|
||||
"fileReadFailed": "파일 읽기 실패",
|
||||
"jsonParseFailed": "JSON 파싱 실패",
|
||||
"importConfigSuccess": "설정 가져오기 성공",
|
||||
"importStatsSuccess": "통계 가져오기 성공",
|
||||
"importBackupSuccess": "전체 복원 성공",
|
||||
"importCommentsSuccess": "댓글 가져오기 성공",
|
||||
"prefixRequired": "도메인 접두사를 입력하세요",
|
||||
"importStart": "가져오기 시작: {name} (모드: {mode})",
|
||||
"fileParseSuccess": "파일 파싱 성공, 처리 중...",
|
||||
"errorWithMessage": "오류: {msg}",
|
||||
"parsedCommentsCount": "{count}개 댓글 파싱됨",
|
||||
"detectMissingPrefix": "{count}개 URL 누락 감지, 확인 대기 중...",
|
||||
"prefixAdded": "접두사 추가됨, 계속 진행 중...",
|
||||
"skipPrefix": "접두사 추가 건너뜀",
|
||||
"readFileFailedLog": "파일 읽기 실패",
|
||||
"importCommentsDone": "가져오기 완료: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "댓글 관리",
|
||||
"statusFilter": {
|
||||
"all": "전체",
|
||||
"approved": "승인됨",
|
||||
"pending": "대기 중",
|
||||
"rejected": "거절됨"
|
||||
},
|
||||
"refresh": "새로고침",
|
||||
"table": {
|
||||
"author": "사용자",
|
||||
"content": "내용",
|
||||
"path": "경로",
|
||||
"status": "상태",
|
||||
"actions": "작업",
|
||||
"admin": "관리자",
|
||||
"time": "시간",
|
||||
"ip": "IP",
|
||||
"email": "이메일"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "승인",
|
||||
"pending": "보류",
|
||||
"reject": "거절",
|
||||
"edit": "편집",
|
||||
"delete": "삭제",
|
||||
"blockIp": "IP 차단",
|
||||
"blockEmail": "이메일 차단",
|
||||
"pin": "고정"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "이전",
|
||||
"next": "다음",
|
||||
"jumpTo": "이동",
|
||||
"page": "페이지",
|
||||
"confirm": "확인"
|
||||
},
|
||||
"confirmDelete": "댓글 {id}를 삭제하시겠습니까?",
|
||||
"confirmBlockIp": "IP {ip}를 차단하시겠습니까?",
|
||||
"confirmBlockEmail": "이메일 {email}을 차단하시겠습니까?",
|
||||
"successBlockIp": "IP 차단됨",
|
||||
"successBlockEmail": "이메일 차단됨",
|
||||
"empty": "데이터 없음",
|
||||
"editModal": {
|
||||
"title": "댓글 편집",
|
||||
"name": "이름",
|
||||
"email": "이메일",
|
||||
"url": "URL",
|
||||
"postSlug": "슬러그",
|
||||
"postUrl": "게시물 URL",
|
||||
"content": "내용",
|
||||
"status": "상태",
|
||||
"priority": "우선순위 (1=보통, 높을수록 상단)",
|
||||
"cancel": "취소",
|
||||
"save": "저장",
|
||||
"saving": "저장 중..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "설정",
|
||||
"tabs": {
|
||||
"comment": "댓글 및 보안",
|
||||
"feature": "기능",
|
||||
"emailNotify": "이메일 알림",
|
||||
"telegramNotify": "Telegram 알림",
|
||||
"display": "표시 설정"
|
||||
},
|
||||
"comment": {
|
||||
"title": "댓글 표시 설정",
|
||||
"adminEmail": "관리자 이메일",
|
||||
"adminBadge": "관리자 배지 텍스트 (기본 아이콘 사용 시 비워둠)",
|
||||
"adminEnabled": "관리자 배지 표시",
|
||||
"avatarPrefix": "아바타 접두사 (기본값: https://gravatar.com/avatar)",
|
||||
"securityTitle": "보안 설정",
|
||||
"requireReview": "새 댓글 검토 후 표시",
|
||||
"adminKey": "관리자 키 (관리자 이메일 댓글 작성 시 필요)",
|
||||
"adminKeyPlaceholder": "키 입력",
|
||||
"allowedDomains": "허용 도메인 (비워두면 모두 허용. 공백/콤마로 구분)",
|
||||
"blockedIps": "차단된 IP (콤마/줄바꿈으로 구분)",
|
||||
"blockedEmails": "차단된 이메일 (콤마/줄바꿈으로 구분)",
|
||||
"save": "저장",
|
||||
"saving": "저장 중..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "기능 설정",
|
||||
"articleLike": "게시물 좋아요 활성화",
|
||||
"articleLikeHint": "댓글 상단에 좋아요 버튼 표시.",
|
||||
"commentLike": "댓글 좋아요 활성화",
|
||||
"commentLikeHint": "각 댓글에 좋아요 버튼 표시.",
|
||||
"imageLightbox": "이미지 라이트박스",
|
||||
"imageLightboxHint": "댓글 이미지 클릭 시 전체 화면 미리보기.",
|
||||
"placeholder": "플레이스홀더",
|
||||
"placeholderHint": "댓글 입력창 안내 문구.",
|
||||
"widgetLanguage": "위젯 언어",
|
||||
"widgetLanguageHint": "프론트엔드 위젯 언어.",
|
||||
"save": "저장",
|
||||
"saving": "저장 중..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "이메일 알림",
|
||||
"enable": "이메일 알림 활성화",
|
||||
"smtpTitle": "1. SMTP 설정",
|
||||
"provider": "제공자",
|
||||
"host": "SMTP 호스트",
|
||||
"port": "SMTP 포트",
|
||||
"secure": "SSL 보안",
|
||||
"user": "이메일 계정",
|
||||
"pass": "비밀번호/앱 토큰",
|
||||
"qqHint": "참고: QQ 메일은 비밀번호 대신 앱 토큰을 사용하세요.",
|
||||
"163Hint": "참고: 163 메일은 비밀번호 대신 앱 토큰을 사용하세요.",
|
||||
"templateTitle": "2. 템플릿 설정",
|
||||
"adminTemplate": "관리자 알림 템플릿 (HTML)",
|
||||
"adminTemplateHint": "변수: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "답글 알림 템플릿 (HTML)",
|
||||
"replyTemplateHint": "변수: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "테스트 이메일 전송",
|
||||
"testingBtn": "전송 중...",
|
||||
"resetBtn": "템플릿 초기화",
|
||||
"save": "설정 저장",
|
||||
"saving": "저장 중..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram 알림",
|
||||
"enable": "Telegram 알림 활성화",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "@BotFather에서 획득",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "사용자 ID 또는 그룹 ID. @userinfobot으로 확인.",
|
||||
"webhookBtn": "웹훅 설정",
|
||||
"webhookSetting": "설정 중...",
|
||||
"testBtn": "테스트 메시지 전송",
|
||||
"testingBtn": "전송 중...",
|
||||
"save": "저장",
|
||||
"saving": "저장 중..."
|
||||
},
|
||||
"display": {
|
||||
"title": "표시 설정",
|
||||
"layoutTitle": "관리자 제목",
|
||||
"layoutTitleHint": "상단 내비게이션 바에 표시됨.",
|
||||
"adminLanguage": "관리자 언어",
|
||||
"adminLanguageHint": "관리자 패널 언어.",
|
||||
"save": "저장",
|
||||
"saving": "저장 중..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "저장 성공",
|
||||
"saveFailed": "저장 실패",
|
||||
"loading": "로딩 중..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/nl.json
Normal file
304
cwd-admin/src/locales/nl.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Reactiebeheer",
|
||||
"stats": "Dashboard",
|
||||
"analytics": "Bezoekstatistieken",
|
||||
"settings": "Instellingen",
|
||||
"data": "Gegevensbeheer"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Menu wisselen",
|
||||
"docs": "Documentatie",
|
||||
"logout": "Uitloggen",
|
||||
"moreActions": "Meer acties",
|
||||
"defaultSite": "Standaard site",
|
||||
"theme": {
|
||||
"light": "Licht",
|
||||
"dark": "Donker",
|
||||
"system": "Systeem"
|
||||
},
|
||||
"version": {
|
||||
"title": "Versie-informatie",
|
||||
"apiAddress": "API-adres",
|
||||
"apiVersion": "API-versie",
|
||||
"adminVersion": "Beheerversie",
|
||||
"match": "De huidige beheerversie komt overeen met de API-versie, u kunt deze normaal gebruiken.",
|
||||
"mismatch": "De huidige beheerversie komt niet overeen met de API-versie. Het wordt aanbevolen om de API-service bij te werken om compatibiliteitsproblemen te voorkomen.",
|
||||
"fetchError": "Kan API-versie niet ophalen:",
|
||||
"loading": "Laden...",
|
||||
"notConfigured": "Niet geconfigureerd",
|
||||
"notFetched": "Niet opgehaald",
|
||||
"ok": "Begrepen"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dashboard",
|
||||
"overview": "Overzicht",
|
||||
"total": "Totaal reacties",
|
||||
"approved": "Goedgekeurd",
|
||||
"pending": "In afwachting",
|
||||
"rejected": "Geweigerd",
|
||||
"trend": "Reactietrend",
|
||||
"bySite": "Statistieken per site",
|
||||
"last7Days": "Laatste 7 dagen",
|
||||
"last30Days": "Laatste 30 dagen",
|
||||
"noData": "Geen reactiegegevens",
|
||||
"table": {
|
||||
"domain": "Domein",
|
||||
"total": "Totaal",
|
||||
"approved": "Goedgekeurd",
|
||||
"pending": "In afwachting",
|
||||
"rejected": "Geweigerd"
|
||||
},
|
||||
"loadError": "Kan statistieken niet laden"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Bezoekstatistieken",
|
||||
"overview": "Overzicht",
|
||||
"totalPv": "Totaal aantal bezoeken",
|
||||
"todayPv": "Bezoeken vandaag",
|
||||
"weekPv": "Bezoeken deze week",
|
||||
"monthPv": "Bezoeken deze maand",
|
||||
"totalPages": "Pagina's met bezoeken",
|
||||
"trend": "Bezoektrend",
|
||||
"pageDetail": "Paginadetails",
|
||||
"likeRank": "Pagina's met meeste likes",
|
||||
"last7Days": "Laatste 7 dagen",
|
||||
"last30Days": "Laatste 30 dagen",
|
||||
"sort": {
|
||||
"pv": "Sorteer op PV",
|
||||
"latest": "Nieuwste bezoek"
|
||||
},
|
||||
"table": {
|
||||
"title": "Paginatitel",
|
||||
"pv": "Bezoeken",
|
||||
"time": "Laatste bezoek",
|
||||
"url": "Pagina-URL",
|
||||
"rank": "Rang",
|
||||
"like": "Likes"
|
||||
},
|
||||
"noData": "Geen bezoekgegevens",
|
||||
"noLikeData": "Geen like-gegevens",
|
||||
"loadError": "Kan bezoekstatistieken niet laden"
|
||||
},
|
||||
"data": {
|
||||
"title": "Gegevensbeheer",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Reactiegegevens",
|
||||
"desc": "Beheer reacties, ondersteunt migratie van andere reactiesystemen.",
|
||||
"exportLabel": "Exporteren:",
|
||||
"exporting": "Exporteren...",
|
||||
"exportJson": "JSON exporteren",
|
||||
"importLabel": "Importeren:",
|
||||
"importButton": "Reacties importeren",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Systeemconfiguratie",
|
||||
"desc": "Beheer systeeminstellingen, e-mailconfiguratie, zwarte lijsten, enz.",
|
||||
"export": "Configuratie exporteren",
|
||||
"import": "Configuratie importeren"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Bezoekstatistieken",
|
||||
"desc": "Beheer paginabezoeken, likes en dagelijkse trends.",
|
||||
"export": "Statistieken exporteren",
|
||||
"import": "Statistieken importeren"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Volledige back-up",
|
||||
"desc": "Back-up of herstel van alle systeemgegevens (reacties + configuratie + statistieken).",
|
||||
"export": "Volledig exporteren",
|
||||
"import": "Volledig herstellen"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Actielogs"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "URL-voorvoegsel ontbreekt",
|
||||
"descPart1": "Gedetecteerd ",
|
||||
"descPart2": " reacties zonder domeinvoorvoegsel (http/https).",
|
||||
"descPart3": "Wilt u dit toevoegen tijdens het importeren?",
|
||||
"label": "Domeinvoorvoegsel (bijv. https://example.me)",
|
||||
"placeholder": "Voer domeinvoorvoegsel in",
|
||||
"skip": "Direct importeren (niet toevoegen)",
|
||||
"confirm": "Toevoegen en importeren"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Exporteren geslaagd",
|
||||
"exportFailed": "Exporteren mislukt",
|
||||
"fileReadFailed": "Bestand lezen mislukt",
|
||||
"jsonParseFailed": "JSON parsen mislukt, controleer het bestandsformaat",
|
||||
"importConfigSuccess": "Configuratie importeren geslaagd",
|
||||
"importStatsSuccess": "Statistieken importeren geslaagd",
|
||||
"importBackupSuccess": "Volledig herstel geslaagd",
|
||||
"importCommentsSuccess": "Reacties importeren geslaagd",
|
||||
"prefixRequired": "Voer een domeinvoorvoegsel in",
|
||||
"importStart": "Start import: {name} (Modus: {mode})",
|
||||
"fileParseSuccess": "Bestand geparsed, verwerken...",
|
||||
"errorWithMessage": "Fout: {msg}",
|
||||
"parsedCommentsCount": "{count} reacties geparsed",
|
||||
"detectMissingPrefix": "{count} URL's zonder voorvoegsel gedetecteerd, wachten op bevestiging...",
|
||||
"prefixAdded": "Voorvoegsel toegevoegd, doorgaan met importeren...",
|
||||
"skipPrefix": "Gebruiker heeft voorvoegsel toevoegen overgeslagen",
|
||||
"readFileFailedLog": "Bestand lezen mislukt",
|
||||
"importCommentsDone": "Import voltooid: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Reactiebeheer",
|
||||
"statusFilter": {
|
||||
"all": "Alle statussen",
|
||||
"approved": "Goedgekeurd",
|
||||
"pending": "In afwachting",
|
||||
"rejected": "Geweigerd"
|
||||
},
|
||||
"refresh": "Vernieuwen",
|
||||
"table": {
|
||||
"author": "Gebruiker",
|
||||
"content": "Inhoud",
|
||||
"path": "Pad",
|
||||
"status": "Status",
|
||||
"actions": "Acties",
|
||||
"admin": "Beheerder",
|
||||
"time": "Tijd",
|
||||
"ip": "IP",
|
||||
"email": "E-mail"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Goedkeuren",
|
||||
"pending": "Wachten",
|
||||
"reject": "Weigeren",
|
||||
"edit": "Bewerken",
|
||||
"delete": "Verwijderen",
|
||||
"blockIp": "IP blokkeren",
|
||||
"blockEmail": "E-mail blokkeren",
|
||||
"pin": "Vastzetten"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Vorige",
|
||||
"next": "Volgende",
|
||||
"jumpTo": "Ga naar",
|
||||
"page": "Pagina",
|
||||
"confirm": "Bevestigen"
|
||||
},
|
||||
"confirmDelete": "Weet u zeker dat u reactie {id} wilt verwijderen?",
|
||||
"confirmBlockIp": "Weet u zeker dat u IP {ip} op de zwarte lijst wilt zetten?",
|
||||
"confirmBlockEmail": "Weet u zeker dat u e-mail {email} op de zwarte lijst wilt zetten?",
|
||||
"successBlockIp": "IP toegevoegd aan zwarte lijst",
|
||||
"successBlockEmail": "E-mail toegevoegd aan zwarte lijst",
|
||||
"empty": "Geen gegevens",
|
||||
"editModal": {
|
||||
"title": "Reactie bewerken",
|
||||
"name": "Naam bezoeker",
|
||||
"email": "E-mail bezoeker",
|
||||
"url": "URL bezoeker",
|
||||
"postSlug": "Pagina-ID",
|
||||
"postUrl": "Reactie-URL",
|
||||
"content": "Inhoud",
|
||||
"status": "Status",
|
||||
"priority": "Prioriteit (1 is standaard, hoger is belangrijker)",
|
||||
"cancel": "Annuleren",
|
||||
"save": "Opslaan",
|
||||
"saving": "Opslaan..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Instellingen",
|
||||
"tabs": {
|
||||
"comment": "Reacties & Beveiliging",
|
||||
"feature": "Functies",
|
||||
"emailNotify": "E-mailmeldingen",
|
||||
"telegramNotify": "Telegram-meldingen",
|
||||
"display": "Weergave"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Reactieweergave",
|
||||
"adminEmail": "E-mailadres beheerder",
|
||||
"adminBadge": "Beheerderlabel (leeg laten voor standaardpictogram)",
|
||||
"adminEnabled": "Beheerderlabel weergeven",
|
||||
"avatarPrefix": "Avatar-voorvoegsel (standaard: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Beveiligingsinstellingen",
|
||||
"requireReview": "Nieuwe reacties moeten worden goedgekeurd",
|
||||
"adminKey": "Beheerderssleutel (vereist voor reacties met beheerders-e-mail)",
|
||||
"adminKeyPlaceholder": "Voer sleutel in om in te stellen of te wijzigen",
|
||||
"allowedDomains": "Toegestane domeinen (leeg laten voor alle domeinen, scheiden met komma of spatie)",
|
||||
"blockedIps": "IP zwarte lijst (scheiden met komma of nieuwe regel)",
|
||||
"blockedEmails": "E-mail zwarte lijst (scheiden met komma of nieuwe regel)",
|
||||
"save": "Opslaan",
|
||||
"saving": "Opslaan..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Functies",
|
||||
"articleLike": "Artikel likes inschakelen",
|
||||
"articleLikeHint": "Toont een like-knop boven de reactiesectie.",
|
||||
"commentLike": "Reactie likes inschakelen",
|
||||
"commentLikeHint": "Toont een like-knop bij elke reactie.",
|
||||
"imageLightbox": "Lightbox voor afbeeldingen",
|
||||
"imageLightboxHint": "Klik op afbeeldingen in reacties om ze op volledig scherm te bekijken.",
|
||||
"placeholder": "Plaatsaanduiding invoerveld",
|
||||
"placeholderHint": "Aangepaste tekst voor het invoerveld. Leeg laten voor standaard.",
|
||||
"widgetLanguage": "Widgettaal",
|
||||
"widgetLanguageHint": "Taal van de frontend-widget.",
|
||||
"save": "Opslaan",
|
||||
"saving": "Opslaan..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "E-mailinstellingen",
|
||||
"enable": "E-mailmeldingen inschakelen",
|
||||
"smtpTitle": "1. SMTP-configuratie",
|
||||
"provider": "Provider",
|
||||
"host": "SMTP-host",
|
||||
"port": "SMTP-poort",
|
||||
"secure": "SSL-verbinding",
|
||||
"user": "E-mailadres",
|
||||
"pass": "Wachtwoord/App-wachtwoord",
|
||||
"qqHint": "Opmerking: Gebruik voor QQ Mail een autorisatiecode, geen wachtwoord.",
|
||||
"163Hint": "Opmerking: Gebruik voor 163 Mail een autorisatiecode, geen wachtwoord.",
|
||||
"templateTitle": "2. E-mailjablonen",
|
||||
"adminTemplate": "Beheerdersmelding (HTML)",
|
||||
"adminTemplateHint": "Variabelen: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Antwoordmelding (HTML)",
|
||||
"replyTemplateHint": "Variabelen: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Test e-mail verzenden",
|
||||
"testingBtn": "Verzenden...",
|
||||
"resetBtn": "Sjablonen resetten",
|
||||
"save": "Configuratie opslaan",
|
||||
"saving": "Opslaan..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram-instellingen",
|
||||
"enable": "Telegram-meldingen inschakelen",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "Maak een bot aan via @BotFather om een token te krijgen",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "Gebruiker- of groeps-ID. Stuur een bericht naar de bot en gebruik API of @userinfobot om ID te vinden.",
|
||||
"webhookBtn": "Webhook instellen",
|
||||
"webhookSetting": "Instellen...",
|
||||
"testBtn": "Testbericht verzenden",
|
||||
"testingBtn": "Verzenden...",
|
||||
"save": "Opslaan",
|
||||
"saving": "Opslaan..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Weergave-instellingen",
|
||||
"layoutTitle": "Titel beheerpaneel",
|
||||
"layoutTitleHint": "Wordt weergegeven in de navigatiebalk.",
|
||||
"adminLanguage": "Taal beheerpaneel",
|
||||
"adminLanguageHint": "Taal van het beheersysteem.",
|
||||
"save": "Opslaan",
|
||||
"saving": "Opslaan..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Opslaan geslaagd",
|
||||
"saveFailed": "Opslaan mislukt",
|
||||
"loading": "Laden..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/pt.json
Normal file
304
cwd-admin/src/locales/pt.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Gestão de Comentários",
|
||||
"stats": "Painel",
|
||||
"analytics": "Analítica",
|
||||
"settings": "Configurações",
|
||||
"data": "Dados"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Alternar Menu",
|
||||
"docs": "Documentação",
|
||||
"logout": "Sair",
|
||||
"moreActions": "Mais Ações",
|
||||
"defaultSite": "Site Padrão",
|
||||
"theme": {
|
||||
"light": "Claro",
|
||||
"dark": "Escuro",
|
||||
"system": "Sistema"
|
||||
},
|
||||
"version": {
|
||||
"title": "Info da Versão",
|
||||
"apiAddress": "Endereço da API",
|
||||
"apiVersion": "Versão da API",
|
||||
"adminVersion": "Versão do Admin",
|
||||
"match": "As versões do Admin e da API correspondem.",
|
||||
"mismatch": "Versão incompatível. Atualize o serviço da API.",
|
||||
"fetchError": "Falha ao obter versão:",
|
||||
"loading": "Carregando...",
|
||||
"notConfigured": "Não Configurado",
|
||||
"notFetched": "Não Obtido",
|
||||
"ok": "OK"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Painel",
|
||||
"overview": "Visão Geral",
|
||||
"total": "Total de Comentários",
|
||||
"approved": "Aprovados",
|
||||
"pending": "Pendentes",
|
||||
"rejected": "Rejeitados",
|
||||
"trend": "Tendência",
|
||||
"bySite": "Por Site",
|
||||
"last7Days": "Últimos 7 Dias",
|
||||
"last30Days": "Últimos 30 Dias",
|
||||
"noData": "Sem Dados",
|
||||
"table": {
|
||||
"domain": "Domínio",
|
||||
"total": "Total",
|
||||
"approved": "Aprovados",
|
||||
"pending": "Pendentes",
|
||||
"rejected": "Rejeitados"
|
||||
},
|
||||
"loadError": "Erro ao carregar estatísticas"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Analítica",
|
||||
"overview": "Visão Geral",
|
||||
"totalPv": "PV Total",
|
||||
"todayPv": "PV Hoje",
|
||||
"weekPv": "PV Semana",
|
||||
"monthPv": "PV Mês",
|
||||
"totalPages": "Páginas Visitadas",
|
||||
"trend": "Tendência de Tráfego",
|
||||
"pageDetail": "Detalhes da Página",
|
||||
"likeRank": "Top Curtidas",
|
||||
"last7Days": "Últimos 7 Dias",
|
||||
"last30Days": "Últimos 30 Dias",
|
||||
"sort": {
|
||||
"pv": "Ordenar por PV",
|
||||
"latest": "Última Visita"
|
||||
},
|
||||
"table": {
|
||||
"title": "Título da Página",
|
||||
"pv": "PV",
|
||||
"time": "Última Visita",
|
||||
"url": "URL",
|
||||
"rank": "Rank",
|
||||
"like": "Curtidas"
|
||||
},
|
||||
"noData": "Sem Dados",
|
||||
"noLikeData": "Sem Dados de Curtidas",
|
||||
"loadError": "Erro ao carregar analítica"
|
||||
},
|
||||
"data": {
|
||||
"title": "Gestão de Dados",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Dados de Comentários",
|
||||
"desc": "Gerenciar e importar comentários.",
|
||||
"exportLabel": "Exportar:",
|
||||
"exporting": "Exportando...",
|
||||
"exportJson": "Exportar JSON",
|
||||
"importLabel": "Importar:",
|
||||
"importButton": "Importar Comentários",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Config do Sistema",
|
||||
"desc": "Configurações, e-mail, lista negra, etc.",
|
||||
"export": "Exportar Config",
|
||||
"import": "Importar Config"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Dados Analíticos",
|
||||
"desc": "Visualizações, curtidas e tendências.",
|
||||
"export": "Exportar Stats",
|
||||
"import": "Importar Stats"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Backup Completo",
|
||||
"desc": "Backup ou restauração de tudo (Comentários + Config + Stats).",
|
||||
"export": "Exportação Completa",
|
||||
"import": "Restauração Completa"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Logs de Operação"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Prefixo de URL Ausente",
|
||||
"descPart1": "Detectado ",
|
||||
"descPart2": " comentários sem prefixo de protocolo (http/https).",
|
||||
"descPart3": "Adicionar ao importar?",
|
||||
"label": "Prefixo de Domínio (ex: https://example.me)",
|
||||
"placeholder": "Inserir prefixo",
|
||||
"skip": "Pular",
|
||||
"confirm": "Adicionar e Importar"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Exportação com Sucesso",
|
||||
"exportFailed": "Falha na Exportação",
|
||||
"fileReadFailed": "Falha na Leitura do Arquivo",
|
||||
"jsonParseFailed": "Falha na Análise JSON",
|
||||
"importConfigSuccess": "Config Importada",
|
||||
"importStatsSuccess": "Stats Importadas",
|
||||
"importBackupSuccess": "Restauração Completa com Sucesso",
|
||||
"importCommentsSuccess": "Comentários Importados",
|
||||
"prefixRequired": "Por favor, insira o prefixo",
|
||||
"importStart": "Importando: {name} (Modo: {mode})",
|
||||
"fileParseSuccess": "Arquivo analisado, processando...",
|
||||
"errorWithMessage": "Erro: {msg}",
|
||||
"parsedCommentsCount": "{count} comentários analisados",
|
||||
"detectMissingPrefix": "{count} URLs sem prefixo, aguardando confirmação...",
|
||||
"prefixAdded": "Prefixo adicionado, continuando...",
|
||||
"skipPrefix": "Adição de prefixo pulada",
|
||||
"readFileFailedLog": "Falha na leitura do arquivo",
|
||||
"importCommentsDone": "Importação Concluída: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Gestão de Comentários",
|
||||
"statusFilter": {
|
||||
"all": "Todos",
|
||||
"approved": "Aprovados",
|
||||
"pending": "Pendentes",
|
||||
"rejected": "Rejeitados"
|
||||
},
|
||||
"refresh": "Atualizar",
|
||||
"table": {
|
||||
"author": "Usuário",
|
||||
"content": "Comentário",
|
||||
"path": "Caminho",
|
||||
"status": "Status",
|
||||
"actions": "Ações",
|
||||
"admin": "Admin",
|
||||
"time": "Hora",
|
||||
"ip": "IP",
|
||||
"email": "E-mail"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Aprovar",
|
||||
"pending": "Pendente",
|
||||
"reject": "Rejeitar",
|
||||
"edit": "Editar",
|
||||
"delete": "Excluir",
|
||||
"blockIp": "Bloquear IP",
|
||||
"blockEmail": "Bloquear E-mail",
|
||||
"pin": "Fixar"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Ant",
|
||||
"next": "Próx",
|
||||
"jumpTo": "Ir para",
|
||||
"page": "Página",
|
||||
"confirm": "OK"
|
||||
},
|
||||
"confirmDelete": "Excluir comentário {id}?",
|
||||
"confirmBlockIp": "Bloquear IP {ip}?",
|
||||
"confirmBlockEmail": "Bloquear e-mail {email}?",
|
||||
"successBlockIp": "IP Bloqueado",
|
||||
"successBlockEmail": "E-mail Bloqueado",
|
||||
"empty": "Sem Dados",
|
||||
"editModal": {
|
||||
"title": "Editar Comentário",
|
||||
"name": "Nome",
|
||||
"email": "E-mail",
|
||||
"url": "URL",
|
||||
"postSlug": "Slug",
|
||||
"postUrl": "URL do Post",
|
||||
"content": "Conteúdo",
|
||||
"status": "Status",
|
||||
"priority": "Prioridade (1=Normal, maior=Topo)",
|
||||
"cancel": "Cancelar",
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Configurações",
|
||||
"tabs": {
|
||||
"comment": "Comentários e Segurança",
|
||||
"feature": "Funcionalidades",
|
||||
"emailNotify": "Notificação por E-mail",
|
||||
"telegramNotify": "Notificação Telegram",
|
||||
"display": "Exibição"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Exibição de Comentários",
|
||||
"adminEmail": "E-mail Admin",
|
||||
"adminBadge": "Texto do Emblema Admin (Vazio para ícone padrão)",
|
||||
"adminEnabled": "Mostrar Emblema Admin",
|
||||
"avatarPrefix": "Prefixo do Avatar (Padrão: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Segurança",
|
||||
"requireReview": "Exigir Revisão para Novos Comentários",
|
||||
"adminKey": "Chave Admin (Necessária para comentários com e-mail admin)",
|
||||
"adminKeyPlaceholder": "Inserir chave",
|
||||
"allowedDomains": "Domínios Permitidos (Vazio para todos. Separar por espaço/vírgula)",
|
||||
"blockedIps": "IPs Bloqueados (Separar por vírgula/nova linha)",
|
||||
"blockedEmails": "E-mails Bloqueados (Separar por vírgula/nova linha)",
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Funcionalidades",
|
||||
"articleLike": "Ativar Curtidas no Artigo",
|
||||
"articleLikeHint": "Mostrar botão de curtir acima dos comentários.",
|
||||
"commentLike": "Ativar Curtidas no Comentário",
|
||||
"commentLikeHint": "Mostrar botão de curtir em cada comentário.",
|
||||
"imageLightbox": "Lightbox de Imagem",
|
||||
"imageLightboxHint": "Ativar visualização em tela cheia para imagens.",
|
||||
"placeholder": "Texto do Placeholder",
|
||||
"placeholderHint": "Placeholder personalizado para entrada de comentários.",
|
||||
"widgetLanguage": "Idioma do Widget",
|
||||
"widgetLanguageHint": "Idioma para o widget frontend.",
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Notificação por E-mail",
|
||||
"enable": "Ativar Notificação por E-mail",
|
||||
"smtpTitle": "1. Config SMTP",
|
||||
"provider": "Provedor",
|
||||
"host": "Host SMTP",
|
||||
"port": "Porta SMTP",
|
||||
"secure": "Segurança SSL",
|
||||
"user": "Usuário de E-mail",
|
||||
"pass": "Senha/Token de App",
|
||||
"qqHint": "Nota: Para QQ Mail, use Token de App.",
|
||||
"163Hint": "Nota: Para 163 Mail, use Token de App.",
|
||||
"templateTitle": "2. Config de Modelos",
|
||||
"adminTemplate": "Modelo Admin (HTML)",
|
||||
"adminTemplateHint": "Vars: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Modelo Resposta (HTML)",
|
||||
"replyTemplateHint": "Vars: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Enviar E-mail de Teste",
|
||||
"testingBtn": "Enviando...",
|
||||
"resetBtn": "Redefinir Modelos",
|
||||
"save": "Salvar Config",
|
||||
"saving": "Salvando..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Notificação Telegram",
|
||||
"enable": "Ativar Notificação Telegram",
|
||||
"botToken": "Token do Bot",
|
||||
"botTokenHint": "Obter via @BotFather",
|
||||
"chatId": "ID do Chat",
|
||||
"chatIdHint": "ID de Usuário ou Grupo. Use @userinfobot.",
|
||||
"webhookBtn": "Definir Webhook",
|
||||
"webhookSetting": "Configurando...",
|
||||
"testBtn": "Enviar Mensagem de Teste",
|
||||
"testingBtn": "Enviando...",
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Configurações de Exibição",
|
||||
"layoutTitle": "Título do Admin",
|
||||
"layoutTitleHint": "Exibido na barra de navegação superior.",
|
||||
"adminLanguage": "Idioma do Admin",
|
||||
"adminLanguageHint": "Idioma para o painel de administração.",
|
||||
"save": "Salvar",
|
||||
"saving": "Salvando..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Salvo com Sucesso",
|
||||
"saveFailed": "Falha ao Salvar",
|
||||
"loading": "Carregando..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/ru.json
Normal file
304
cwd-admin/src/locales/ru.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "Управление Комментариями",
|
||||
"stats": "Панель",
|
||||
"analytics": "Аналитика",
|
||||
"settings": "Настройки",
|
||||
"data": "Данные"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "Меню",
|
||||
"docs": "Документация",
|
||||
"logout": "Выйти",
|
||||
"moreActions": "Ещё",
|
||||
"defaultSite": "Сайт по Умолчанию",
|
||||
"theme": {
|
||||
"light": "Светлая",
|
||||
"dark": "Тёмная",
|
||||
"system": "Системная"
|
||||
},
|
||||
"version": {
|
||||
"title": "Версия",
|
||||
"apiAddress": "Адрес API",
|
||||
"apiVersion": "Версия API",
|
||||
"adminVersion": "Версия Админки",
|
||||
"match": "Версии совпадают.",
|
||||
"mismatch": "Версии не совпадают. Обновите API.",
|
||||
"fetchError": "Ошибка получения версии:",
|
||||
"loading": "Загрузка...",
|
||||
"notConfigured": "Не настроено",
|
||||
"notFetched": "Не получено",
|
||||
"ok": "ОК"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "Панель",
|
||||
"overview": "Обзор",
|
||||
"total": "Всего Комментариев",
|
||||
"approved": "Одобрено",
|
||||
"pending": "На проверке",
|
||||
"rejected": "Отклонено",
|
||||
"trend": "Тренд",
|
||||
"bySite": "По сайтам",
|
||||
"last7Days": "7 дней",
|
||||
"last30Days": "30 дней",
|
||||
"noData": "Нет данных",
|
||||
"table": {
|
||||
"domain": "Домен",
|
||||
"total": "Всего",
|
||||
"approved": "Одобрено",
|
||||
"pending": "На проверке",
|
||||
"rejected": "Отклонено"
|
||||
},
|
||||
"loadError": "Ошибка загрузки статистики"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "Аналитика",
|
||||
"overview": "Обзор",
|
||||
"totalPv": "Всего PV",
|
||||
"todayPv": "PV Сегодня",
|
||||
"weekPv": "PV Неделя",
|
||||
"monthPv": "PV Месяц",
|
||||
"totalPages": "Посещённые страницы",
|
||||
"trend": "Тренд Трафика",
|
||||
"pageDetail": "Детали Страницы",
|
||||
"likeRank": "Топ Лайков",
|
||||
"last7Days": "7 дней",
|
||||
"last30Days": "30 дней",
|
||||
"sort": {
|
||||
"pv": "Сорт. по PV",
|
||||
"latest": "Последние"
|
||||
},
|
||||
"table": {
|
||||
"title": "Заголовок",
|
||||
"pv": "PV",
|
||||
"time": "Последний Визит",
|
||||
"url": "URL",
|
||||
"rank": "Ранг",
|
||||
"like": "Лайки"
|
||||
},
|
||||
"noData": "Нет данных",
|
||||
"noLikeData": "Нет данных о лайках",
|
||||
"loadError": "Ошибка загрузки аналитики"
|
||||
},
|
||||
"data": {
|
||||
"title": "Управление Данными",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "Данные Комментариев",
|
||||
"desc": "Управление и импорт комментариев.",
|
||||
"exportLabel": "Экспорт:",
|
||||
"exporting": "Экспорт...",
|
||||
"exportJson": "Экспорт JSON",
|
||||
"importLabel": "Импорт:",
|
||||
"importButton": "Импорт Комментариев",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "Конфигурация",
|
||||
"desc": "Настройки, email, чёрный список.",
|
||||
"export": "Экспорт Конфига",
|
||||
"import": "Импорт Конфига"
|
||||
},
|
||||
"stats": {
|
||||
"title": "Аналитика",
|
||||
"desc": "Просмотры, лайки, тренды.",
|
||||
"export": "Экспорт Статистики",
|
||||
"import": "Импорт Статистики"
|
||||
},
|
||||
"backup": {
|
||||
"title": "Полный Бэкап",
|
||||
"desc": "Бэкап или восстановление всего (Комментарии + Конфиг + Статистика).",
|
||||
"export": "Полный Экспорт",
|
||||
"import": "Полное Восстановление"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "Журнал Операций"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "Отсутствует префикс URL",
|
||||
"descPart1": "Обнаружено ",
|
||||
"descPart2": " комментариев без префикса (http/https).",
|
||||
"descPart3": "Добавить при импорте?",
|
||||
"label": "Префикс домена (напр. https://example.me)",
|
||||
"placeholder": "Введите префикс",
|
||||
"skip": "Пропустить",
|
||||
"confirm": "Добавить и Импортировать"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "Экспорт успешен",
|
||||
"exportFailed": "Ошибка экспорта",
|
||||
"fileReadFailed": "Ошибка чтения файла",
|
||||
"jsonParseFailed": "Ошибка парсинга JSON",
|
||||
"importConfigSuccess": "Конфиг импортирован",
|
||||
"importStatsSuccess": "Статистика импортирована",
|
||||
"importBackupSuccess": "Восстановление успешно",
|
||||
"importCommentsSuccess": "Комментарии импортированы",
|
||||
"prefixRequired": "Введите префикс",
|
||||
"importStart": "Импорт: {name} (Режим: {mode})",
|
||||
"fileParseSuccess": "Файл разобран, обработка...",
|
||||
"errorWithMessage": "Ошибка: {msg}",
|
||||
"parsedCommentsCount": "Разобрано {count} комментариев",
|
||||
"detectMissingPrefix": "{count} URL без префикса, ожидание...",
|
||||
"prefixAdded": "Префикс добавлен, продолжение...",
|
||||
"skipPrefix": "Добавление префикса пропущено",
|
||||
"readFileFailedLog": "Ошибка чтения файла",
|
||||
"importCommentsDone": "Импорт завершён: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "Управление Комментариями",
|
||||
"statusFilter": {
|
||||
"all": "Все",
|
||||
"approved": "Одобрено",
|
||||
"pending": "На проверке",
|
||||
"rejected": "Отклонено"
|
||||
},
|
||||
"refresh": "Обновить",
|
||||
"table": {
|
||||
"author": "Пользователь",
|
||||
"content": "Комментарий",
|
||||
"path": "Путь",
|
||||
"status": "Статус",
|
||||
"actions": "Действия",
|
||||
"admin": "Админ",
|
||||
"time": "Время",
|
||||
"ip": "IP",
|
||||
"email": "Email"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "Одобрить",
|
||||
"pending": "На проверку",
|
||||
"reject": "Отклонить",
|
||||
"edit": "Редактировать",
|
||||
"delete": "Удалить",
|
||||
"blockIp": "Блок IP",
|
||||
"blockEmail": "Блок Email",
|
||||
"pin": "Закрепить"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "Пред",
|
||||
"next": "След",
|
||||
"jumpTo": "Перейти",
|
||||
"page": "Стр",
|
||||
"confirm": "ОК"
|
||||
},
|
||||
"confirmDelete": "Удалить комментарий {id}?",
|
||||
"confirmBlockIp": "Блокировать IP {ip}?",
|
||||
"confirmBlockEmail": "Блокировать Email {email}?",
|
||||
"successBlockIp": "IP заблокирован",
|
||||
"successBlockEmail": "Email заблокирован",
|
||||
"empty": "Нет данных",
|
||||
"editModal": {
|
||||
"title": "Редактировать Комментарий",
|
||||
"name": "Имя",
|
||||
"email": "Email",
|
||||
"url": "URL",
|
||||
"postSlug": "Слаг",
|
||||
"postUrl": "URL Поста",
|
||||
"content": "Контент",
|
||||
"status": "Статус",
|
||||
"priority": "Приоритет (1=Обычный, выше=Топ)",
|
||||
"cancel": "Отмена",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "Настройки",
|
||||
"tabs": {
|
||||
"comment": "Комментарии и Безопасность",
|
||||
"feature": "Функции",
|
||||
"emailNotify": "Email Уведомления",
|
||||
"telegramNotify": "Telegram Уведомления",
|
||||
"display": "Отображение"
|
||||
},
|
||||
"comment": {
|
||||
"title": "Отображение Комментариев",
|
||||
"adminEmail": "Email Админа",
|
||||
"adminBadge": "Текст Бейджа Админа (Пусто для иконки)",
|
||||
"adminEnabled": "Показывать Бейдж Админа",
|
||||
"avatarPrefix": "Префикс Аватара (По умолч.: https://gravatar.com/avatar)",
|
||||
"securityTitle": "Безопасность",
|
||||
"requireReview": "Премодерация Новых Комментариев",
|
||||
"adminKey": "Ключ Админа (Для комм. с email админа)",
|
||||
"adminKeyPlaceholder": "Введите ключ",
|
||||
"allowedDomains": "Разрешённые Домены (Пусто для всех. Разделитель пробел/запятая)",
|
||||
"blockedIps": "Заблокированные IP (Разделитель запятая/новая строка)",
|
||||
"blockedEmails": "Заблокированные Email (Разделитель запятая/новая строка)",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "Функции",
|
||||
"articleLike": "Включить Лайки Статей",
|
||||
"articleLikeHint": "Кнопка лайка над комментариями.",
|
||||
"commentLike": "Включить Лайки Комментариев",
|
||||
"commentLikeHint": "Кнопка лайка у каждого комментария.",
|
||||
"imageLightbox": "Лайтбокс Изображений",
|
||||
"imageLightboxHint": "Полноэкранный просмотр изображений.",
|
||||
"placeholder": "Текст Плейсхолдера",
|
||||
"placeholderHint": "Текст подсказки в поле ввода.",
|
||||
"widgetLanguage": "Язык Виджета",
|
||||
"widgetLanguageHint": "Язык фронтенд виджета.",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "Email Уведомления",
|
||||
"enable": "Включить Email Уведомления",
|
||||
"smtpTitle": "1. Настройки SMTP",
|
||||
"provider": "Провайдер",
|
||||
"host": "SMTP Хост",
|
||||
"port": "SMTP Порт",
|
||||
"secure": "SSL Безопасность",
|
||||
"user": "Email Пользователь",
|
||||
"pass": "Пароль/Токен",
|
||||
"qqHint": "Для QQ Mail используйте токен приложения.",
|
||||
"163Hint": "Для 163 Mail используйте токен приложения.",
|
||||
"templateTitle": "2. Настройки Шаблонов",
|
||||
"adminTemplate": "Шаблон Админа (HTML)",
|
||||
"adminTemplateHint": "Перем: ${commentAuthor}, ${postTitle}, ${postUrl}, ${commentContent}",
|
||||
"replyTemplate": "Шаблон Ответа (HTML)",
|
||||
"replyTemplateHint": "Перем: ${toName}, ${replyAuthor}, ${postTitle}, ${postUrl}, ${parentComment}, ${replyContent}",
|
||||
"testBtn": "Отправить Тест",
|
||||
"testingBtn": "Отправка...",
|
||||
"resetBtn": "Сбросить Шаблоны",
|
||||
"save": "Сохранить Конфиг",
|
||||
"saving": "Сохранение..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram Уведомления",
|
||||
"enable": "Включить Telegram Уведомления",
|
||||
"botToken": "Токен Бота",
|
||||
"botTokenHint": "Получить у @BotFather",
|
||||
"chatId": "ID Чата",
|
||||
"chatIdHint": "ID Пользователя или Группы. Исп. @userinfobot.",
|
||||
"webhookBtn": "Установить Вебхук",
|
||||
"webhookSetting": "Настройка...",
|
||||
"testBtn": "Отправить Тест",
|
||||
"testingBtn": "Отправка...",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение..."
|
||||
},
|
||||
"display": {
|
||||
"title": "Настройки Отображения",
|
||||
"layoutTitle": "Заголовок Админки",
|
||||
"layoutTitleHint": "Отображается в верхней панели.",
|
||||
"adminLanguage": "Язык Админки",
|
||||
"adminLanguageHint": "Язык панели администратора.",
|
||||
"save": "Сохранить",
|
||||
"saving": "Сохранение..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "Сохранено",
|
||||
"saveFailed": "Ошибка Сохранения",
|
||||
"loading": "Загрузка..."
|
||||
}
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/zh-CN.json
Normal file
304
cwd-admin/src/locales/zh-CN.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "评论管理",
|
||||
"stats": "数据看板",
|
||||
"analytics": "访问统计",
|
||||
"settings": "网站设置",
|
||||
"data": "数据管理"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "切换菜单",
|
||||
"docs": "使用文档",
|
||||
"logout": "退出",
|
||||
"moreActions": "更多操作",
|
||||
"defaultSite": "默认站点",
|
||||
"theme": {
|
||||
"light": "明亮模式",
|
||||
"dark": "暗黑模式",
|
||||
"system": "跟随系统"
|
||||
},
|
||||
"version": {
|
||||
"title": "版本信息",
|
||||
"apiAddress": "API 地址",
|
||||
"apiVersion": "接口版本",
|
||||
"adminVersion": "后台版本",
|
||||
"match": "当前后台与接口版本一致,可以正常使用。",
|
||||
"mismatch": "当前后台与接口版本不一致,推荐将 API 服务更新到与后台版本一致,以避免潜在的兼容性问题。",
|
||||
"fetchError": "无法获取接口版本:",
|
||||
"loading": "加载中...",
|
||||
"notConfigured": "未配置",
|
||||
"notFetched": "未获取到",
|
||||
"ok": "我知道了"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "数据看板",
|
||||
"overview": "整体概览",
|
||||
"total": "总评论数",
|
||||
"approved": "已通过",
|
||||
"pending": "待审核",
|
||||
"rejected": "已拒绝",
|
||||
"trend": "评论数趋势",
|
||||
"bySite": "按站点统计",
|
||||
"last7Days": "最近 7 天",
|
||||
"last30Days": "最近 30 天",
|
||||
"noData": "暂无评论数据",
|
||||
"table": {
|
||||
"domain": "域名",
|
||||
"total": "总数",
|
||||
"approved": "已通过",
|
||||
"pending": "待审核",
|
||||
"rejected": "已拒绝"
|
||||
},
|
||||
"loadError": "加载统计数据失败"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "访问统计",
|
||||
"overview": "整体概览",
|
||||
"totalPv": "全站总访问量",
|
||||
"todayPv": "今日访问量",
|
||||
"weekPv": "本周访问量",
|
||||
"monthPv": "本月访问量",
|
||||
"totalPages": "有访问记录的页面数",
|
||||
"trend": "访问趋势",
|
||||
"pageDetail": "页面访问明细",
|
||||
"likeRank": "点赞页面排行榜",
|
||||
"last7Days": "最近 7 天",
|
||||
"last30Days": "最近 30 天",
|
||||
"sort": {
|
||||
"pv": "按 PV 排序",
|
||||
"latest": "最新访问"
|
||||
},
|
||||
"table": {
|
||||
"title": "页面标题",
|
||||
"pv": "访问量",
|
||||
"time": "最后访问时间",
|
||||
"url": "页面地址",
|
||||
"rank": "排名",
|
||||
"like": "点赞数"
|
||||
},
|
||||
"noData": "暂无访问数据",
|
||||
"noLikeData": "暂无点赞数据",
|
||||
"loadError": "加载访问统计数据失败"
|
||||
},
|
||||
"data": {
|
||||
"title": "数据管理",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "评论数据",
|
||||
"desc": "管理评论内容,支持从其他评论框架迁移数据。",
|
||||
"exportLabel": "导出:",
|
||||
"exporting": "导出中...",
|
||||
"exportJson": "导出 JSON",
|
||||
"importLabel": "导入:",
|
||||
"importButton": "导入评论",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "系统配置",
|
||||
"desc": "管理后台设置、邮件配置、黑名单等。",
|
||||
"export": "导出配置",
|
||||
"import": "导入配置"
|
||||
},
|
||||
"stats": {
|
||||
"title": "访问统计",
|
||||
"desc": "管理文章访问量、点赞数及每日访问趋势。",
|
||||
"export": "导出统计",
|
||||
"import": "导入统计"
|
||||
},
|
||||
"backup": {
|
||||
"title": "全量备份",
|
||||
"desc": "一键备份或恢复系统所有数据(评论 + 配置 + 统计)。",
|
||||
"export": "全量导出",
|
||||
"import": "全量恢复"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "操作日志"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "检测到 URL 缺失前缀",
|
||||
"descPart1": "检测到 ",
|
||||
"descPart2": " 条评论的 URL 不存在域名前缀(http/https)。",
|
||||
"descPart3": "是否在导入时统一添加?",
|
||||
"label": "域名前缀 (例如 https://example.me)",
|
||||
"placeholder": "请输入域名前缀",
|
||||
"skip": "直接导入 (不添加)",
|
||||
"confirm": "添加并导入"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "导出成功",
|
||||
"exportFailed": "导出失败",
|
||||
"fileReadFailed": "读取文件失败",
|
||||
"jsonParseFailed": "JSON 解析失败,请检查文件格式",
|
||||
"importConfigSuccess": "配置导入成功",
|
||||
"importStatsSuccess": "统计数据导入成功",
|
||||
"importBackupSuccess": "全量恢复成功",
|
||||
"importCommentsSuccess": "评论导入成功",
|
||||
"prefixRequired": "请输入域名前缀",
|
||||
"importStart": "开始导入: {name} (模式: {mode})",
|
||||
"fileParseSuccess": "文件解析成功,开始处理...",
|
||||
"errorWithMessage": "错误: {msg}",
|
||||
"parsedCommentsCount": "解析到 {count} 条评论数据",
|
||||
"detectMissingPrefix": "检测到 {count} 条 URL 缺失前缀,等待用户确认...",
|
||||
"prefixAdded": "已添加前缀,继续导入...",
|
||||
"skipPrefix": "用户跳过前缀添加",
|
||||
"readFileFailedLog": "读取文件失败",
|
||||
"importCommentsDone": "导入完成: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "评论管理",
|
||||
"statusFilter": {
|
||||
"all": "全部状态",
|
||||
"approved": "已通过",
|
||||
"pending": "待审核",
|
||||
"rejected": "已拒绝"
|
||||
},
|
||||
"refresh": "刷新",
|
||||
"table": {
|
||||
"author": "用户",
|
||||
"content": "评论信息",
|
||||
"path": "评论地址",
|
||||
"status": "状态",
|
||||
"actions": "操作",
|
||||
"admin": "网站管理员",
|
||||
"time": "时间",
|
||||
"ip": "IP",
|
||||
"email": "邮箱"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "通过",
|
||||
"pending": "待审",
|
||||
"reject": "拒绝",
|
||||
"edit": "编辑",
|
||||
"delete": "删除",
|
||||
"blockIp": "屏蔽该 IP",
|
||||
"blockEmail": "屏蔽该邮箱",
|
||||
"pin": "置顶"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "上一页",
|
||||
"next": "下一页",
|
||||
"jumpTo": "跳转到",
|
||||
"page": "页",
|
||||
"confirm": "确定"
|
||||
},
|
||||
"confirmDelete": "确认删除评论 {id} 吗",
|
||||
"confirmBlockIp": "确认将 IP {ip} 加入黑名单吗?",
|
||||
"confirmBlockEmail": "确认将邮箱 {email} 加入黑名单吗?",
|
||||
"successBlockIp": "已加入 IP 黑名单",
|
||||
"successBlockEmail": "已加入邮箱黑名单",
|
||||
"empty": "暂无数据",
|
||||
"editModal": {
|
||||
"title": "编辑评论",
|
||||
"name": "访客昵称",
|
||||
"email": "访客邮箱",
|
||||
"url": "访客网址",
|
||||
"postSlug": "页面标识",
|
||||
"postUrl": "评论地址",
|
||||
"content": "评论内容",
|
||||
"status": "评论状态",
|
||||
"priority": "置顶权重(1 为不置顶,数值越大越靠前)",
|
||||
"cancel": "取消",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "网站设置",
|
||||
"tabs": {
|
||||
"comment": "评论与安全",
|
||||
"feature": "功能开关",
|
||||
"emailNotify": "邮箱提醒",
|
||||
"telegramNotify": "Telegram 通知",
|
||||
"display": "后台显示"
|
||||
},
|
||||
"comment": {
|
||||
"title": "评论显示配置",
|
||||
"adminEmail": "管理员邮箱",
|
||||
"adminBadge": "博主标签文字(留空使用默认图标)",
|
||||
"adminEnabled": "是否开启博主标签显示",
|
||||
"avatarPrefix": "头像前缀(默认:https://gravatar.com/avatar)",
|
||||
"securityTitle": "安全设置",
|
||||
"requireReview": "新评论是否审核后再显示",
|
||||
"adminKey": "管理员评论密钥(设置后前台使用管理员邮箱评论需输入此密钥。)",
|
||||
"adminKeyPlaceholder": "输入密钥以设置或修改",
|
||||
"allowedDomains": "允许调用的域名(设置后仅匹配域名可调用前台评论组件,留空则不限制。使用空格或者逗号进行分割。)",
|
||||
"blockedIps": "IP 黑名单(多个 IP 用逗号或换行分隔,留空则不限制)",
|
||||
"blockedEmails": "邮箱黑名单(多个邮箱用逗号或换行分隔,留空则不限制)",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "功能开关",
|
||||
"articleLike": "开启文章点赞功能",
|
||||
"articleLikeHint": "开启后,评论区顶部会显示的文章点赞(喜欢)按钮。",
|
||||
"commentLike": "开启评论点赞功能",
|
||||
"commentLikeHint": "开启后,评论列表中的每条评论都会显示点赞按钮。",
|
||||
"imageLightbox": "评论列表图片灯箱模式",
|
||||
"imageLightboxHint": "开启后,点击评论中的图片时会全屏放大预览。",
|
||||
"placeholder": "评论框提示文案 (Placeholder)",
|
||||
"placeholderHint": "自定义评论输入框的提示文字,支持换行。留空则使用默认值。",
|
||||
"widgetLanguage": "组件语言",
|
||||
"widgetLanguageHint": "设置前端评论组件显示的语言。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "通知邮箱设置",
|
||||
"enable": "开启邮件通知",
|
||||
"smtpTitle": "1. SMTP 发件配置",
|
||||
"provider": "邮件服务商",
|
||||
"host": "SMTP 服务器",
|
||||
"port": "SMTP 端口",
|
||||
"secure": "SSL 安全连接",
|
||||
"user": "发件邮箱账号",
|
||||
"pass": "授权码/密码",
|
||||
"qqHint": "注意:QQ 邮箱必须使用授权码,而非 QQ 密码。请登录 QQ 邮箱网页版,在【设置 - 账户】中开启 POP3/SMTP 服务并生成授权码。",
|
||||
"163Hint": "注意:163 邮箱必须使用授权码,而非登录密码。请登录 163 邮箱网页版,在【设置 - POP3/SMTP/IMAP】中开启服务并生成授权码。",
|
||||
"templateTitle": "2. 邮件模板设置",
|
||||
"adminTemplate": "管理员通知模板 (HTML)",
|
||||
"adminTemplateHint": "可用变量:${commentAuthor} (评论人昵称), ${postTitle} (文章标题), ${postUrl} (文章链接), ${commentContent} (评论内容)",
|
||||
"replyTemplate": "回复通知模板 (HTML)",
|
||||
"replyTemplateHint": "可用变量:${toName} (接收人昵称), ${replyAuthor} (回复人昵称), ${postTitle} (文章标题), ${postUrl} (文章链接), ${parentComment} (原评论), ${replyContent} (回复内容)",
|
||||
"testBtn": "发送测试邮件",
|
||||
"testingBtn": "发送中...",
|
||||
"resetBtn": "恢复默认模板",
|
||||
"save": "保存配置",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram 通知设置",
|
||||
"enable": "开启 Telegram 通知",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "在 Telegram 中搜索 @BotFather 创建机器人获取 Token",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "这是接收通知的用户 ID 或群组 ID。可以先给机器人发消息,然后通过 API 获取 ID,或者使用 @userinfobot 查询。",
|
||||
"webhookBtn": "一键设置 Webhook",
|
||||
"webhookSetting": "设置中...",
|
||||
"testBtn": "发送测试消息",
|
||||
"testingBtn": "发送中...",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"display": {
|
||||
"title": "后台显示设置",
|
||||
"layoutTitle": "后台标题",
|
||||
"layoutTitleHint": "显示在后台顶部导航栏左侧。",
|
||||
"adminLanguage": "后台语言",
|
||||
"adminLanguageHint": "设置后台管理系统的显示语言。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "保存成功",
|
||||
"saveFailed": "保存失败",
|
||||
"loading": "加载中..."
|
||||
}
|
||||
}
|
||||
304
cwd-admin/src/locales/zh-TW.json
Normal file
304
cwd-admin/src/locales/zh-TW.json
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
"menu": {
|
||||
"comments": "評論管理",
|
||||
"stats": "數據看板",
|
||||
"analytics": "訪問統計",
|
||||
"settings": "網站設置",
|
||||
"data": "數據管理"
|
||||
},
|
||||
"layout": {
|
||||
"toggleMenu": "切換菜單",
|
||||
"docs": "使用文檔",
|
||||
"logout": "退出",
|
||||
"moreActions": "更多操作",
|
||||
"defaultSite": "默認站點",
|
||||
"theme": {
|
||||
"light": "明亮模式",
|
||||
"dark": "暗黑模式",
|
||||
"system": "跟隨系統"
|
||||
},
|
||||
"version": {
|
||||
"title": "版本信息",
|
||||
"apiAddress": "API 地址",
|
||||
"apiVersion": "接口版本",
|
||||
"adminVersion": "後台版本",
|
||||
"match": "當前後台與接口版本一致,可以正常使用。",
|
||||
"mismatch": "當前後台與接口版本不一致,推薦將 API 服務更新到與後台版本一致,以避免潛在的兼容性問題。",
|
||||
"fetchError": "無法獲取接口版本:",
|
||||
"loading": "加載中...",
|
||||
"notConfigured": "未配置",
|
||||
"notFetched": "未獲取到",
|
||||
"ok": "我知道了"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
"title": "數據看板",
|
||||
"overview": "整體概覽",
|
||||
"total": "總評論數",
|
||||
"approved": "已通過",
|
||||
"pending": "待審核",
|
||||
"rejected": "已拒絕",
|
||||
"trend": "評論數趨勢",
|
||||
"bySite": "按站點統計",
|
||||
"last7Days": "最近 7 天",
|
||||
"last30Days": "最近 30 天",
|
||||
"noData": "暫無評論數據",
|
||||
"table": {
|
||||
"domain": "域名",
|
||||
"total": "總數",
|
||||
"approved": "已通過",
|
||||
"pending": "待審核",
|
||||
"rejected": "已拒絕"
|
||||
},
|
||||
"loadError": "加載統計數據失敗"
|
||||
},
|
||||
"analytics": {
|
||||
"title": "訪問統計",
|
||||
"overview": "整體概覽",
|
||||
"totalPv": "全站總訪問量",
|
||||
"todayPv": "今日訪問量",
|
||||
"weekPv": "本週訪問量",
|
||||
"monthPv": "本月訪問量",
|
||||
"totalPages": "有訪問記錄的頁面數",
|
||||
"trend": "訪問趨勢",
|
||||
"pageDetail": "頁面訪問明細",
|
||||
"likeRank": "點贊頁面排行榜",
|
||||
"last7Days": "最近 7 天",
|
||||
"last30Days": "最近 30 天",
|
||||
"sort": {
|
||||
"pv": "按 PV 排序",
|
||||
"latest": "最新訪問"
|
||||
},
|
||||
"table": {
|
||||
"title": "頁面標題",
|
||||
"pv": "訪問量",
|
||||
"time": "最後訪問時間",
|
||||
"url": "頁面地址",
|
||||
"rank": "排名",
|
||||
"like": "點贊數"
|
||||
},
|
||||
"noData": "暫無訪問數據",
|
||||
"noLikeData": "暫無點贊數據",
|
||||
"loadError": "加載訪問統計數據失敗"
|
||||
},
|
||||
"data": {
|
||||
"title": "數據管理",
|
||||
"sections": {
|
||||
"comments": {
|
||||
"title": "評論數據",
|
||||
"desc": "管理評論內容,支持從其他評論框架遷移數據。",
|
||||
"exportLabel": "導出:",
|
||||
"exporting": "導出中...",
|
||||
"exportJson": "導出 JSON",
|
||||
"importLabel": "導入:",
|
||||
"importButton": "導入評論",
|
||||
"source": {
|
||||
"cwd": "CWD (.json)",
|
||||
"twikoo": "Twikoo (.json)",
|
||||
"artalk": "Artalk (.json)"
|
||||
}
|
||||
},
|
||||
"config": {
|
||||
"title": "系統配置",
|
||||
"desc": "管理後台設置、郵件配置、黑名單等。",
|
||||
"export": "導出配置",
|
||||
"import": "導入配置"
|
||||
},
|
||||
"stats": {
|
||||
"title": "訪問統計",
|
||||
"desc": "管理文章訪問量、點贊數及每日訪問趨勢。",
|
||||
"export": "導出統計",
|
||||
"import": "導入統計"
|
||||
},
|
||||
"backup": {
|
||||
"title": "全量備份",
|
||||
"desc": "一鍵備份或恢復系統所有數據(評論 + 配置 + 統計)。",
|
||||
"export": "全量導出",
|
||||
"import": "全量恢復"
|
||||
}
|
||||
},
|
||||
"logs": {
|
||||
"title": "操作日誌"
|
||||
},
|
||||
"prefixModal": {
|
||||
"title": "檢測到 URL 缺失前綴",
|
||||
"descPart1": "檢測到 ",
|
||||
"descPart2": " 條評論的 URL 不存在域名前綴(http/https)。",
|
||||
"descPart3": "是否在導入時統一添加?",
|
||||
"label": "域名前綴 (例如 https://example.me)",
|
||||
"placeholder": "請輸入域名前綴",
|
||||
"skip": "直接導入 (不添加)",
|
||||
"confirm": "添加並導入"
|
||||
},
|
||||
"messages": {
|
||||
"exportSuccess": "導出成功",
|
||||
"exportFailed": "導出失敗",
|
||||
"fileReadFailed": "讀取文件失敗",
|
||||
"jsonParseFailed": "JSON 解析失敗,請檢查文件格式",
|
||||
"importConfigSuccess": "配置導入成功",
|
||||
"importStatsSuccess": "統計數據導入成功",
|
||||
"importBackupSuccess": "全量恢復成功",
|
||||
"importCommentsSuccess": "評論導入成功",
|
||||
"prefixRequired": "請輸入域名前綴",
|
||||
"importStart": "開始導入: {name} (模式: {mode})",
|
||||
"fileParseSuccess": "文件解析成功,開始處理...",
|
||||
"errorWithMessage": "錯誤: {msg}",
|
||||
"parsedCommentsCount": "解析到 {count} 條評論數據",
|
||||
"detectMissingPrefix": "檢測到 {count} 條 URL 缺失前綴,等待用戶確認...",
|
||||
"prefixAdded": "已添加前綴,繼續導入...",
|
||||
"skipPrefix": "用戶跳過前綴添加",
|
||||
"readFileFailedLog": "讀取文件失敗",
|
||||
"importCommentsDone": "導入完成: {message}"
|
||||
}
|
||||
},
|
||||
"comments": {
|
||||
"title": "評論管理",
|
||||
"statusFilter": {
|
||||
"all": "全部狀態",
|
||||
"approved": "已通過",
|
||||
"pending": "待審核",
|
||||
"rejected": "已拒絕"
|
||||
},
|
||||
"refresh": "刷新",
|
||||
"table": {
|
||||
"author": "用戶",
|
||||
"content": "評論信息",
|
||||
"path": "評論地址",
|
||||
"status": "狀態",
|
||||
"actions": "操作",
|
||||
"admin": "網站管理員",
|
||||
"time": "時間",
|
||||
"ip": "IP",
|
||||
"email": "郵箱"
|
||||
},
|
||||
"actions": {
|
||||
"approve": "通過",
|
||||
"pending": "待審",
|
||||
"reject": "拒絕",
|
||||
"edit": "編輯",
|
||||
"delete": "刪除",
|
||||
"blockIp": "屏蔽該 IP",
|
||||
"blockEmail": "屏蔽該郵箱",
|
||||
"pin": "置頂"
|
||||
},
|
||||
"pagination": {
|
||||
"prev": "上一頁",
|
||||
"next": "下一頁",
|
||||
"jumpTo": "跳轉到",
|
||||
"page": "頁",
|
||||
"confirm": "確定"
|
||||
},
|
||||
"confirmDelete": "確認刪除評論 {id} 嗎",
|
||||
"confirmBlockIp": "確認將 IP {ip} 加入黑名單嗎?",
|
||||
"confirmBlockEmail": "確認將郵箱 {email} 加入黑名單嗎?",
|
||||
"successBlockIp": "已加入 IP 黑名單",
|
||||
"successBlockEmail": "已加入郵箱黑名單",
|
||||
"empty": "暫無數據",
|
||||
"editModal": {
|
||||
"title": "編輯評論",
|
||||
"name": "訪客暱稱",
|
||||
"email": "訪客郵箱",
|
||||
"url": "訪客網址",
|
||||
"postSlug": "頁面標識",
|
||||
"postUrl": "評論地址",
|
||||
"content": "評論內容",
|
||||
"status": "評論狀態",
|
||||
"priority": "置頂權重(1 為不置頂,數值越大越靠前)",
|
||||
"cancel": "取消",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
}
|
||||
},
|
||||
"settings": {
|
||||
"title": "網站設置",
|
||||
"tabs": {
|
||||
"comment": "評論與安全",
|
||||
"feature": "功能開關",
|
||||
"emailNotify": "郵箱提醒",
|
||||
"telegramNotify": "Telegram 通知",
|
||||
"display": "後台顯示"
|
||||
},
|
||||
"comment": {
|
||||
"title": "評論顯示配置",
|
||||
"adminEmail": "管理員郵箱",
|
||||
"adminBadge": "博主標籤文字(留空使用默認圖標)",
|
||||
"adminEnabled": "是否開啟博主標籤顯示",
|
||||
"avatarPrefix": "頭像前綴(默認:https://gravatar.com/avatar)",
|
||||
"securityTitle": "安全設置",
|
||||
"requireReview": "新評論是否審核後再顯示",
|
||||
"adminKey": "管理員評論密鑰(設置後前台使用管理員郵箱評論需輸入此密鑰。)",
|
||||
"adminKeyPlaceholder": "輸入密鑰以設置或修改",
|
||||
"allowedDomains": "允許調用的域名(設置後僅匹配域名可調用前台評論組件,留空則不限制。使用空格或者逗號進行分割。)",
|
||||
"blockedIps": "IP 黑名單(多個 IP 用逗號或換行分隔,留空則不限制)",
|
||||
"blockedEmails": "郵箱黑名單(多個郵箱用逗號或換行分隔,留空則不限制)",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"feature": {
|
||||
"title": "功能開關",
|
||||
"articleLike": "開啟文章點贊功能",
|
||||
"articleLikeHint": "開啟後,評論區頂部會顯示的文章點贊(喜歡)按鈕。",
|
||||
"commentLike": "開啟評論點贊功能",
|
||||
"commentLikeHint": "開啟後,評論列表中的每條評論都會顯示點贊按鈕。",
|
||||
"imageLightbox": "評論列表圖片灯箱模式",
|
||||
"imageLightboxHint": "開啟後,點擊評論中的圖片時會全屏放大預覽。",
|
||||
"placeholder": "評論框提示文案 (Placeholder)",
|
||||
"placeholderHint": "自定義評論輸入框的提示文字,支持換行。留空則使用默認值。",
|
||||
"widgetLanguage": "組件語言",
|
||||
"widgetLanguageHint": "設置前端評論組件顯示的語言。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"emailNotify": {
|
||||
"title": "通知郵箱設置",
|
||||
"enable": "開啟郵件通知",
|
||||
"smtpTitle": "1. SMTP 發件配置",
|
||||
"provider": "郵件服務商",
|
||||
"host": "SMTP 服務器",
|
||||
"port": "SMTP 端口",
|
||||
"secure": "SSL 安全連接",
|
||||
"user": "發件郵箱賬號",
|
||||
"pass": "授權碼/密碼",
|
||||
"qqHint": "注意:QQ 郵箱必須使用授權碼,而非 QQ 密碼。請登錄 QQ 郵箱網頁版,在【設置 - 賬戶】中開啟 POP3/SMTP 服務並生成授權碼。",
|
||||
"163Hint": "注意:163 郵箱必須使用授權碼,而非登錄密碼。請登錄 163 郵箱網頁版,在【設置 - POP3/SMTP/IMAP】中開啟服務並生成授權碼。",
|
||||
"templateTitle": "2. 郵件模板設置",
|
||||
"adminTemplate": "管理員通知模板 (HTML)",
|
||||
"adminTemplateHint": "可用變量:${commentAuthor} (評論人暱稱), ${postTitle} (文章標題), ${postUrl} (文章鏈接), ${commentContent} (評論內容)",
|
||||
"replyTemplate": "回覆通知模板 (HTML)",
|
||||
"replyTemplateHint": "可用變量:${toName} (接收人暱稱), ${replyAuthor} (回覆人暱稱), ${postTitle} (文章標題), ${postUrl} (文章鏈接), ${parentComment} (原評論), ${replyContent} (回覆內容)",
|
||||
"testBtn": "發送測試郵件",
|
||||
"testingBtn": "發送中...",
|
||||
"resetBtn": "恢復默認模板",
|
||||
"save": "保存配置",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"telegramNotify": {
|
||||
"title": "Telegram 通知設置",
|
||||
"enable": "開啟 Telegram 通知",
|
||||
"botToken": "Bot Token",
|
||||
"botTokenHint": "在 Telegram 中搜索 @BotFather 創建機器人獲取 Token",
|
||||
"chatId": "Chat ID",
|
||||
"chatIdHint": "這是接收通知的用戶 ID 或群組 ID。可以先給機器人發消息,然後通過 API 獲取 ID,或者使用 @userinfobot 查詢。",
|
||||
"webhookBtn": "一鍵設置 Webhook",
|
||||
"webhookSetting": "設置中...",
|
||||
"testBtn": "發送測試消息",
|
||||
"testingBtn": "發送中...",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"display": {
|
||||
"title": "後台顯示設置",
|
||||
"layoutTitle": "後台標題",
|
||||
"layoutTitleHint": "顯示在後台頂部導航欄左側。",
|
||||
"adminLanguage": "後台語言",
|
||||
"adminLanguageHint": "設置後台管理系統的顯示語言。",
|
||||
"save": "保存",
|
||||
"saving": "保存中..."
|
||||
},
|
||||
"common": {
|
||||
"saveSuccess": "保存成功",
|
||||
"saveFailed": "保存失敗",
|
||||
"loading": "加載中..."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import { createApp } from 'vue';
|
||||
import App from './App.vue';
|
||||
import { router } from './router';
|
||||
import i18n from './i18n';
|
||||
|
||||
import PhosphorIcons from '@phosphor-icons/vue';
|
||||
|
||||
@@ -9,5 +10,6 @@ import './styles/common.less';
|
||||
|
||||
const app = createApp(App);
|
||||
app.use(router);
|
||||
app.use(i18n);
|
||||
app.use(PhosphorIcons);
|
||||
app.mount('#app');
|
||||
|
||||
@@ -157,6 +157,12 @@
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.menu-item span {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.menu-item-icon {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
@@ -307,4 +313,4 @@
|
||||
.layout-actions-item-danger:hover {
|
||||
background-color: rgba(209, 36, 47, 0.1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div style="display: flex; align-items: center; gap: 20px">
|
||||
<h2 class="page-title">访问统计</h2>
|
||||
<h2 class="page-title">{{ t('analytics.title') }}</h2>
|
||||
</div>
|
||||
<div
|
||||
v-if="toastVisible"
|
||||
@@ -13,18 +13,18 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">整体概览</h3>
|
||||
<h3 class="card-title">{{ t('analytics.overview') }}</h3>
|
||||
</div>
|
||||
<div v-if="loading" class="page-hint">加载中...</div>
|
||||
<div v-if="loading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="error" class="page-error">{{ error }}</div>
|
||||
<div v-else>
|
||||
<div class="stats-grid">
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">全站总访问量</div>
|
||||
<div class="stats-label">{{ t('analytics.totalPv') }}</div>
|
||||
<div class="stats-value"><CountTo :end-val="overview.totalPv" /></div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">今日访问量</div>
|
||||
<div class="stats-label">{{ t('analytics.todayPv') }}</div>
|
||||
<div class="stats-value">
|
||||
<CountTo :end-val="overview.todayPv" />
|
||||
<span
|
||||
@@ -39,7 +39,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">本周访问量</div>
|
||||
<div class="stats-label">{{ t('analytics.weekPv') }}</div>
|
||||
<div class="stats-value">
|
||||
<CountTo :end-val="overview.weekPv" />
|
||||
<span
|
||||
@@ -54,7 +54,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">本月访问量</div>
|
||||
<div class="stats-label">{{ t('analytics.monthPv') }}</div>
|
||||
<div class="stats-value">
|
||||
<CountTo :end-val="overview.monthPv" />
|
||||
<span
|
||||
@@ -69,7 +69,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">有访问记录的页面数</div>
|
||||
<div class="stats-label">{{ t('analytics.totalPages') }}</div>
|
||||
<div class="stats-value"><CountTo :end-val="overview.totalPages" /></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,7 +78,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">访问趋势</h3>
|
||||
<h3 class="card-title">{{ t('analytics.trend') }}</h3>
|
||||
<div class="visit-tabs">
|
||||
<button
|
||||
class="visit-tab"
|
||||
@@ -86,7 +86,7 @@
|
||||
type="button"
|
||||
@click="changeChartRange('7')"
|
||||
>
|
||||
最近 7 天
|
||||
{{ t('analytics.last7Days') }}
|
||||
</button>
|
||||
<button
|
||||
class="visit-tab"
|
||||
@@ -94,11 +94,11 @@
|
||||
type="button"
|
||||
@click="changeChartRange('30')"
|
||||
>
|
||||
最近 30 天
|
||||
{{ t('analytics.last30Days') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="page-hint">加载中...</div>
|
||||
<div v-if="loading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="error" class="page-error">{{ error }}</div>
|
||||
<div class="chart-wrapper">
|
||||
<div ref="chartEl" class="chart"></div>
|
||||
@@ -107,7 +107,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">页面访问明细</h3>
|
||||
<h3 class="card-title">{{ t('analytics.pageDetail') }}</h3>
|
||||
<div class="visit-tabs">
|
||||
<button
|
||||
class="visit-tab"
|
||||
@@ -115,7 +115,7 @@
|
||||
type="button"
|
||||
@click="changeVisitTab('pv')"
|
||||
>
|
||||
按 PV 排序
|
||||
{{ t('analytics.sort.pv') }}
|
||||
</button>
|
||||
<button
|
||||
class="visit-tab"
|
||||
@@ -123,20 +123,20 @@
|
||||
type="button"
|
||||
@click="changeVisitTab('latest')"
|
||||
>
|
||||
最新访问
|
||||
{{ t('analytics.sort.latest') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="listLoading" class="page-hint">加载中...</div>
|
||||
<div v-if="listLoading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="error" class="page-error">{{ error }}</div>
|
||||
<div v-else-if="items.length === 0" class="page-hint">暂无访问数据</div>
|
||||
<div v-else-if="items.length === 0" class="page-hint">{{ t('analytics.noData') }}</div>
|
||||
<div v-else class="domain-table-wrapper">
|
||||
<div class="domain-table">
|
||||
<div class="domain-table-header">
|
||||
<div class="domain-cell domain-cell-title">页面标题</div>
|
||||
<div class="domain-cell domain-cell-pv">访问量</div>
|
||||
<div class="domain-cell domain-cell-time">最后访问时间</div>
|
||||
<div class="domain-cell domain-cell-url">页面地址</div>
|
||||
<div class="domain-cell domain-cell-title">{{ t('analytics.table.title') }}</div>
|
||||
<div class="domain-cell domain-cell-pv">{{ t('analytics.table.pv') }}</div>
|
||||
<div class="domain-cell domain-cell-time">{{ t('analytics.table.time') }}</div>
|
||||
<div class="domain-cell domain-cell-url">{{ t('analytics.table.url') }}</div>
|
||||
</div>
|
||||
<div v-for="item in items" :key="item.postSlug" class="domain-table-row">
|
||||
<div class="domain-cell domain-cell-title">
|
||||
@@ -166,18 +166,18 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">点赞页面排行榜</h3>
|
||||
<h3 class="card-title">{{ t('analytics.likeRank') }}</h3>
|
||||
</div>
|
||||
<div v-if="loading" class="page-hint">加载中...</div>
|
||||
<div v-if="loading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="error" class="page-error">{{ error }}</div>
|
||||
<div v-else-if="likeStatsItems.length === 0" class="page-hint">暂无点赞数据</div>
|
||||
<div v-else-if="likeStatsItems.length === 0" class="page-hint">{{ t('analytics.noLikeData') }}</div>
|
||||
<div v-else class="domain-table-wrapper">
|
||||
<div class="domain-table">
|
||||
<div class="domain-table-header">
|
||||
<div class="domain-cell domain-cell-rank">排名</div>
|
||||
<div class="domain-cell domain-cell-title">页面标题</div>
|
||||
<div class="domain-cell domain-cell-like">点赞数</div>
|
||||
<div class="domain-cell domain-cell-url">页面地址</div>
|
||||
<div class="domain-cell domain-cell-rank">{{ t('analytics.table.rank') }}</div>
|
||||
<div class="domain-cell domain-cell-title">{{ t('analytics.table.title') }}</div>
|
||||
<div class="domain-cell domain-cell-like">{{ t('analytics.table.like') }}</div>
|
||||
<div class="domain-cell domain-cell-url">{{ t('analytics.table.url') }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="(item, index) in likeStatsItems"
|
||||
@@ -214,6 +214,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onBeforeUnmount, ref, nextTick, watch, inject, computed } from "vue";
|
||||
import type { Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import * as echarts from "echarts";
|
||||
import CountTo from "../../components/CountTo.vue";
|
||||
import {
|
||||
@@ -226,6 +227,8 @@ import {
|
||||
} from "../../api/admin";
|
||||
import { useSite } from "../../composables/useSite";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const loading = ref(false);
|
||||
const listLoading = ref(false);
|
||||
const error = ref("");
|
||||
|
||||
@@ -1,42 +1,42 @@
|
||||
<template>
|
||||
<div v-if="visible" class="modal-overlay">
|
||||
<div class="modal">
|
||||
<h3 class="modal-title">编辑评论</h3>
|
||||
<h3 class="modal-title">{{ t('comments.editModal.title') }}</h3>
|
||||
<div v-if="form" class="modal-body">
|
||||
<div class="form-item">
|
||||
<label class="form-label">访客昵称</label>
|
||||
<label class="form-label">{{ t('comments.editModal.name') }}</label>
|
||||
<input v-model="form.name" class="form-input" type="text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">访客邮箱</label>
|
||||
<label class="form-label">{{ t('comments.editModal.email') }}</label>
|
||||
<input v-model="form.email" class="form-input" type="email" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">访客网址</label>
|
||||
<label class="form-label">{{ t('comments.editModal.url') }}</label>
|
||||
<input v-model="form.url" class="form-input" type="text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">页面标识</label>
|
||||
<label class="form-label">{{ t('comments.editModal.postSlug') }}</label>
|
||||
<input v-model="form.postSlug" class="form-input" type="text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">评论地址</label>
|
||||
<label class="form-label">{{ t('comments.editModal.postUrl') }}</label>
|
||||
<input v-model="form.postUrl" class="form-input" type="text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">评论内容</label>
|
||||
<label class="form-label">{{ t('comments.editModal.content') }}</label>
|
||||
<textarea v-model="form.contentText" class="form-input" rows="4"></textarea>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">评论状态</label>
|
||||
<label class="form-label">{{ t('comments.editModal.status') }}</label>
|
||||
<select v-model="form.status" class="form-input">
|
||||
<option value="approved">已通过</option>
|
||||
<option value="pending">待审核</option>
|
||||
<option value="rejected">已拒绝</option>
|
||||
<option value="approved">{{ t('comments.statusFilter.approved') }}</option>
|
||||
<option value="pending">{{ t('comments.statusFilter.pending') }}</option>
|
||||
<option value="rejected">{{ t('comments.statusFilter.rejected') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">置顶权重(1 为不置顶,数值越大越靠前)</label>
|
||||
<label class="form-label">{{ t('comments.editModal.priority') }}</label>
|
||||
<input
|
||||
v-model.number="form.priority"
|
||||
class="form-input"
|
||||
@@ -47,7 +47,7 @@
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="modal-btn secondary" type="button" @click="handleClose">
|
||||
取消
|
||||
{{ t('comments.editModal.cancel') }}
|
||||
</button>
|
||||
<button
|
||||
class="modal-btn primary"
|
||||
@@ -55,8 +55,8 @@
|
||||
:disabled="saving"
|
||||
@click="handleSubmit"
|
||||
>
|
||||
<span v-if="saving">保存中...</span>
|
||||
<span v-else>保存</span>
|
||||
<span v-if="saving">{{ t('comments.editModal.saving') }}</span>
|
||||
<span v-else>{{ t('comments.editModal.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -64,6 +64,10 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from "vue-i18n";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
interface EditForm {
|
||||
id: number;
|
||||
name: string;
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<h2 class="page-title">评论管理</h2>
|
||||
<h2 class="page-title">{{ t('comments.title') }}</h2>
|
||||
<div class="toolbar">
|
||||
<div class="toolbar-left">
|
||||
<select v-model="statusFilter" class="toolbar-select">
|
||||
<option value="">全部状态</option>
|
||||
<option value="approved">已通过</option>
|
||||
<option value="pending">待审核</option>
|
||||
<option value="rejected">已拒绝</option>
|
||||
<option value="">{{ t('comments.statusFilter.all') }}</option>
|
||||
<option value="approved">{{ t('comments.statusFilter.approved') }}</option>
|
||||
<option value="pending">{{ t('comments.statusFilter.pending') }}</option>
|
||||
<option value="rejected">{{ t('comments.statusFilter.rejected') }}</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="toolbar-right">
|
||||
<button class="toolbar-button" @click="goPage(1)">刷新</button>
|
||||
<button class="toolbar-button" @click="goPage(1)">{{ t('comments.refresh') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="loading" class="page-hint">加载中...</div>
|
||||
<div v-if="loading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="error" class="page-error">{{ error }}</div>
|
||||
<div v-else>
|
||||
<div class="comment-table">
|
||||
<div class="table-header">
|
||||
<div class="table-cell table-cell-author">用户</div>
|
||||
<div class="table-cell table-cell-content">评论信息</div>
|
||||
<div class="table-cell table-cell-path">评论地址</div>
|
||||
<div class="table-cell table-cell-status">状态</div>
|
||||
<div class="table-cell table-cell-actions">操作</div>
|
||||
<div class="table-cell table-cell-author">{{ t('comments.table.author') }}</div>
|
||||
<div class="table-cell table-cell-content">{{ t('comments.table.content') }}</div>
|
||||
<div class="table-cell table-cell-path">{{ t('comments.table.path') }}</div>
|
||||
<div class="table-cell table-cell-status">{{ t('comments.table.status') }}</div>
|
||||
<div class="table-cell table-cell-actions">{{ t('comments.table.actions') }}</div>
|
||||
</div>
|
||||
<div v-for="item in filteredComments" :key="item.id" class="table-row">
|
||||
<div class="table-cell table-cell-author">
|
||||
@@ -40,7 +40,7 @@
|
||||
<span v-if="item.isAdmin" class="cell-admin-tag">
|
||||
<svg
|
||||
viewBox="0 0 22 22"
|
||||
aria-label="网站管理员"
|
||||
:aria-label="t('comments.table.admin')"
|
||||
role="img"
|
||||
class="cwd-admin-icon"
|
||||
style="
|
||||
@@ -63,7 +63,7 @@
|
||||
<span
|
||||
class="cell-email-text"
|
||||
@click="handleBlockEmail(item)"
|
||||
title="屏蔽该邮箱"
|
||||
:title="t('comments.actions.blockEmail')"
|
||||
>
|
||||
{{ item.email }}
|
||||
</span>
|
||||
@@ -73,7 +73,7 @@
|
||||
<span
|
||||
class="cell-ip-text"
|
||||
@click="handleBlockIp(item)"
|
||||
title="屏蔽该 IP"
|
||||
:title="t('comments.actions.blockIp')"
|
||||
>{{ item.ipAddress }}</span
|
||||
>
|
||||
</div>
|
||||
@@ -104,7 +104,7 @@
|
||||
:title="String(item.priority)"
|
||||
class="cell-status cell-pin-flag"
|
||||
>
|
||||
置顶
|
||||
{{ t('comments.actions.pin') }}
|
||||
</span>
|
||||
<span class="cell-status cell-likes-number" v-if="item.likes !== 0">
|
||||
<PhThumbsUp :size="13" />
|
||||
@@ -126,21 +126,21 @@
|
||||
:value="item.status"
|
||||
@change="handleStatusChange(item, $event)"
|
||||
>
|
||||
<option value="approved">通过</option>
|
||||
<option value="pending">待审</option>
|
||||
<option value="rejected">拒绝</option>
|
||||
<option value="approved">{{ t('comments.actions.approve') }}</option>
|
||||
<option value="pending">{{ t('comments.actions.pending') }}</option>
|
||||
<option value="rejected">{{ t('comments.actions.reject') }}</option>
|
||||
</select>
|
||||
<button class="table-action" @click="openEdit(item)">编辑</button>
|
||||
<button class="table-action" @click="openEdit(item)">{{ t('comments.actions.edit') }}</button>
|
||||
<button
|
||||
class="table-action table-action-danger"
|
||||
@click="removeComment(item)"
|
||||
>
|
||||
删除
|
||||
{{ t('comments.actions.delete') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="filteredComments.length === 0" class="table-empty">暂无数据</div>
|
||||
<div v-if="filteredComments.length === 0" class="table-empty">{{ t('comments.empty') }}</div>
|
||||
</div>
|
||||
<div v-if="pagination.total > 1" class="pagination">
|
||||
<button
|
||||
@@ -148,7 +148,7 @@
|
||||
:disabled="pagination.page <= 1"
|
||||
@click="goPage(pagination.page - 1)"
|
||||
>
|
||||
上一页
|
||||
{{ t('comments.pagination.prev') }}
|
||||
</button>
|
||||
<button
|
||||
class="pagination-button"
|
||||
@@ -199,10 +199,10 @@
|
||||
:disabled="pagination.page >= pagination.total"
|
||||
@click="goPage(pagination.page + 1)"
|
||||
>
|
||||
下一页
|
||||
{{ t('comments.pagination.next') }}
|
||||
</button>
|
||||
<div class="pagination-jump">
|
||||
<span>跳转到</span>
|
||||
<span>{{ t('comments.pagination.jumpTo') }}</span>
|
||||
<input
|
||||
v-model="jumpPageInput"
|
||||
class="pagination-input"
|
||||
@@ -211,8 +211,8 @@
|
||||
:max="pagination.total"
|
||||
@keyup.enter="handleJumpPage"
|
||||
/>
|
||||
<span>页</span>
|
||||
<button class="pagination-button" @click="handleJumpPage">确定</button>
|
||||
<span>{{ t('comments.pagination.page') }}</span>
|
||||
<button class="pagination-button" @click="handleJumpPage">{{ t('comments.pagination.confirm') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -231,6 +231,10 @@ import "../../styles/markdown.css";
|
||||
import { onMounted, ref, computed, watch, inject } from "vue";
|
||||
import type { Ref } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { marked } from "marked";
|
||||
import DOMPurify from "dompurify";
|
||||
import ModalEdit from "./components/ModalEdit.vue";
|
||||
import {
|
||||
CommentItem,
|
||||
CommentListResponse,
|
||||
@@ -241,12 +245,13 @@ import {
|
||||
blockIp,
|
||||
blockEmail,
|
||||
} from "../../api/admin";
|
||||
import ModalEdit from "./components/ModalEdit.vue";
|
||||
import { useSite } from "../../composables/useSite";
|
||||
|
||||
const { t } = useI18n();
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
// ... existing refs ...
|
||||
const comments = ref<CommentItem[]>([]);
|
||||
const pagination = ref<{ page: number; total: number }>({ page: 1, total: 1 });
|
||||
const loading = ref(false);
|
||||
@@ -268,6 +273,11 @@ const editForm = ref<{
|
||||
priority: number;
|
||||
} | null>(null);
|
||||
|
||||
const searchKeyword = ref(""); // Missing ref in original code snippet but used in template?
|
||||
// Wait, I saw searchKeyword in original code snippet. I must ensure I don't lose it.
|
||||
// I will just use the replace string for the specific parts if possible, but I am replacing whole template.
|
||||
// I need to be careful with script content.
|
||||
|
||||
const filteredComments = computed(() => {
|
||||
if (!statusFilter.value) {
|
||||
return comments.value;
|
||||
@@ -275,6 +285,7 @@ const filteredComments = computed(() => {
|
||||
return comments.value.filter((item) => item.status === statusFilter.value);
|
||||
});
|
||||
|
||||
// ... visiblePages computed ...
|
||||
const visiblePages = computed(() => {
|
||||
const total = pagination.value.total;
|
||||
const current = pagination.value.page;
|
||||
@@ -308,17 +319,18 @@ function formatDate(value: number) {
|
||||
|
||||
function formatStatus(status: string) {
|
||||
if (status === "approved") {
|
||||
return "已通过";
|
||||
return t('comments.statusFilter.approved');
|
||||
}
|
||||
if (status === "pending") {
|
||||
return "待审核";
|
||||
return t('comments.statusFilter.pending');
|
||||
}
|
||||
if (status === "rejected") {
|
||||
return "已拒绝";
|
||||
return t('comments.statusFilter.rejected');
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
// ... other functions ...
|
||||
async function loadComments(page?: number) {
|
||||
const targetPage = typeof page === "number" ? page : 1;
|
||||
loading.value = true;
|
||||
@@ -341,9 +353,7 @@ function updateRoutePage(page: number) {
|
||||
} else {
|
||||
query.p = String(page);
|
||||
}
|
||||
// Removed domain from query as it's now global state
|
||||
delete query.domain;
|
||||
|
||||
router.push({ query });
|
||||
}
|
||||
|
||||
@@ -388,7 +398,7 @@ function handleStatusChange(item: CommentItem, event: Event) {
|
||||
}
|
||||
|
||||
async function removeComment(item: CommentItem) {
|
||||
if (!window.confirm(`确认删除评论 ${item.id} 吗`)) {
|
||||
if (!window.confirm(t('comments.confirmDelete', { id: item.id }))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
@@ -403,12 +413,12 @@ async function handleBlockIp(item: CommentItem) {
|
||||
if (!item.ipAddress) {
|
||||
return;
|
||||
}
|
||||
if (!window.confirm(`确认将 IP ${item.ipAddress} 加入黑名单吗?`)) {
|
||||
if (!window.confirm(t('comments.confirmBlockIp', { ip: item.ipAddress }))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await blockIp(item.ipAddress);
|
||||
window.alert(res.message || "已加入 IP 黑名单");
|
||||
window.alert(res.message || t('comments.successBlockIp'));
|
||||
} catch (e: any) {
|
||||
error.value = e.message || "屏蔽 IP 失败";
|
||||
}
|
||||
@@ -418,12 +428,12 @@ async function handleBlockEmail(item: CommentItem) {
|
||||
if (!item.email) {
|
||||
return;
|
||||
}
|
||||
if (!window.confirm(`确认将邮箱 ${item.email} 加入黑名单吗?`)) {
|
||||
if (!window.confirm(t('comments.confirmBlockEmail', { email: item.email }))) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const res = await blockEmail(item.email);
|
||||
window.alert(res.message || "已加入邮箱黑名单");
|
||||
window.alert(res.message || t('comments.successBlockEmail'));
|
||||
} catch (e: any) {
|
||||
error.value = e.message || "屏蔽邮箱失败";
|
||||
}
|
||||
@@ -535,6 +545,7 @@ watch(currentSiteId, () => {
|
||||
updateRoutePage(1);
|
||||
loadComments(1);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="less">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<h2 class="page-title">数据管理</h2>
|
||||
<h2 class="page-title">{{ t('data.title') }}</h2>
|
||||
<div
|
||||
v-if="toastVisible"
|
||||
class="toast"
|
||||
@@ -11,57 +11,57 @@
|
||||
|
||||
<!-- 1. 评论数据 -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">评论数据</h3>
|
||||
<p class="card-desc">管理评论内容,支持从其他评论框架迁移数据。</p>
|
||||
<h3 class="card-title">{{ t('data.sections.comments.title') }}</h3>
|
||||
<p class="card-desc">{{ t('data.sections.comments.desc') }}</p>
|
||||
|
||||
<div class="action-row">
|
||||
<span class="action-label">导出:</span>
|
||||
<span class="action-label">{{ t('data.sections.comments.exportLabel') }}</span>
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportComments">
|
||||
<span v-if="exporting">导出中...</span>
|
||||
<span v-else>导出 JSON</span>
|
||||
<span v-if="exporting">{{ t('data.sections.comments.exporting') }}</span>
|
||||
<span v-else>{{ t('data.sections.comments.exportJson') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="action-row">
|
||||
<span class="action-label">导入:</span>
|
||||
<span class="action-label">{{ t('data.sections.comments.importLabel') }}</span>
|
||||
<select v-model="importSource" class="form-select" style="min-width:120px;">
|
||||
<option value="cwd">CWD (.json)</option>
|
||||
<option value="twikoo">Twikoo (.json)</option>
|
||||
<option value="artalk">Artalk (.json)</option>
|
||||
<option value="cwd">{{ t('data.sections.comments.source.cwd') }}</option>
|
||||
<option value="twikoo">{{ t('data.sections.comments.source.twikoo') }}</option>
|
||||
<option value="artalk">{{ t('data.sections.comments.source.artalk') }}</option>
|
||||
</select>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('comments')">
|
||||
导入评论
|
||||
{{ t('data.sections.comments.importButton') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. 系统配置 -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">系统配置</h3>
|
||||
<p class="card-desc">管理后台设置、邮件配置、黑名单等。</p>
|
||||
<h3 class="card-title">{{ t('data.sections.config.title') }}</h3>
|
||||
<p class="card-desc">{{ t('data.sections.config.desc') }}</p>
|
||||
<div class="action-row">
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportConfig">导出配置</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('config')">导入配置</button>
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportConfig">{{ t('data.sections.config.export') }}</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('config')">{{ t('data.sections.config.import') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. 访问统计 -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">访问统计</h3>
|
||||
<p class="card-desc">管理文章访问量、点赞数及每日访问趋势。</p>
|
||||
<h3 class="card-title">{{ t('data.sections.stats.title') }}</h3>
|
||||
<p class="card-desc">{{ t('data.sections.stats.desc') }}</p>
|
||||
<div class="action-row">
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportStats">导出统计</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('stats')">导入统计</button>
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportStats">{{ t('data.sections.stats.export') }}</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('stats')">{{ t('data.sections.stats.import') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. 全量备份 -->
|
||||
<div class="card">
|
||||
<h3 class="card-title">全量备份</h3>
|
||||
<p class="card-desc">一键备份或恢复系统所有数据(评论 + 配置 + 统计)。</p>
|
||||
<h3 class="card-title">{{ t('data.sections.backup.title') }}</h3>
|
||||
<p class="card-desc">{{ t('data.sections.backup.desc') }}</p>
|
||||
<div class="action-row">
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportBackup">全量导出</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('backup')">全量恢复</button>
|
||||
<button class="card-button secondary" :disabled="exporting" @click="handleExportBackup">{{ t('data.sections.backup.export') }}</button>
|
||||
<button class="card-button secondary" :disabled="importing" @click="triggerFileInput('backup')">{{ t('data.sections.backup.import') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
<!-- 导入日志 -->
|
||||
<div v-if="importLogs.length > 0" class="log-container">
|
||||
<div class="log-title">操作日志</div>
|
||||
<div class="log-title">{{ t('data.logs.title') }}</div>
|
||||
<div class="log-list">
|
||||
<div v-for="(log, index) in importLogs" :key="index" class="log-item">
|
||||
{{ log }}
|
||||
@@ -87,26 +87,27 @@
|
||||
<!-- 前缀确认弹窗 -->
|
||||
<div v-if="showPrefixModal" class="modal-overlay">
|
||||
<div class="modal">
|
||||
<h3 class="modal-title">检测到 URL 缺失前缀</h3>
|
||||
<h3 class="modal-title">{{ t('data.prefixModal.title') }}</h3>
|
||||
<p class="modal-desc">
|
||||
检测到 <strong>{{ missingPrefixCount }}</strong> 条评论的 URL
|
||||
不存在域名前缀(http/https)。<br />
|
||||
是否在导入时统一添加?
|
||||
{{ t('data.prefixModal.descPart1') }}
|
||||
<strong>{{ missingPrefixCount }}</strong>
|
||||
{{ t('data.prefixModal.descPart2') }}<br />
|
||||
{{ t('data.prefixModal.descPart3') }}
|
||||
</p>
|
||||
<div class="form-group">
|
||||
<label class="form-label">域名前缀 (例如 https://example.me)</label>
|
||||
<label class="form-label">{{ t('data.prefixModal.label') }}</label>
|
||||
<input
|
||||
v-model="urlPrefix"
|
||||
class="form-input"
|
||||
placeholder="请输入域名前缀"
|
||||
:placeholder="t('data.prefixModal.placeholder')"
|
||||
@keyup.enter="confirmPrefix"
|
||||
/>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<div class="modal-actions">
|
||||
<button class="modal-btn secondary" @click="cancelPrefix">
|
||||
直接导入 (不添加)
|
||||
{{ t('data.prefixModal.skip') }}
|
||||
</button>
|
||||
<button class="modal-btn primary" @click="confirmPrefix">添加并导入</button>
|
||||
<button class="modal-btn primary" @click="confirmPrefix">{{ t('data.prefixModal.confirm') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,6 +116,7 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import {
|
||||
exportComments, importComments,
|
||||
exportConfig, importConfig,
|
||||
@@ -123,6 +125,8 @@ import {
|
||||
} from "../../api/admin";
|
||||
import { useSite } from "../../composables/useSite";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const exporting = ref(false);
|
||||
const importing = ref(false);
|
||||
const importSource = ref("cwd");
|
||||
@@ -171,9 +175,9 @@ async function executeExport(apiFunc: () => Promise<any>, fileNamePrefix: string
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
showToast("导出成功", "success");
|
||||
showToast(t('data.messages.exportSuccess'), "success");
|
||||
} catch (e: any) {
|
||||
showToast(e.message || "导出失败", "error");
|
||||
showToast(e.message || t('data.messages.exportFailed'), "error");
|
||||
} finally {
|
||||
exporting.value = false;
|
||||
}
|
||||
@@ -188,7 +192,7 @@ const handleExportBackup = () => executeExport(exportBackup, 'cwd-full-backup');
|
||||
// 触发文件选择
|
||||
function triggerFileInput(mode: string) {
|
||||
currentImportMode.value = mode;
|
||||
importLogs.value = []; // 清空日志
|
||||
importLogs.value = [];
|
||||
if (fileInput.value) {
|
||||
fileInput.value.value = ''; // 重置 input
|
||||
fileInput.value.click();
|
||||
@@ -202,7 +206,7 @@ async function handleFileChange(event: Event) {
|
||||
if (!file) return;
|
||||
|
||||
importing.value = true;
|
||||
addLog(`开始导入: ${file.name} (模式: ${currentImportMode.value})`);
|
||||
addLog(t('data.messages.importStart', { name: file.name, mode: currentImportMode.value }));
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = async (e) => {
|
||||
@@ -212,10 +216,10 @@ async function handleFileChange(event: Event) {
|
||||
try {
|
||||
json = JSON.parse(content);
|
||||
} catch (parseError) {
|
||||
throw new Error("JSON 解析失败,请检查文件格式");
|
||||
throw new Error(t('data.messages.jsonParseFailed'));
|
||||
}
|
||||
|
||||
addLog("文件解析成功,开始处理...");
|
||||
addLog(t('data.messages.fileParseSuccess'));
|
||||
|
||||
switch (currentImportMode.value) {
|
||||
case 'comments':
|
||||
@@ -234,15 +238,15 @@ async function handleFileChange(event: Event) {
|
||||
|
||||
} catch (err: any) {
|
||||
console.error(err);
|
||||
addLog(`错误: ${err.message}`);
|
||||
addLog(t('data.messages.errorWithMessage', { msg: err.message }));
|
||||
showToast(err.message, "error");
|
||||
importing.value = false;
|
||||
}
|
||||
};
|
||||
|
||||
reader.onerror = () => {
|
||||
addLog("读取文件失败");
|
||||
showToast("读取文件失败", "error");
|
||||
addLog(t('data.messages.readFileFailedLog'));
|
||||
showToast(t('data.messages.fileReadFailed'), "error");
|
||||
importing.value = false;
|
||||
};
|
||||
|
||||
@@ -253,27 +257,27 @@ async function handleFileChange(event: Event) {
|
||||
async function processImportConfig(data: any) {
|
||||
const res = await importConfig(data);
|
||||
addLog(res.message);
|
||||
showToast("配置导入成功");
|
||||
showToast(t('data.messages.importConfigSuccess'));
|
||||
importing.value = false;
|
||||
}
|
||||
|
||||
async function processImportStats(data: any) {
|
||||
const res = await importStats(data);
|
||||
addLog(res.message);
|
||||
showToast("统计数据导入成功");
|
||||
showToast(t('data.messages.importStatsSuccess'));
|
||||
importing.value = false;
|
||||
}
|
||||
|
||||
async function processImportBackup(data: any) {
|
||||
const res = await importBackup(data);
|
||||
addLog(res.message);
|
||||
showToast("全量恢复成功");
|
||||
showToast(t('data.messages.importBackupSuccess'));
|
||||
importing.value = false;
|
||||
}
|
||||
|
||||
async function processImportComments(json: any) {
|
||||
const comments = Array.isArray(json) ? json : [json];
|
||||
addLog(`解析到 ${comments.length} 条评论数据`);
|
||||
addLog(t('data.messages.parsedCommentsCount', { count: comments.length }));
|
||||
|
||||
// 检查 URL 前缀 (仅针对评论导入)
|
||||
let missingCount = 0;
|
||||
@@ -287,7 +291,7 @@ async function processImportComments(json: any) {
|
||||
}
|
||||
|
||||
if (missingCount > 0) {
|
||||
addLog(`检测到 ${missingCount} 条 URL 缺失前缀,等待用户确认...`);
|
||||
addLog(t('data.messages.detectMissingPrefix', { count: missingCount }));
|
||||
missingPrefixCount.value = missingCount;
|
||||
pendingJson.value = comments;
|
||||
showPrefixModal.value = true;
|
||||
@@ -300,8 +304,8 @@ async function processImportComments(json: any) {
|
||||
async function executeImportComments(comments: any[]) {
|
||||
try {
|
||||
const res = await importComments(comments);
|
||||
addLog(`导入完成: ${res.message}`);
|
||||
showToast("评论导入成功");
|
||||
addLog(t('data.messages.importCommentsDone', { message: res.message }));
|
||||
showToast(t('data.messages.importCommentsSuccess'));
|
||||
} catch (err: any) {
|
||||
throw err;
|
||||
} finally {
|
||||
@@ -313,7 +317,7 @@ async function executeImportComments(comments: any[]) {
|
||||
// 前缀确认逻辑
|
||||
async function confirmPrefix() {
|
||||
if (!urlPrefix.value) {
|
||||
showToast("请输入域名前缀", "error");
|
||||
showToast(t('data.messages.prefixRequired'), "error");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -343,13 +347,13 @@ async function confirmPrefix() {
|
||||
});
|
||||
|
||||
showPrefixModal.value = false;
|
||||
addLog(`已添加前缀,继续导入...`);
|
||||
addLog(t('data.messages.prefixAdded'));
|
||||
await executeImportComments(comments);
|
||||
}
|
||||
|
||||
function cancelPrefix() {
|
||||
showPrefixModal.value = false;
|
||||
addLog("用户跳过前缀添加");
|
||||
addLog(t('data.messages.skipPrefix'));
|
||||
executeImportComments(pendingJson.value);
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<button
|
||||
class="layout-menu-toggle"
|
||||
@click="toggleSider"
|
||||
aria-label="切换菜单"
|
||||
:aria-label="t('layout.toggleMenu')"
|
||||
type="button"
|
||||
>
|
||||
<PhTextIndent :size="20" />
|
||||
@@ -25,7 +25,7 @@
|
||||
</div>
|
||||
<div class="layout-actions">
|
||||
<a class="layout-button" href="https://cwd.js.org" target="_blank">
|
||||
使用文档
|
||||
{{ t('layout.docs') }}
|
||||
</a>
|
||||
<a class="layout-button" href="https://github.com/anghunk/cwd" target="_blank">
|
||||
Github
|
||||
@@ -40,20 +40,20 @@
|
||||
<PhMoon v-else-if="theme === 'dark'" :size="16" />
|
||||
<PhAirplay v-else :size="16" />
|
||||
</button>
|
||||
<button class="layout-button" @click="handleLogout">退出</button>
|
||||
<button class="layout-button" @click="handleLogout">{{ t('layout.logout') }}</button>
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="layout-actions-toggle"
|
||||
@click="toggleActions"
|
||||
aria-label="更多操作"
|
||||
:aria-label="t('layout.moreActions')"
|
||||
type="button"
|
||||
>
|
||||
<PhDotsThreeVertical :size="20" bold />
|
||||
</button>
|
||||
<div v-if="isActionsOpen" class="layout-actions-dropdown">
|
||||
<button class="layout-actions-item" type="button" @click="openDocs">
|
||||
使用文档
|
||||
{{ t('layout.docs') }}
|
||||
</button>
|
||||
<button class="layout-actions-item" type="button" @click="openGithub">
|
||||
Github
|
||||
@@ -63,7 +63,7 @@
|
||||
type="button"
|
||||
@click="handleLogoutFromActions"
|
||||
>
|
||||
退出
|
||||
{{ t('layout.logout') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -92,7 +92,7 @@
|
||||
@click="goComments"
|
||||
>
|
||||
<PhChatCircleDots class="menu-item-icon" :size="18" />
|
||||
<span>评论管理</span>
|
||||
<span>{{ t('menu.comments') }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="menu-item"
|
||||
@@ -100,7 +100,7 @@
|
||||
@click="goStats"
|
||||
>
|
||||
<PhSquaresFour class="menu-item-icon" :size="18" />
|
||||
<span>数据看板</span>
|
||||
<span>{{ t('menu.stats') }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="menu-item"
|
||||
@@ -108,7 +108,7 @@
|
||||
@click="goAnalytics"
|
||||
>
|
||||
<PhChartBar class="menu-item-icon" :size="18" />
|
||||
<span>访问统计</span>
|
||||
<span>{{ t('menu.analytics') }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="menu-item"
|
||||
@@ -116,7 +116,7 @@
|
||||
@click="goSettings"
|
||||
>
|
||||
<PhGear class="menu-item-icon" :size="18" />
|
||||
<span>网站设置</span>
|
||||
<span>{{ t('menu.settings') }}</span>
|
||||
</li>
|
||||
<li
|
||||
class="menu-item"
|
||||
@@ -124,7 +124,7 @@
|
||||
@click="goData"
|
||||
>
|
||||
<PhDatabase class="menu-item-icon" :size="18" />
|
||||
<span>数据管理</span>
|
||||
<span>{{ t('menu.data') }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="layout-sider-footer" @click="openVersionModal">
|
||||
@@ -141,36 +141,35 @@
|
||||
</div>
|
||||
<div v-if="versionModalVisible" class="modal-overlay" @click.self="closeVersionModal">
|
||||
<div class="modal">
|
||||
<h3 class="modal-title">版本信息</h3>
|
||||
<h3 class="modal-title">{{ t('layout.version.title') }}</h3>
|
||||
<div class="modal-body">
|
||||
<p class="modal-row">
|
||||
<span class="modal-label">API 地址</span>
|
||||
<span class="modal-value">{{ checkedApiBaseUrl || "未配置" }}</span>
|
||||
<span class="modal-label">{{ t('layout.version.apiAddress') }}</span>
|
||||
<span class="modal-value">{{ checkedApiBaseUrl || t('layout.version.notConfigured') }}</span>
|
||||
</p>
|
||||
<p class="modal-row">
|
||||
<span class="modal-label">接口版本</span>
|
||||
<span class="modal-label">{{ t('layout.version.apiVersion') }}</span>
|
||||
<span class="modal-value">
|
||||
{{ apiVersion || (apiVersionError ? "未获取到" : "加载中...") }}
|
||||
{{ apiVersion || (apiVersionError ? t('layout.version.notFetched') : t('layout.version.loading')) }}
|
||||
</span>
|
||||
</p>
|
||||
<p class="modal-row">
|
||||
<span class="modal-label">后台版本</span>
|
||||
<span class="modal-label">{{ t('layout.version.adminVersion') }}</span>
|
||||
<span class="modal-value">{{ adminVersion }}</span>
|
||||
</p>
|
||||
<p v-if="apiVersion && apiVersion === adminVersion" class="modal-status">
|
||||
当前后台与接口版本一致,可以正常使用。
|
||||
{{ t('layout.version.match') }}
|
||||
</p>
|
||||
<p v-else-if="apiVersion && apiVersion !== adminVersion" class="modal-status">
|
||||
当前后台与接口版本不一致,推荐将 API 服务更新到与后台版本一致,
|
||||
以避免潜在的兼容性问题。
|
||||
{{ t('layout.version.mismatch') }}
|
||||
</p>
|
||||
<p v-else-if="apiVersionError" class="modal-status">
|
||||
无法获取接口版本:{{ apiVersionError }}
|
||||
{{ t('layout.version.fetchError') }} {{ apiVersionError }}
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="modal-btn" type="button" @click="closeVersionModal">
|
||||
我知道了
|
||||
{{ t('layout.version.ok') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -181,6 +180,7 @@
|
||||
<script setup lang="ts">
|
||||
import { ref, onMounted, provide, computed } from "vue";
|
||||
import { useRouter, useRoute } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import { logoutAdmin, fetchAdminDisplaySettings, fetchSiteList } from "../../api/admin";
|
||||
import { useTheme } from "../../composables/useTheme";
|
||||
import { useSite } from "../../composables/useSite";
|
||||
@@ -191,6 +191,7 @@ const SITE_TITLE_KEY = "cwd_admin_site_title";
|
||||
|
||||
const router = useRouter();
|
||||
const route = useRoute();
|
||||
const { t } = useI18n();
|
||||
const { theme, setTheme } = useTheme();
|
||||
const { currentSiteId } = useSite();
|
||||
|
||||
@@ -204,9 +205,9 @@ const versionModalVisible = ref(false);
|
||||
const layoutTitle = ref(localStorage.getItem(SITE_TITLE_KEY) || "CWD 评论系统");
|
||||
|
||||
const themeTitle = computed(() => {
|
||||
if (theme.value === "light") return "明亮模式";
|
||||
if (theme.value === "dark") return "暗黑模式";
|
||||
return "跟随系统";
|
||||
if (theme.value === "light") return t('layout.theme.light');
|
||||
if (theme.value === "dark") return t('layout.theme.dark');
|
||||
return t('layout.theme.system');
|
||||
});
|
||||
|
||||
function cycleTheme() {
|
||||
@@ -221,7 +222,7 @@ const defaultSiteId = "default";
|
||||
|
||||
function getSiteLabel(value: string) {
|
||||
if (!value || value === "default") {
|
||||
return "默认站点";
|
||||
return t('layout.defaultSite');
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<h2 class="page-title">网站设置</h2>
|
||||
<h2 class="page-title">{{ t('settings.title') }}</h2>
|
||||
<div
|
||||
v-if="toastVisible"
|
||||
class="toast"
|
||||
@@ -8,7 +8,7 @@
|
||||
>
|
||||
{{ toastMessage }}
|
||||
</div>
|
||||
<div v-if="loading" class="page-hint">加载中...</div>
|
||||
<div v-if="loading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else>
|
||||
<div class="settings-tabs">
|
||||
<button
|
||||
@@ -17,7 +17,7 @@
|
||||
:class="{ 'settings-tab-active': activeTab === 'comment' }"
|
||||
@click="activeTab = 'comment'"
|
||||
>
|
||||
评论与安全
|
||||
{{ t('settings.tabs.comment') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -25,15 +25,7 @@
|
||||
:class="{ 'settings-tab-active': activeTab === 'feature' }"
|
||||
@click="activeTab = 'feature'"
|
||||
>
|
||||
功能开关
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="settings-tab"
|
||||
:class="{ 'settings-tab-active': activeTab === 'display' }"
|
||||
@click="activeTab = 'display'"
|
||||
>
|
||||
后台显示
|
||||
{{ t('settings.tabs.feature') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -41,7 +33,7 @@
|
||||
:class="{ 'settings-tab-active': activeTab === 'emailNotify' }"
|
||||
@click="activeTab = 'emailNotify'"
|
||||
>
|
||||
邮箱提醒
|
||||
{{ t('settings.tabs.emailNotify') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
@@ -49,7 +41,15 @@
|
||||
:class="{ 'settings-tab-active': activeTab === 'telegramNotify' }"
|
||||
@click="activeTab = 'telegramNotify'"
|
||||
>
|
||||
Telegram 通知
|
||||
{{ t('settings.tabs.telegramNotify') }}
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="settings-tab"
|
||||
:class="{ 'settings-tab-active': activeTab === 'display' }"
|
||||
@click="activeTab = 'display'"
|
||||
>
|
||||
{{ t('settings.tabs.display') }}
|
||||
</button>
|
||||
</div>
|
||||
<transition name="tab-fade" mode="out-in">
|
||||
@@ -57,19 +57,19 @@
|
||||
<template v-if="activeTab === 'comment'">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">评论显示配置</div>
|
||||
<div class="card-title">{{ t('settings.comment.title') }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-item">
|
||||
<label class="form-label">管理员邮箱</label>
|
||||
<label class="form-label">{{ t('settings.comment.adminEmail') }}</label>
|
||||
<input v-model="commentAdminEmail" class="form-input" type="email" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">博主标签文字(留空使用默认图标)</label>
|
||||
<label class="form-label">{{ t('settings.comment.adminBadge') }}</label>
|
||||
<input v-model="commentAdminBadge" class="form-input" type="text" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">是否开启博主标签显示</label>
|
||||
<label class="form-label">{{ t('settings.comment.adminEnabled') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="commentAdminEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
@@ -77,13 +77,13 @@
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label"
|
||||
>头像前缀(默认:https://gravatar.com/avatar)</label
|
||||
>{{ t('settings.comment.avatarPrefix') }}</label
|
||||
>
|
||||
<input v-model="avatarPrefix" class="form-input" type="text" />
|
||||
</div>
|
||||
<h3 class="card-title">安全设置</h3>
|
||||
<h3 class="card-title">{{ t('settings.comment.securityTitle') }}</h3>
|
||||
<div class="form-item">
|
||||
<label class="form-label">新评论是否审核后再显示</label>
|
||||
<label class="form-label">{{ t('settings.comment.requireReview') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="requireReview" type="checkbox" />
|
||||
<span class="slider" />
|
||||
@@ -91,31 +91,31 @@
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">
|
||||
管理员评论密钥(设置后前台使用管理员邮箱评论需输入此密钥。)
|
||||
{{ t('settings.comment.adminKey') }}
|
||||
</label>
|
||||
|
||||
<input
|
||||
v-model="commentAdminKey"
|
||||
class="form-input"
|
||||
placeholder="输入密钥以设置或修改"
|
||||
:placeholder="t('settings.comment.adminKeyPlaceholder')"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">
|
||||
允许调用的域名(设置后仅匹配域名可调用前台评论组件,留空则不限制。使用空格或者逗号进行分割。)
|
||||
{{ t('settings.comment.allowedDomains') }}
|
||||
</label>
|
||||
<TagInput v-model="allowedDomainTags" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">
|
||||
IP 黑名单(多个 IP 用逗号或换行分隔,留空则不限制)
|
||||
{{ t('settings.comment.blockedIps') }}
|
||||
</label>
|
||||
<TagInput v-model="blockedIpTags" />
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label"
|
||||
>邮箱黑名单(多个邮箱用逗号或换行分隔,留空则不限制)</label
|
||||
>{{ t('settings.comment.blockedEmails') }}</label
|
||||
>
|
||||
<TagInput v-model="blockedEmailTags" />
|
||||
</div>
|
||||
@@ -126,8 +126,8 @@
|
||||
:disabled="savingComment"
|
||||
@click="saveComment"
|
||||
>
|
||||
<span v-if="savingComment">保存中...</span>
|
||||
<span v-else>保存</span>
|
||||
<span v-if="savingComment">{{ t('settings.comment.saving') }}</span>
|
||||
<span v-else>{{ t('settings.comment.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -136,66 +136,80 @@
|
||||
<template v-else-if="activeTab === 'feature'">
|
||||
<div class="card feature">
|
||||
<div class="card-header">
|
||||
<div class="card-title">功能开关</div>
|
||||
<div class="card-title">{{ t('settings.feature.title') }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-item bg">
|
||||
<div class="form-item-flex">
|
||||
<label class="form-label">开启文章点赞功能</label>
|
||||
<label class="form-label">{{ t('settings.feature.articleLike') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="enableArticleLike" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-hint">
|
||||
开启后,评论区顶部会显示的文章点赞(喜欢)按钮。
|
||||
{{ t('settings.feature.articleLikeHint') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-item bg">
|
||||
<div class="form-item-flex">
|
||||
<label class="form-label">开启评论点赞功能</label>
|
||||
<label class="form-label">{{ t('settings.feature.commentLike') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="enableCommentLike" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-hint">
|
||||
开启后,评论列表中的每条评论都会显示点赞按钮。
|
||||
{{ t('settings.feature.commentLikeHint') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-item bg">
|
||||
<div class="form-item-flex">
|
||||
<label class="form-label">评论列表图片灯箱模式</label>
|
||||
<label class="form-label">{{ t('settings.feature.imageLightbox') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="enableImageLightbox" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-hint">开启后,点击评论中的图片时会全屏放大预览。</div>
|
||||
<div class="form-hint">{{ t('settings.feature.imageLightboxHint') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">评论框提示文案 (Placeholder)</label>
|
||||
<label class="form-label">{{ t('settings.feature.placeholder') }}</label>
|
||||
<textarea
|
||||
v-model="commentPlaceholder"
|
||||
class="form-input"
|
||||
rows="3"
|
||||
style="height: 90px; resize: none"
|
||||
placeholder="默认:写下你的评论,可换行书写提示"
|
||||
:placeholder="t('settings.feature.placeholderHint')"
|
||||
></textarea>
|
||||
<div class="form-hint">
|
||||
自定义评论输入框的提示文字,支持换行。留空则使用默认值。
|
||||
{{ t('settings.feature.placeholderHint') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">{{ t('settings.feature.widgetLanguage') }}</label>
|
||||
<select v-model="widgetLanguage" class="form-input">
|
||||
<option value="auto">Auto (Browser Default)</option>
|
||||
<option v-for="lang in languageOptions" :key="lang.value" :value="lang.value">
|
||||
{{ lang.label }} ({{ lang.value }})
|
||||
</option>
|
||||
</select>
|
||||
<div class="form-hint">
|
||||
{{ t('settings.feature.widgetLanguageHint') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-actions">
|
||||
<button
|
||||
class="card-button"
|
||||
:disabled="savingFeature"
|
||||
@click="saveFeature"
|
||||
>
|
||||
<span v-if="savingFeature">保存中...</span>
|
||||
<span v-else>保存</span>
|
||||
<span v-if="savingFeature">{{ t('settings.feature.saving') }}</span>
|
||||
<span v-else>{{ t('settings.feature.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -204,27 +218,38 @@
|
||||
<template v-else-if="activeTab === 'display'">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">后台显示设置</div>
|
||||
<div class="card-title">{{ t('settings.display.title') }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-item">
|
||||
<label class="form-label">后台标题</label>
|
||||
<label class="form-label">{{ t('settings.display.layoutTitle') }}</label>
|
||||
<input
|
||||
v-model="adminLayoutTitle"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="CWD 评论系统"
|
||||
/>
|
||||
<div class="form-hint">显示在后台顶部导航栏左侧。</div>
|
||||
<div class="form-hint">{{ t('settings.display.layoutTitleHint') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">{{ t('settings.display.adminLanguage') }}</label>
|
||||
<select v-model="adminLanguage" class="form-input">
|
||||
<option v-for="lang in languageOptions" :key="lang.value" :value="lang.value">
|
||||
{{ lang.label }} ({{ lang.value }})
|
||||
</option>
|
||||
</select>
|
||||
<div class="form-hint">{{ t('settings.display.adminLanguageHint') }}</div>
|
||||
</div>
|
||||
|
||||
<div class="card-actions">
|
||||
<button
|
||||
class="card-button"
|
||||
:disabled="savingDisplay"
|
||||
@click="saveDisplay"
|
||||
>
|
||||
<span v-if="savingDisplay">保存中...</span>
|
||||
<span v-else>保存</span>
|
||||
<span v-if="savingDisplay">{{ t('settings.display.saving') }}</span>
|
||||
<span v-else>{{ t('settings.display.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -233,11 +258,11 @@
|
||||
<template v-else-if="activeTab === 'emailNotify'">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">通知邮箱设置</div>
|
||||
<div class="card-title">{{ t('settings.emailNotify.title') }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-item">
|
||||
<label class="form-label">开启邮件通知</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.enable') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="emailGlobalEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
@@ -245,10 +270,10 @@
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<h4 class="card-subtitle">1. SMTP 发件配置</h4>
|
||||
<h4 class="card-subtitle">{{ t('settings.emailNotify.smtpTitle') }}</h4>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">邮件服务商</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.provider') }}</label>
|
||||
<select
|
||||
v-model="smtpProvider"
|
||||
class="form-input"
|
||||
@@ -262,7 +287,7 @@
|
||||
|
||||
<div v-if="smtpProvider === 'custom'">
|
||||
<div class="form-item">
|
||||
<label class="form-label">SMTP 服务器</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.host') }}</label>
|
||||
<input
|
||||
v-model="smtpHost"
|
||||
class="form-input"
|
||||
@@ -270,7 +295,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">SMTP 端口</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.port') }}</label>
|
||||
<input
|
||||
v-model="smtpPort"
|
||||
class="form-input"
|
||||
@@ -279,7 +304,7 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">SSL 安全连接</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.secure') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="smtpSecure" type="checkbox" />
|
||||
<span class="slider" />
|
||||
@@ -288,7 +313,7 @@
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">发件邮箱账号</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.user') }}</label>
|
||||
<input
|
||||
v-model="smtpUser"
|
||||
class="form-input"
|
||||
@@ -296,37 +321,24 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">授权码/密码</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.pass') }}</label>
|
||||
<input
|
||||
v-model="smtpPass"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="QQ邮箱请使用授权码"
|
||||
/>
|
||||
<div v-if="smtpProvider === 'qq'" class="form-hint">
|
||||
注意:QQ 邮箱必须使用<a
|
||||
href="https://service.mail.qq.com/detail/0/75"
|
||||
target="_blank"
|
||||
>授权码</a
|
||||
>,而非 QQ 密码。<br />
|
||||
请登录 QQ 邮箱网页版,在【设置 - 账户】中开启 POP3/SMTP
|
||||
服务并生成授权码。
|
||||
</div>
|
||||
<div v-else-if="smtpProvider === '163'" class="form-hint">
|
||||
注意:163 邮箱必须使用授权码,而非登录密码。<br />
|
||||
请登录 163 邮箱网页版,在【设置 -
|
||||
POP3/SMTP/IMAP】中开启服务并生成授权码。
|
||||
</div>
|
||||
<div v-if="smtpProvider === 'qq'" class="form-hint" v-html="t('settings.emailNotify.qqHint')"></div>
|
||||
<div v-else-if="smtpProvider === '163'" class="form-hint" v-html="t('settings.emailNotify.163Hint')"></div>
|
||||
</div>
|
||||
|
||||
<div class="divider"></div>
|
||||
<h4 class="card-subtitle">2. 邮件模板设置</h4>
|
||||
<h4 class="card-subtitle">{{ t('settings.emailNotify.templateTitle') }}</h4>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">管理员通知模板 (HTML)</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.adminTemplate') }}</label>
|
||||
<div class="form-hint">
|
||||
可用变量:${commentAuthor} (评论人昵称), ${postTitle} (文章标题),
|
||||
${postUrl} (文章链接), ${commentContent} (评论内容)
|
||||
{{ t('settings.emailNotify.adminTemplateHint') }}
|
||||
</div>
|
||||
<textarea
|
||||
v-model="templateAdmin"
|
||||
@@ -337,11 +349,9 @@
|
||||
</div>
|
||||
|
||||
<div class="form-item">
|
||||
<label class="form-label">回复通知模板 (HTML)</label>
|
||||
<label class="form-label">{{ t('settings.emailNotify.replyTemplate') }}</label>
|
||||
<div class="form-hint">
|
||||
可用变量:${toName} (接收人昵称), ${replyAuthor} (回复人昵称),
|
||||
${postTitle} (文章标题), ${postUrl} (文章链接), ${parentComment}
|
||||
(原评论), ${replyContent} (回复内容)
|
||||
{{ t('settings.emailNotify.replyTemplateHint') }}
|
||||
</div>
|
||||
<textarea
|
||||
v-model="templateReply"
|
||||
@@ -363,19 +373,19 @@
|
||||
:disabled="testingEmail"
|
||||
@click="testEmail"
|
||||
>
|
||||
<span v-if="testingEmail">发送中...</span>
|
||||
<span v-else>发送测试邮件</span>
|
||||
<span v-if="testingEmail">{{ t('settings.emailNotify.testingBtn') }}</span>
|
||||
<span v-else>{{ t('settings.emailNotify.testBtn') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="card-button secondary"
|
||||
style="margin-left: auto"
|
||||
@click="resetTemplatesToDefault"
|
||||
>
|
||||
恢复默认模板
|
||||
{{ t('settings.emailNotify.resetBtn') }}
|
||||
</button>
|
||||
<button class="card-button" :disabled="savingEmail" @click="saveEmail">
|
||||
<span v-if="savingEmail">保存中...</span>
|
||||
<span v-else>保存配置</span>
|
||||
<span v-if="savingEmail">{{ t('settings.emailNotify.saving') }}</span>
|
||||
<span v-else>{{ t('settings.emailNotify.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -384,44 +394,36 @@
|
||||
<template v-else-if="activeTab === 'telegramNotify'">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<div class="card-title">Telegram 通知设置</div>
|
||||
<div class="card-title">{{ t('settings.telegramNotify.title') }}</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="form-item">
|
||||
<label class="form-label">开启 Telegram 通知</label>
|
||||
<label class="form-label">{{ t('settings.telegramNotify.enable') }}</label>
|
||||
<label class="switch">
|
||||
<input v-model="telegramNotifyEnabled" type="checkbox" />
|
||||
<span class="slider" />
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">Bot Token</label>
|
||||
<label class="form-label">{{ t('settings.telegramNotify.botToken') }}</label>
|
||||
<input
|
||||
v-model="telegramBotToken"
|
||||
class="form-input"
|
||||
type="text"
|
||||
type="password"
|
||||
placeholder="123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11"
|
||||
autocomplete="new-password"
|
||||
/>
|
||||
<div class="form-hint">
|
||||
在 Telegram 中搜索
|
||||
<a href="https://t.me/BotFather" target="_blank">@BotFather</a>
|
||||
创建机器人获取 Token
|
||||
</div>
|
||||
<div class="form-hint" v-html="t('settings.telegramNotify.botTokenHint')"></div>
|
||||
</div>
|
||||
<div class="form-item">
|
||||
<label class="form-label">Chat ID</label>
|
||||
<label class="form-label">{{ t('settings.telegramNotify.chatId') }}</label>
|
||||
<input
|
||||
v-model="telegramChatId"
|
||||
class="form-input"
|
||||
type="text"
|
||||
placeholder="123456789"
|
||||
/>
|
||||
<div class="form-hint">
|
||||
这是接收通知的用户 ID 或群组 ID。可以先给机器人发消息,然后通过 API
|
||||
获取 ID,或者使用
|
||||
<a href="https://t.me/userinfobot" target="_blank">@userinfobot</a>
|
||||
查询。
|
||||
</div>
|
||||
<div class="form-hint" v-html="t('settings.telegramNotify.chatIdHint')"></div>
|
||||
</div>
|
||||
|
||||
<div class="card-actions" style="justify-content: space-between">
|
||||
@@ -430,8 +432,8 @@
|
||||
:disabled="settingUpWebhook"
|
||||
@click="doSetupWebhook"
|
||||
>
|
||||
<span v-if="settingUpWebhook">设置中...</span>
|
||||
<span v-else>一键设置 Webhook</span>
|
||||
<span v-if="settingUpWebhook">{{ t('settings.telegramNotify.webhookSetting') }}</span>
|
||||
<span v-else>{{ t('settings.telegramNotify.webhookBtn') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="card-button secondary"
|
||||
@@ -439,16 +441,16 @@
|
||||
@click="testTelegram"
|
||||
style="margin-right: auto"
|
||||
>
|
||||
<span v-if="testingTelegram">发送中...</span>
|
||||
<span v-else>发送测试消息</span>
|
||||
<span v-if="testingTelegram">{{ t('settings.telegramNotify.testingBtn') }}</span>
|
||||
<span v-else>{{ t('settings.telegramNotify.testBtn') }}</span>
|
||||
</button>
|
||||
<button
|
||||
class="card-button"
|
||||
:disabled="savingTelegram"
|
||||
@click="saveTelegram"
|
||||
>
|
||||
<span v-if="savingTelegram">保存中...</span>
|
||||
<span v-else>保存</span>
|
||||
<span v-if="savingTelegram">{{ t('settings.telegramNotify.saving') }}</span>
|
||||
<span v-else>{{ t('settings.telegramNotify.save') }}</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -463,6 +465,7 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref, type Ref, inject, watch } from "vue";
|
||||
import { useRoute, useRouter } from "vue-router";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import {
|
||||
fetchCommentSettings,
|
||||
saveCommentSettings,
|
||||
@@ -578,6 +581,28 @@ const savingTelegram = ref(false);
|
||||
const settingUpWebhook = ref(false);
|
||||
const testingTelegram = ref(false);
|
||||
|
||||
const languageOptions = [
|
||||
{ value: 'en-US', label: 'English' },
|
||||
{ value: 'zh-CN', label: '简体中文' },
|
||||
{ value: 'zh-TW', label: '繁體中文' },
|
||||
{ value: 'es', label: 'Español' },
|
||||
{ value: 'pt', label: 'Português' },
|
||||
{ value: 'fr', label: 'Français' },
|
||||
{ value: 'de', label: 'Deutsch' },
|
||||
{ value: 'ja', label: '日本語' },
|
||||
{ value: 'ko', label: '한국어' },
|
||||
{ value: 'ru', label: 'Русский' },
|
||||
{ value: 'it', label: 'Italiano' },
|
||||
{ value: 'nl', label: 'Nederlands' },
|
||||
{ value: 'ar', label: 'العربية' },
|
||||
{ value: 'hi', label: 'हिन्दी' },
|
||||
{ value: 'id', label: 'Bahasa Indonesia' },
|
||||
];
|
||||
|
||||
const { t, locale } = useI18n();
|
||||
const adminLanguage = ref("zh-CN");
|
||||
const widgetLanguage = ref("auto");
|
||||
|
||||
const route = useRoute();
|
||||
const router = useRouter();
|
||||
|
||||
@@ -731,6 +756,14 @@ async function load() {
|
||||
enableCommentLike.value = featureRes.enableCommentLike;
|
||||
enableImageLightbox.value = featureRes.enableImageLightbox;
|
||||
commentPlaceholder.value = featureRes.commentPlaceholder || "";
|
||||
adminLanguage.value = featureRes.adminLanguage || "zh-CN";
|
||||
widgetLanguage.value = featureRes.widgetLanguage || "auto";
|
||||
|
||||
// Sync locale
|
||||
if (featureRes.adminLanguage) {
|
||||
locale.value = featureRes.adminLanguage;
|
||||
localStorage.setItem('admin_language', featureRes.adminLanguage);
|
||||
}
|
||||
|
||||
telegramBotToken.value = telegramRes.botToken || "";
|
||||
telegramChatId.value = telegramRes.chatId || "";
|
||||
@@ -861,10 +894,9 @@ async function saveComment() {
|
||||
}),
|
||||
]);
|
||||
|
||||
showToast(commentRes.message || "保存成功", "success");
|
||||
showToast(commentRes.message || t('common.saveSuccess'), "success");
|
||||
} catch (e: any) {
|
||||
message.value = e.message || "保存失败";
|
||||
messageType.value = "error";
|
||||
showToast(e.message || t('common.saveFailed'), "error");
|
||||
} finally {
|
||||
savingComment.value = false;
|
||||
}
|
||||
@@ -880,13 +912,13 @@ async function saveFeature() {
|
||||
enableCommentLike: enableCommentLike.value,
|
||||
enableImageLightbox: enableImageLightbox.value,
|
||||
commentPlaceholder: commentPlaceholder.value,
|
||||
widgetLanguage: widgetLanguage.value,
|
||||
}),
|
||||
]);
|
||||
|
||||
showToast(featureRes.message || "保存成功", "success");
|
||||
showToast(featureRes.message || t('common.saveSuccess'), "success");
|
||||
} catch (e: any) {
|
||||
message.value = e.message || "保存失败";
|
||||
messageType.value = "error";
|
||||
showToast(e.message || t('common.saveFailed'), "error");
|
||||
} finally {
|
||||
savingFeature.value = false;
|
||||
}
|
||||
@@ -901,10 +933,19 @@ async function saveDisplay() {
|
||||
const res = await saveAdminDisplaySettings({
|
||||
layoutTitle: adminLayoutTitle.value,
|
||||
});
|
||||
|
||||
// Also save admin language to feature settings as it's a global preference
|
||||
await saveFeatureSettings({
|
||||
adminLanguage: adminLanguage.value
|
||||
});
|
||||
|
||||
if (updateSiteTitle) {
|
||||
updateSiteTitle(adminLayoutTitle.value);
|
||||
}
|
||||
|
||||
// Update local locale
|
||||
locale.value = adminLanguage.value;
|
||||
localStorage.setItem('admin_language', adminLanguage.value);
|
||||
|
||||
showToast(res.message || "保存成功", "success");
|
||||
} catch (e: any) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="page">
|
||||
<div style="display: flex; align-items: center; gap: 20px">
|
||||
<h2 class="page-title">数据看板</h2>
|
||||
<h2 class="page-title">{{ t('stats.title') }}</h2>
|
||||
</div>
|
||||
<div
|
||||
v-if="toastVisible"
|
||||
@@ -13,28 +13,28 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">整体概览</h3>
|
||||
<h3 class="card-title">{{ t('stats.overview') }}</h3>
|
||||
</div>
|
||||
<div v-if="statsLoading" class="page-hint">加载中...</div>
|
||||
<div v-if="statsLoading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="statsError" class="page-error">{{ statsError }}</div>
|
||||
<div v-else>
|
||||
<div class="stats-grid">
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">总评论数</div>
|
||||
<div class="stats-label">{{ t('stats.total') }}</div>
|
||||
<div class="stats-value">{{ statsSummary.total }}</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">已通过</div>
|
||||
<div class="stats-label">{{ t('stats.approved') }}</div>
|
||||
<div class="stats-value stats-value-approved">
|
||||
{{ statsSummary.approved }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">待审核</div>
|
||||
<div class="stats-label">{{ t('stats.pending') }}</div>
|
||||
<div class="stats-value stats-value-pending">{{ statsSummary.pending }}</div>
|
||||
</div>
|
||||
<div class="stats-item">
|
||||
<div class="stats-label">已拒绝</div>
|
||||
<div class="stats-label">{{ t('stats.rejected') }}</div>
|
||||
<div class="stats-value stats-value-rejected">
|
||||
{{ statsSummary.rejected }}
|
||||
</div>
|
||||
@@ -45,7 +45,7 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">评论数趋势</h3>
|
||||
<h3 class="card-title">{{ t('stats.trend') }}</h3>
|
||||
<div class="chart-tabs">
|
||||
<button
|
||||
class="chart-tab"
|
||||
@@ -53,7 +53,7 @@
|
||||
type="button"
|
||||
@click="changeChartRange('7')"
|
||||
>
|
||||
最近 7 天
|
||||
{{ t('stats.last7Days') }}
|
||||
</button>
|
||||
<button
|
||||
class="chart-tab"
|
||||
@@ -61,11 +61,11 @@
|
||||
type="button"
|
||||
@click="changeChartRange('30')"
|
||||
>
|
||||
最近 30 天
|
||||
{{ t('stats.last30Days') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="statsLoading" class="page-hint">加载中...</div>
|
||||
<div v-if="statsLoading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="statsError" class="page-error">{{ statsError }}</div>
|
||||
<div class="chart-wrapper">
|
||||
<div ref="chartEl" class="chart"></div>
|
||||
@@ -74,20 +74,20 @@
|
||||
|
||||
<div class="card">
|
||||
<div class="card-title-row">
|
||||
<h3 class="card-title">按站点统计</h3>
|
||||
<h3 class="card-title">{{ t('stats.bySite') }}</h3>
|
||||
</div>
|
||||
<div v-if="statsLoading" class="page-hint">加载中...</div>
|
||||
<div v-if="statsLoading" class="page-hint">{{ t('common.loading') }}</div>
|
||||
<div v-else-if="statsError" class="page-error">{{ statsError }}</div>
|
||||
<div v-else-if="domainStats.length === 0" class="page-hint">暂无评论数据</div>
|
||||
<div v-else-if="domainStats.length === 0" class="page-hint">{{ t('stats.noData') }}</div>
|
||||
<div v-else class="domain-stats-layout">
|
||||
<div class="domain-table-wrapper">
|
||||
<div class="domain-table">
|
||||
<div class="domain-table-header">
|
||||
<div class="domain-cell domain-cell-domain">域名</div>
|
||||
<div class="domain-cell">总数</div>
|
||||
<div class="domain-cell">已通过</div>
|
||||
<div class="domain-cell">待审核</div>
|
||||
<div class="domain-cell">已拒绝</div>
|
||||
<div class="domain-cell domain-cell-domain">{{ t('stats.table.domain') }}</div>
|
||||
<div class="domain-cell">{{ t('stats.table.total') }}</div>
|
||||
<div class="domain-cell">{{ t('stats.table.approved') }}</div>
|
||||
<div class="domain-cell">{{ t('stats.table.pending') }}</div>
|
||||
<div class="domain-cell">{{ t('stats.table.rejected') }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="item in domainStats"
|
||||
@@ -113,10 +113,13 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, onBeforeUnmount, ref, nextTick, watch, inject } from "vue";
|
||||
import type { Ref } from "vue";
|
||||
import { useI18n } from "vue-i18n";
|
||||
import * as echarts from "echarts";
|
||||
import { fetchCommentStats } from "../../api/admin";
|
||||
import { useSite } from "../../composables/useSite";
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
type DomainStat = {
|
||||
domain: string;
|
||||
total: number;
|
||||
|
||||
Reference in New Issue
Block a user