feat: add initial project setup with config, models, and assets

This commit introduces the initial project setup including configuration files, API models, and necessary assets. The changes include:
- Added Prettier and PostCSS configuration files
- Included favicon and public assets like SVGs
- Set up Next.js and theme provider configurations
- Added TypeScript models for API endpoints and responses
This commit is contained in:
Daniel Luiz Alves
2025-04-07 16:14:18 -03:00
parent da64d65401
commit 9e35d27497
315 changed files with 19708 additions and 0 deletions

41
apps/app/.gitignore vendored Normal file
View File

@@ -0,0 +1,41 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*
# env files (can opt-in for committing if needed)
.env*
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts

4
apps/app/.prettierignore Normal file
View File

@@ -0,0 +1,4 @@
/node_modules
/.next
/out
/build

16
apps/app/.prettierrc.json Normal file
View File

@@ -0,0 +1,16 @@
{
"printWidth": 120,
"singleQuote": false,
"tabWidth": 2,
"trailingComma": "es5",
"plugins": ["@ianvs/prettier-plugin-sort-imports", "prettier-plugin-sort-json"],
"importOrder": [
"^(react/(.*)$)|^(react$)",
"^(next/(.*)$)|^(next$)",
"<THIRD_PARTY_MODULES>",
"",
"^@/(.*)$",
"^[./]"
],
"importOrderParserPlugins": ["typescript", "jsx", "decorators-legacy"]
}

21
apps/app/components.json Normal file
View File

@@ -0,0 +1,21 @@
{
"$schema": "https://ui.shadcn.com/schema.json",
"style": "new-york",
"rsc": true,
"tsx": true,
"tailwind": {
"config": "",
"css": "src/app/globals.css",
"baseColor": "neutral",
"cssVariables": true,
"prefix": ""
},
"aliases": {
"components": "@/components",
"utils": "@/lib/utils",
"ui": "@/components/ui",
"lib": "@/lib",
"hooks": "@/hooks"
},
"iconLibrary": "lucide"
}

View File

@@ -0,0 +1,66 @@
/* eslint-disable import/no-anonymous-default-export */
import path from "node:path";
import { fileURLToPath } from "node:url";
import { FlatCompat } from "@eslint/eslintrc";
import js from "@eslint/js";
import typescriptEslintEslintPlugin from "@typescript-eslint/eslint-plugin";
import tsParser from "@typescript-eslint/parser";
import prettier from "eslint-plugin-prettier";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
baseDirectory: __dirname,
recommendedConfig: js.configs.recommended,
allConfig: js.configs.all,
});
export default [
...compat.extends("next", "next/core-web-vitals", "prettier"),
{
plugins: {
prettier,
},
rules: {
"prettier/prettier": "error",
camelcase: "off",
"import/prefer-default-export": "off",
"react/jsx-filename-extension": "off",
"react/jsx-props-no-spreading": "off",
"react/no-unused-prop-types": "off",
"react/require-default-props": "off",
"react/no-unescaped-entities": "off",
"import/extensions": [
"error",
"ignorePackages",
{
ts: "never",
tsx: "never",
js: "never",
jsx: "never",
},
],
},
},
...compat.extends("plugin:@typescript-eslint/recommended", "prettier").map((config) => ({
...config,
files: ["**/*.+(ts|tsx)"],
})),
{
files: ["**/*.+(ts|tsx)"],
plugins: {
"@typescript-eslint": typescriptEslintEslintPlugin,
},
languageOptions: {
parser: tsParser,
},
rules: {
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-module-boundary-types": "off",
"no-use-before-define": [0],
"@typescript-eslint/no-use-before-define": [1],
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-var-requires": "off",
},
},
];

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "مرحبا بك",
"signInToContinue": "قم بتسجيل الدخول للمتابعة",
"emailLabel": "البريد الإلكتروني",
"emailPlaceholder": "أدخل بريدك الإلكتروني",
"passwordLabel": "كلمة المرور",
"passwordPlaceholder": "أدخل كلمة المرور",
"signIn": "تسجيل الدخول",
"signingIn": "جاري تسجيل الدخول...",
"forgotPassword": "نسيت كلمة المرور؟",
"pageTitle": "تسجيل الدخول"
},
"errors": {
"invalidCredentials": "بريد إلكتروني أو كلمة مرور غير صحيحة",
"userNotFound": "المستخدم غير موجود",
"accountLocked": "تم قفل الحساب. يرجى المحاولة لاحقًا",
"unexpectedError": "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى"
},
"validation": {
"invalidEmail": "عنوان بريد إلكتروني غير صالح",
"passwordMinLength": "يجب أن تحتوي كلمة المرور على 6 أحرف على الأقل",
"firstNameRequired": "الاسم الأول مطلوب",
"lastNameRequired": "اسم العائلة مطلوب",
"usernameLength": "يجب أن يحتوي اسم المستخدم على 3 أحرف على الأقل",
"usernameSpaces": "لا يمكن أن يحتوي اسم المستخدم على فراغات",
"passwordLength": "يجب أن تحتوي كلمة المرور على 8 أحرف على الأقل",
"passwordsMatch": "كلمتا المرور غير متطابقتين",
"emailRequired": "البريد الإلكتروني مطلوب",
"passwordRequired": "كلمة المرور مطلوبة"
},
"fileSelector": {
"availableFiles": "الملفات المتاحة ({{count}})",
"shareFiles": "مشاركة الملفات ({{count}})",
"searchPlaceholder": "ابحث عن الملفات...",
"noMatchingFiles": "لا توجد ملفات مطابقة",
"noAvailableFiles": "لا توجد ملفات متاحة",
"noFilesInShare": "لا توجد ملفات للمشاركة",
"saveChanges": "احفظ التغييرات"
},
"recipientSelector": {
"emailPlaceholder": "أدخل بريد المستلم الإلكتروني",
"add": "أضف",
"recipients": "المستلمون ({{count}})",
"notifyAll": "أبلغ الجميع",
"noRecipients": "لم يتم إضافة أي مستلمين بعد",
"addSuccess": "تم إضافة المستلم بنجاح",
"addError": "فشل في إضافة المستلم",
"removeSuccess": "تم إزالة المستلم بنجاح",
"removeError": "فشل في إزالة المستلم",
"sendingNotifications": "جاري إرسال الإشعارات...",
"notifySuccess": "تم إعلام المستلمين بنجاح",
"notifyError": "فشل في إعلام المستلمين"
},
"navigation": {
"dashboard": "لوحة التحكم"
},
"common": {
"loading": "جاري التحميل، يرجى الانتظار...",
"cancel": "إلغاء",
"save": "حفظ",
"delete": "حذف",
"close": "إغلاق",
"download": "تنزيل",
"unexpectedError": "حدث خطأ غير متوقع. يرجى المحاولة مرة أخرى.",
"yes": "نعم",
"no": "لا",
"dashboard": "لوحة التحكم"
},
"createShare": {
"title": "إنشاء مشاركة",
"nameLabel": "اسم المشاركة",
"expirationLabel": "تاريخ الانتهاء",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "أقصى عدد للمشاهدات",
"maxViewsPlaceholder": "اتركه فارغاً للمحدودية غير المحدودة",
"passwordProtection": "حماية بكلمة المرور",
"passwordLabel": "كلمة المرور",
"create": "إنشاء المشاركة",
"success": "تم إنشاء المشاركة بنجاح",
"error": "فشل في إنشاء المشاركة"
},
"fileActions": {
"editFile": "تعديل الملف",
"nameLabel": "الاسم",
"namePlaceholder": "أدخل اسمًا جديدًا",
"extension": "الامتداد",
"descriptionLabel": "الوصف",
"descriptionPlaceholder": "أدخل وصف الملف",
"deleteFile": "حذف الملف",
"deleteConfirmation": "هل أنت متأكد أنك تريد حذف \"{{fileName}}\"؟",
"deleteWarning": "هذا الإجراء لا يمكن التراجع عنه."
},
"filePreview": {
"loading": "جاري تحميل المعاينة...",
"notAvailable": "المعاينة غير متوفرة",
"downloadToView": "قم بتنزيل الملف لعرض المحتوى",
"audioNotSupported": "المتصفح لا يدعم عنصر الصوت",
"videoNotSupported": "المتصفح لا يدعم عنصر الفيديو",
"loadError": "فشل في تحميل المعاينة",
"downloadError": "فشل في تنزيل الملف"
},
"generateShareLink": {
"generateTitle": "إنشاء رابط المشاركة",
"updateTitle": "تحديث رابط المشاركة",
"generateDescription": "أنشئ رابطاً لمشاركة ملفاتك",
"updateDescription": "قم بتحديث اللقب لهذا الرابط",
"aliasPlaceholder": "أدخل لقبًا",
"linkReady": "رابط المشاركة جاهز:",
"generateButton": "إنشاء الرابط",
"updateButton": "تحديث الرابط",
"copyButton": "نسخ الرابط",
"success": "تم إنشاء الرابط بنجاح",
"error": "فشل في إنشاء الرابط",
"copied": "تم نسخ الرابط إلى الحافظة"
},
"shareActions": {
"deleteTitle": "حذف المشاركة",
"deleteConfirmation": "هل أنت متأكد من رغبتك في حذف هذه المشاركة؟ هذا الإجراء لا يمكن التراجع عنه.",
"editTitle": "تعديل المشاركة",
"nameLabel": "اسم المشاركة",
"expirationLabel": "تاريخ الانتهاء",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "أقصى عدد للمشاهدات",
"maxViewsPlaceholder": "اتركه فارغاً للمحدودية غير المحدودة",
"passwordProtection": "محمي بكلمة المرور",
"passwordLabel": "كلمة المرور",
"passwordPlaceholder": "أدخل كلمة المرور",
"newPasswordLabel": "كلمة مرور جديدة (اتركه فارغاً للاحتفاظ بالحالي)",
"newPasswordPlaceholder": "أدخل كلمة مرور جديدة",
"manageFilesTitle": "إدارة الملفات",
"manageRecipientsTitle": "إدارة المستلمين",
"editSuccess": "تم تحديث المشاركة بنجاح",
"editError": "فشل في تحديث المشاركة"
},
"shareDetails": {
"title": "تفاصيل المشاركة",
"subtitle": "معلومات مفصلة عن هذه المشاركة",
"basicInfo": "المعلومات الأساسية",
"name": "الاسم",
"untitled": "بدون عنوان",
"views": "المشاهدات",
"dates": "التواريخ",
"created": "تم الإنشاء",
"expires": "تنتهي",
"never": "أبدًا",
"security": "الأمان",
"passwordProtected": "محمي بكلمة المرور",
"publicAccess": "الوصول العام",
"maxViews": "أقصى عدد للمشاهدات: {{count}}",
"files": "الملفات ({{count}})",
"recipients": "المستلمون ({{count}})",
"notAvailable": "غير متوفر",
"invalidDate": "تاريخ غير صالح",
"loadError": "فشل في تحميل تفاصيل المشاركة"
},
"uploadFile": {
"title": "رفع الملف",
"selectFile": "اضغط لاختيار ملف",
"preview": "المعاينة",
"uploadProgress": "تقدم الرفع",
"upload": "رفع",
"success": "تم رفع الملف بنجاح",
"error": "فشل في رفع الملف"
},
"filesTable": {
"ariaLabel": "جدول الملفات",
"columns": {
"name": "الاسم",
"description": "الوصف",
"size": "الحجم",
"createdAt": "تاريخ الإنشاء",
"updatedAt": "تاريخ التحديث",
"actions": "الإجراءات"
},
"actions": {
"menu": "قائمة إجراءات الملف",
"preview": "المعاينة",
"edit": "تعديل",
"download": "تنزيل",
"delete": "حذف"
}
},
"sharesTable": {
"ariaLabel": "جدول المشاركات",
"never": "أبدًا",
"columns": {
"name": "الاسم",
"createdAt": "تاريخ الإنشاء",
"expiresAt": "تاريخ الانتهاء",
"status": "الحالة",
"security": "الأمان",
"files": "الملفات",
"recipients": "المستلمون",
"actions": "الإجراءات"
},
"status": {
"neverExpires": "لا تنتهي",
"active": "نشطة",
"expired": "منتهية"
},
"security": {
"protected": "محمي",
"public": "عام"
},
"filesCount": "{{count}} ملف",
"recipientsCount": "{{count}} مستلم",
"actions": {
"menu": "قائمة إجراءات المشاركة",
"edit": "تعديل",
"manageFiles": "إدارة الملفات",
"manageRecipients": "إدارة المستلمين",
"viewDetails": "عرض التفاصيل",
"generateLink": "إنشاء الرابط",
"editLink": "تعديل الرابط",
"copyLink": "نسخ الرابط",
"notifyRecipients": "إعلام المستلمين",
"delete": "حذف"
}
},
"footer": {
"poweredBy": "مدعوم من",
"kyanHomepage": "الصفحة الرئيسية لـ Kyantech"
},
"fileManager": {
"downloadError": "فشل في تنزيل الملف",
"updateSuccess": "تم تحديث الملف بنجاح",
"updateError": "فشل في تحديث الملف",
"deleteSuccess": "تم حذف الملف بنجاح",
"deleteError": "فشل في حذف الملف"
},
"shareManager": {
"deleteSuccess": "تم حذف المشاركة بنجاح",
"deleteError": "فشل في حذف المشاركة",
"updateSuccess": "تم تحديث المشاركة بنجاح",
"updateError": "فشل في تحديث المشاركة",
"filesUpdateSuccess": "تم تحديث الملفات بنجاح",
"filesUpdateError": "فشل في تحديث الملفات",
"recipientsUpdateSuccess": "تم تحديث المستلمين بنجاح",
"recipientsUpdateError": "فشل في تحديث المستلمين",
"linkGenerateSuccess": "تم إنشاء رابط المشاركة بنجاح",
"linkGenerateError": "فشل في إنشاء رابط المشاركة",
"notifyLoading": "جاري إرسال الإشعارات...",
"notifySuccess": "تم إعلام المستلمين بنجاح",
"notifyError": "فشل في إعلام المستلمين"
},
"quickAccess": {
"files": {
"title": "ملفاتي",
"description": "الوصول إلى الملفات المرفوعة وإدارتها"
},
"shares": {
"title": "مشاركاتي",
"description": "عرض وإدارة الملفات المشتركة"
}
},
"recentFiles": {
"title": "الرفع الأخير",
"viewAll": "عرض الكل",
"uploadFile": "رفع ملف",
"noFiles": "لم يتم رفع أي ملفات بعد"
},
"recentShares": {
"title": "المشاركات الأخيرة",
"viewAll": "عرض الكل",
"createShare": "إنشاء مشاركة",
"noShares": "لم يتم إنشاء أي مشاركات بعد",
"createFirst": "أنشئ مشاركتك الأولى"
},
"storageUsage": {
"title": "استخدام التخزين",
"ariaLabel": "شريط تقدم استخدام التخزين",
"used": "المستخدمة: {{size}}",
"available": "المتاحة: {{size}}"
},
"dashboard": {
"loadError": "فشل في تحميل بيانات لوحة التحكم",
"linkCopied": "تم نسخ الرابط إلى الحافظة",
"pageTitle": "لوحة التحكم",
"breadcrumb": "لوحة التحكم"
},
"emptyState": {
"noFiles": "لم يتم رفع أي ملفات بعد",
"uploadFile": "رفع ملف"
},
"files": {
"title": "كل الملفات",
"uploadFile": "رفع ملف",
"loadError": "فشل في تحميل الملفات",
"pageTitle": "ملفاتي",
"breadcrumb": "ملفاتي"
},
"searchBar": {
"placeholder": "ابحث عن الملفات...",
"results": "تم العثور على {{filtered}} من {{total}} ملف"
},
"forgotPassword": {
"emailLabel": "البريد الإلكتروني",
"emailPlaceholder": "أدخل بريدك الإلكتروني",
"sending": "جاري الإرسال...",
"submit": "أرسل تعليمات إعادة التعيين",
"backToLogin": "العودة إلى تسجيل الدخول",
"title": "نسيت كلمة المرور",
"description": "أدخل بريدك الإلكتروني وسنرسل لك تعليمات إعادة تعيين كلمة المرور.",
"resetInstructions": "تم إرسال تعليمات إعادة التعيين إلى بريدك الإلكتروني",
"pageTitle": "نسيت كلمة المرور"
},
"home": {
"description": "البديل مفتوح المصدر لـ WeTransfer. شارك ملفاتك بأمان، دون تتبع أو قيود.",
"documentation": "التوثيق",
"starOnGithub": "ضع نجمة على GitHub",
"privacyMessage": "مصمم مع مراعاة الخصوصية. ملفاتك قبل الرفع متاحة فقط لأولئك الذين لديهم رابط المشاركة. مجاني ومفتوح المصدر دائمًا.",
"header": {
"fileSharing": "مشاركة الملفات",
"tagline": "بسيط ومجاني"
},
"pageTitle": "الصفحة الرئيسية"
},
"profile": {
"password": {
"title": "تغيير كلمة المرور",
"newPassword": "كلمة مرور جديدة",
"confirmPassword": "تأكيد كلمة المرور الجديدة",
"updateButton": "تحديث كلمة المرور"
},
"form": {
"title": "معلومات الملف الشخصي",
"firstName": "الاسم الأول",
"lastName": "اسم العائلة",
"username": "اسم المستخدم",
"email": "البريد الإلكتروني",
"updateButton": "تحديث الملف الشخصي"
},
"header": {
"title": "الملف الشخصي",
"subtitle": "إدارة معلوماتك الشخصية وكلمة المرور"
},
"picture": {
"title": "صورة الملف الشخصي",
"description": "انقر على أيقونة الكاميرا لتغيير صورة الملف الشخصي",
"uploadPhoto": "رفع صورة",
"removePhoto": "حذف الصورة"
},
"errors": {
"loadFailed": "فشل في تحميل بيانات المستخدم",
"updateFailed": "فشل في تحديث الملف الشخصي",
"passwordFailed": "فشل في تحديث كلمة المرور",
"imageFailed": "فشل في تحديث صورة الملف الشخصي",
"imageRemoveFailed": "فشل في حذف صورة الملف الشخصي"
},
"messages": {
"noChanges": "لا توجد تغييرات للحفظ",
"updateSuccess": "تم تحديث الملف الشخصي بنجاح",
"fillPasswords": "يرجى ملء كلا حقلي كلمة المرور",
"passwordSuccess": "تم تحديث كلمة المرور بنجاح",
"imageSuccess": "تم تحديث صورة الملف الشخصي بنجاح",
"imageRemoved": "تم حذف صورة الملف الشخصي بنجاح"
},
"pageTitle": "الملف الشخصي"
},
"resetPassword": {
"pageTitle": "إعادة تعيين كلمة المرور",
"header": {
"title": "إعادة تعيين كلمة المرور",
"description": "أدخل كلمة المرور الجديدة أدناه"
},
"form": {
"newPassword": "كلمة مرور جديدة",
"newPasswordPlaceholder": "أدخل كلمة المرور الجديدة",
"confirmPassword": "تأكيد كلمة المرور الجديدة",
"confirmPasswordPlaceholder": "أدخل تأكيد كلمة المرور الجديدة",
"resetting": "جاري إعادة تعيين كلمة المرور...",
"submit": "إعادة تعيين كلمة المرور",
"backToLogin": "العودة إلى تسجيل الدخول"
},
"messages": {
"success": "تم إعادة تعيين كلمة المرور بنجاح"
},
"errors": {
"serverError": "فشل في إعادة تعيين كلمة المرور. يرجى المحاولة مرة أخرى.",
"invalidToken": "رمز إعادة التعيين غير صالح أو مفقود"
}
},
"settings": {
"groups": {
"defaultDescription": "خيارات التكوين",
"general": {
"title": "عام",
"description": "إعدادات التطبيق الأساسية"
},
"email": {
"title": "البريد الإلكتروني",
"description": "تكوين خادم البريد الإلكتروني"
},
"security": {
"title": "الأمان",
"description": "إعدادات الأمان والمصادقة"
},
"storage": {
"title": "التخزين",
"description": "تكوين تخزين الملفات"
}
},
"fields": {
"noDescription": "لا يوجد وصف متاح",
"appLogo": {
"title": "شعار التطبيق",
"description": "صورة شعار التطبيق"
},
"appName": {
"title": "اسم التطبيق",
"description": "اسم التطبيق الذي يظهر للمستخدمين"
},
"appDescription": {
"title": "وصف التطبيق",
"description": "وصف مختصر للتطبيق"
},
"showHomePage": {
"title": "عرض الصفحة الرئيسية",
"description": "عرض الصفحة الرئيسية بعد التثبيت"
},
"smtpEnabled": {
"title": "تمكين SMTP",
"description": "تمكين أو تعطيل وظيفة البريد الإلكتروني عبر SMTP"
},
"smtpHost": {
"title": "خادم SMTP",
"description": "عنوان خادم SMTP"
},
"smtpPort": {
"title": "منفذ SMTP",
"description": "منفذ خادم SMTP"
},
"smtpUser": {
"title": "مستخدم SMTP",
"description": "اسم المستخدم لمصادقة SMTP"
},
"smtpPass": {
"title": "كلمة مرور SMTP",
"description": "كلمة المرور لمصادقة SMTP"
},
"smtpFromName": {
"title": "اسم المرسل",
"description": "الاسم الظاهر في الرسائل المرسلة"
},
"smtpFromEmail": {
"title": "البريد الإلكتروني للمرسل",
"description": "عنوان البريد الإلكتروني للمرسل"
},
"maxLoginAttempts": {
"title": "أقصى محاولات تسجيل دخول",
"description": "الحد الأقصى لمحاولات تسجيل الدخول قبل الحظر"
},
"loginBlockDuration": {
"title": "مدة حظر تسجيل الدخول",
"description": "مدة الحظر (بالثواني) بعد تجاوز الحد الأقصى للمحاولات"
},
"passwordMinLength": {
"title": "الحد الأدنى لطول كلمة المرور",
"description": "الحد الأدنى لعدد الأحرف في كلمة المرور"
},
"passwordResetTokenExpiration": {
"title": "انتهاء صلاحية رمز إعادة التعيين",
"description": "مدة صلاحية رمز إعادة تعيين كلمة المرور (بالثواني)"
},
"maxFileSize": {
"title": "أقصى حجم للملف",
"description": "الحد الأقصى لحجم الملف المسموح به للرفع (بالبايت)"
},
"maxTotalStoragePerUser": {
"title": "أقصى تخزين لكل مستخدم",
"description": "الحد الإجمالي للتخزين لكل مستخدم (بالبايت)"
}
},
"buttons": {
"save": "احفظ {{group}}"
},
"errors": {
"loadFailed": "فشل في تحميل الإعدادات",
"updateFailed": "فشل في تحديث الإعدادات"
},
"messages": {
"noChanges": "لا توجد تغييرات للحفظ",
"updateSuccess": "تم تحديث إعدادات {{group}} بنجاح"
},
"title": "الإعدادات",
"breadcrumb": "الإعدادات",
"pageTitle": "الإعدادات"
},
"share": {
"errors": {
"invalidPassword": "كلمة مرور غير صحيحة. يرجى المحاولة مرة أخرى.",
"loadFailed": "فشل في تحميل المشاركة",
"downloadFailed": "فشل في تنزيل الملف"
},
"messages": {
"downloadStarted": "بدأ التنزيل"
},
"password": {
"title": "مشاركة محمية بكلمة المرور",
"protected": "هذه المشاركة محمية بكلمة مرور",
"incorrect": "كلمة المرور غير صحيحة. يرجى المحاولة مرة أخرى.",
"label": "كلمة المرور",
"placeholder": "أدخل كلمة مرور المشاركة",
"submit": "إرسال"
},
"details": {
"untitled": "بدون عنوان",
"created": "تم الإنشاء: {{date}}",
"expires": "تنتهي: {{date}}"
},
"notFound": {
"title": "لم يتم العثور على المشاركة",
"description": "قد يكون تم حذف هذه المشاركة أو انتهت صلاحيتها."
},
"pageTitle": "المشاركة"
},
"shares": {
"errors": {
"loadFailed": "فشل في تحميل المشاركات",
"notifyFailed": "فشل في إعلام المستلمين",
"smtpConfigFailed": "فشل في تحميل إعدادات SMTP"
},
"messages": {
"linkCopied": "تم نسخ الرابط إلى الحافظة",
"recipientsNotified": "تم إعلام المستلمين بنجاح"
},
"empty": {
"message": "لم يتم إنشاء أي مشاركات بعد",
"createButton": "إنشاء مشاركة"
},
"header": {
"title": "مشاركاتي",
"myShares": "مشاركاتي"
},
"search": {
"title": "كل المشاركات",
"createButton": "إنشاء مشاركة",
"placeholder": "ابحث عن المشاركات...",
"results": "تم العثور على {{filtered}} من {{total}} مشاركات"
},
"pageTitle": "المشاركات"
},
"users": {
"modes": {
"create": "إنشاء",
"edit": "تعديل"
},
"errors": {
"loadFailed": "فشل في تحميل المستخدمين",
"submitFailed": "فشل في {{mode}} المستخدم",
"deleteFailed": "فشل في حذف المستخدم",
"statusUpdateFailed": "فشل في تحديث حالة المستخدم"
},
"messages": {
"createSuccess": "تم إنشاء المستخدم بنجاح",
"updateSuccess": "تم تحديث المستخدم بنجاح",
"deleteSuccess": "تم حذف المستخدم بنجاح",
"activateSuccess": "تم تفعيل المستخدم بنجاح",
"deactivateSuccess": "تم إلغاء تفعيل المستخدم بنجاح"
},
"actions": {
"edit": "تعديل",
"activate": "تفعيل",
"deactivate": "إلغاء التفعيل",
"delete": "حذف"
},
"delete": {
"title": "تأكيد حذف المستخدم",
"confirmation": "هل أنت متأكد من أنك تريد حذف {{firstName}} {{lastName}}؟ هذا الإجراء لا يمكن التراجع عنه.",
"confirm": "حذف المستخدم"
},
"form": {
"titleCreate": "إضافة مستخدم جديد",
"titleEdit": "تعديل المستخدم",
"firstName": "الاسم الأول",
"lastName": "اسم العائلة",
"username": "اسم المستخدم",
"email": "البريد الإلكتروني",
"password": "كلمة المرور",
"newPassword": "كلمة مرور جديدة (اختياري)",
"passwordPlaceholder": "اتركه فارغاً للاحتفاظ بكلمة المرور الحالية",
"role": "الدور",
"roleUser": "مستخدم",
"roleAdmin": "مسؤول",
"create": "إنشاء",
"save": "حفظ"
},
"status": {
"title": "تأكيد تغيير الحالة",
"confirmation": "هل أنت متأكد من أنك تريد {{action}} المستخدم {{firstName}} {{lastName}}؟",
"activate": "تفعيل",
"deactivate": "إلغاء التفعيل",
"user": "المستخدم"
},
"header": {
"title": "إدارة المستخدمين",
"addUser": "إضافة مستخدم",
"management": "إدارة المستخدمين"
},
"table": {
"user": "المستخدم",
"email": "البريد الإلكتروني",
"status": "الحالة",
"role": "الدور",
"actions": "الإجراءات",
"active": "مفعل",
"inactive": "غير مفعل",
"admin": "مسؤول",
"userr": "مستخدم"
}
},
"logo": {
"labels": {
"appLogo": "شعار التطبيق"
},
"buttons": {
"upload": "رفع الشعار",
"remove": "حذف الشعار"
},
"messages": {
"uploadSuccess": "تم رفع الشعار بنجاح",
"removeSuccess": "تم حذف الشعار بنجاح"
},
"errors": {
"uploadFailed": "فشل في رفع الشعار",
"removeFailed": "فشل في حذف الشعار"
}
},
"navbar": {
"logoAlt": "شعار التطبيق",
"profileMenu": "قائمة الملف الشخصي",
"profile": "الملف الشخصي",
"settings": "الإعدادات",
"usersManagement": "إدارة المستخدمين",
"logout": "تسجيل الخروج"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Willkommen zu",
"signInToContinue": "Melden Sie sich an, um fortzufahren",
"emailLabel": "E-Mail-Adresse",
"emailPlaceholder": "Geben Sie Ihre E-Mail-Adresse ein",
"passwordLabel": "Passwort",
"passwordPlaceholder": "Geben Sie Ihr Passwort ein",
"signIn": "Anmelden",
"signingIn": "Melde an...",
"forgotPassword": "Passwort vergessen?",
"pageTitle": "Anmeldung"
},
"errors": {
"invalidCredentials": "Ungültige E-Mail oder Passwort",
"userNotFound": "Benutzer nicht gefunden",
"accountLocked": "Konto gesperrt. Bitte versuchen Sie es später erneut",
"unexpectedError": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut"
},
"validation": {
"invalidEmail": "Ungültige E-Mail-Adresse",
"passwordMinLength": "Das Passwort muss mindestens 6 Zeichen lang sein",
"firstNameRequired": "Vorname ist erforderlich",
"lastNameRequired": "Nachname ist erforderlich",
"usernameLength": "Der Benutzername muss mindestens 3 Zeichen lang sein",
"usernameSpaces": "Der Benutzername darf keine Leerzeichen enthalten",
"passwordLength": "Das Passwort muss mindestens 8 Zeichen lang sein",
"passwordsMatch": "Die Passwörter stimmen nicht überein",
"emailRequired": "E-Mail ist erforderlich",
"passwordRequired": "Passwort ist erforderlich"
},
"fileSelector": {
"availableFiles": "Verfügbare Dateien ({{count}})",
"shareFiles": "Dateien teilen ({{count}})",
"searchPlaceholder": "Dateien suchen...",
"noMatchingFiles": "Keine übereinstimmenden Dateien",
"noAvailableFiles": "Keine Dateien verfügbar",
"noFilesInShare": "Keine Dateien in der Freigabe",
"saveChanges": "Änderungen speichern"
},
"recipientSelector": {
"emailPlaceholder": "Empfänger-E-Mail eingeben",
"add": "Hinzufügen",
"recipients": "Empfänger ({{count}})",
"notifyAll": "Alle benachrichtigen",
"noRecipients": "Noch keine Empfänger hinzugefügt",
"addSuccess": "Empfänger erfolgreich hinzugefügt",
"addError": "Fehler beim Hinzufügen des Empfängers",
"removeSuccess": "Empfänger erfolgreich entfernt",
"removeError": "Fehler beim Entfernen des Empfängers",
"sendingNotifications": "Benachrichtigungen werden gesendet...",
"notifySuccess": "Empfänger erfolgreich benachrichtigt",
"notifyError": "Fehler beim Benachrichtigen der Empfänger"
},
"navigation": {
"dashboard": "Übersicht"
},
"common": {
"loading": "Lädt, bitte warten...",
"cancel": "Abbrechen",
"save": "Speichern",
"delete": "Löschen",
"close": "Schließen",
"download": "Herunterladen",
"unexpectedError": "Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es erneut.",
"yes": "Ja",
"no": "Nein",
"dashboard": "Übersicht"
},
"createShare": {
"title": "Freigabe erstellen",
"nameLabel": "Freigabename",
"expirationLabel": "Ablaufdatum",
"expirationPlaceholder": "MM/TT/JJJJ SS:MM",
"maxViewsLabel": "Maximale Ansichten",
"maxViewsPlaceholder": "Leer lassen für unbegrenzt",
"passwordProtection": "Passwortgeschützt",
"passwordLabel": "Passwort",
"create": "Freigabe erstellen",
"success": "Freigabe erfolgreich erstellt",
"error": "Fehler beim Erstellen der Freigabe"
},
"fileActions": {
"editFile": "Datei bearbeiten",
"nameLabel": "Name",
"namePlaceholder": "Neuen Namen eingeben",
"extension": "Erweiterung",
"descriptionLabel": "Beschreibung",
"descriptionPlaceholder": "Dateibeschreibung eingeben",
"deleteFile": "Datei löschen",
"deleteConfirmation": "Sind Sie sicher, dass Sie \"{{fileName}}\" löschen möchten?",
"deleteWarning": "Diese Aktion kann nicht rückgängig gemacht werden."
},
"filePreview": {
"loading": "Vorschau wird geladen...",
"notAvailable": "Vorschau nicht verfügbar",
"downloadToView": "Datei herunterladen, um den Inhalt anzuzeigen",
"audioNotSupported": "Ihr Browser unterstützt das Audioelement nicht",
"videoNotSupported": "Ihr Browser unterstützt das Videoelement nicht",
"loadError": "Fehler beim Laden der Vorschau",
"downloadError": "Fehler beim Herunterladen der Datei"
},
"generateShareLink": {
"generateTitle": "Freigabelink generieren",
"updateTitle": "Freigabelink aktualisieren",
"generateDescription": "Erstellen Sie einen Link, um Ihre Dateien zu teilen",
"updateDescription": "Aktualisieren Sie den Alias für diesen Freigabelink",
"aliasPlaceholder": "Alias eingeben",
"linkReady": "Ihr Freigabelink ist fertig:",
"generateButton": "Link generieren",
"updateButton": "Link aktualisieren",
"copyButton": "Link kopieren",
"success": "Link erfolgreich generiert",
"error": "Fehler beim Generieren des Links",
"copied": "Link in die Zwischenablage kopiert"
},
"shareActions": {
"deleteTitle": "Freigabe löschen",
"deleteConfirmation": "Sind Sie sicher, dass Sie diese Freigabe löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
"editTitle": "Freigabe bearbeiten",
"nameLabel": "Freigabename",
"expirationLabel": "Ablaufdatum",
"expirationPlaceholder": "MM/TT/JJJJ SS:MM",
"maxViewsLabel": "Maximale Ansichten",
"maxViewsPlaceholder": "Leer lassen für unbegrenzt",
"passwordProtection": "Passwortgeschützt",
"passwordLabel": "Passwort",
"passwordPlaceholder": "Passwort eingeben",
"newPasswordLabel": "Neues Passwort (leer lassen, um das aktuelle zu behalten)",
"newPasswordPlaceholder": "Neues Passwort eingeben",
"manageFilesTitle": "Dateien verwalten",
"manageRecipientsTitle": "Empfänger verwalten",
"editSuccess": "Freigabe erfolgreich aktualisiert",
"editError": "Fehler beim Aktualisieren der Freigabe"
},
"shareDetails": {
"title": "Freigabedetails",
"subtitle": "Detaillierte Informationen zu dieser Freigabe",
"basicInfo": "Grundinformationen",
"name": "Name",
"untitled": "Ohne Titel",
"views": "Aufrufe",
"dates": "Daten",
"created": "Erstellt",
"expires": "Läuft ab",
"never": "Nie",
"security": "Sicherheit",
"passwordProtected": "Passwortgeschützt",
"publicAccess": "Öffentlicher Zugriff",
"maxViews": "Maximale Ansichten: {{count}}",
"files": "Dateien ({{count}})",
"recipients": "Empfänger ({{count}})",
"notAvailable": "N/V",
"invalidDate": "Ungültiges Datum",
"loadError": "Fehler beim Laden der Freigabedetails"
},
"uploadFile": {
"title": "Datei hochladen",
"selectFile": "Klicken Sie, um eine Datei auszuwählen",
"preview": "Vorschau",
"uploadProgress": "Upload-Fortschritt",
"upload": "Hochladen",
"success": "Datei erfolgreich hochgeladen",
"error": "Fehler beim Hochladen der Datei"
},
"filesTable": {
"ariaLabel": "Dateitabelle",
"columns": {
"name": "NAME",
"description": "BESCHREIBUNG",
"size": "GRÖSSE",
"createdAt": "ERSTELLT AM",
"updatedAt": "AKTUALISIERT AM",
"actions": "AKTIONEN"
},
"actions": {
"menu": "Dateiaktionsmenü",
"preview": "Vorschau",
"edit": "Bearbeiten",
"download": "Herunterladen",
"delete": "Löschen"
}
},
"sharesTable": {
"ariaLabel": "Freigabetabelle",
"never": "Nie",
"columns": {
"name": "NAME",
"createdAt": "ERSTELLT AM",
"expiresAt": "LÄUFT AB",
"status": "STATUS",
"security": "SICHERHEIT",
"files": "DATEIEN",
"recipients": "EMPFÄNGER",
"actions": "AKTIONEN"
},
"status": {
"neverExpires": "Läuft nie ab",
"active": "Aktiv",
"expired": "Abgelaufen"
},
"security": {
"protected": "Geschützt",
"public": "Öffentlich"
},
"filesCount": "{{count}} Dateien",
"recipientsCount": "{{count}} Empfänger",
"actions": {
"menu": "Freigabeaktionsmenü",
"edit": "Bearbeiten",
"manageFiles": "Dateien verwalten",
"manageRecipients": "Empfänger verwalten",
"viewDetails": "Details anzeigen",
"generateLink": "Link generieren",
"editLink": "Link bearbeiten",
"copyLink": "Link kopieren",
"notifyRecipients": "Empfänger benachrichtigen",
"delete": "Löschen"
}
},
"footer": {
"poweredBy": "Powered by",
"kyanHomepage": "Kyantech Homepage"
},
"fileManager": {
"downloadError": "Fehler beim Herunterladen der Datei",
"updateSuccess": "Datei erfolgreich aktualisiert",
"updateError": "Fehler beim Aktualisieren der Datei",
"deleteSuccess": "Datei erfolgreich gelöscht",
"deleteError": "Fehler beim Löschen der Datei"
},
"shareManager": {
"deleteSuccess": "Freigabe erfolgreich gelöscht",
"deleteError": "Fehler beim Löschen der Freigabe",
"updateSuccess": "Freigabe erfolgreich aktualisiert",
"updateError": "Fehler beim Aktualisieren der Freigabe",
"filesUpdateSuccess": "Dateien erfolgreich aktualisiert",
"filesUpdateError": "Fehler beim Aktualisieren der Dateien",
"recipientsUpdateSuccess": "Empfänger erfolgreich aktualisiert",
"recipientsUpdateError": "Fehler beim Aktualisieren der Empfänger",
"linkGenerateSuccess": "Freigabelink erfolgreich generiert",
"linkGenerateError": "Fehler beim Generieren des Freigabelinks",
"notifyLoading": "Benachrichtigungen werden gesendet...",
"notifySuccess": "Empfänger erfolgreich benachrichtigt",
"notifyError": "Fehler beim Benachrichtigen der Empfänger"
},
"quickAccess": {
"files": {
"title": "Meine Dateien",
"description": "Zugriff und Verwaltung Ihrer hochgeladenen Dateien"
},
"shares": {
"title": "Meine Freigaben",
"description": "Anzeigen und Verwalten Ihrer geteilten Dateien"
}
},
"recentFiles": {
"title": "Kürzlich hochgeladen",
"viewAll": "Alle anzeigen",
"uploadFile": "Datei hochladen",
"noFiles": "Noch keine Dateien hochgeladen"
},
"recentShares": {
"title": "Kürzlich geteilte",
"viewAll": "Alle anzeigen",
"createShare": "Freigabe erstellen",
"noShares": "Noch keine Freigaben erstellt",
"createFirst": "Erstellen Sie Ihre erste Freigabe"
},
"storageUsage": {
"title": "Speichernutzung",
"ariaLabel": "Fortschrittsbalken der Speichernutzung",
"used": "{{size}} genutzt",
"available": "{{size}} verfügbar"
},
"dashboard": {
"loadError": "Fehler beim Laden der Dashboard-Daten",
"linkCopied": "Link in die Zwischenablage kopiert",
"pageTitle": "Übersicht",
"breadcrumb": "Übersicht"
},
"emptyState": {
"noFiles": "Noch keine Dateien hochgeladen",
"uploadFile": "Datei hochladen"
},
"files": {
"title": "Alle Dateien",
"uploadFile": "Datei hochladen",
"loadError": "Fehler beim Laden der Dateien",
"pageTitle": "Meine Dateien",
"breadcrumb": "Meine Dateien"
},
"searchBar": {
"placeholder": "Dateien suchen...",
"results": "Gefunden {{filtered}} von {{total}} Dateien"
},
"forgotPassword": {
"emailLabel": "E-Mail-Adresse",
"emailPlaceholder": "Geben Sie Ihre E-Mail-Adresse ein",
"sending": "Wird gesendet...",
"submit": "Anweisungen zum Zurücksetzen senden",
"backToLogin": "Zurück zur Anmeldung",
"title": "Passwort vergessen",
"description": "Geben Sie Ihre E-Mail-Adresse ein und wir senden Ihnen Anweisungen zum Zurücksetzen Ihres Passworts.",
"resetInstructions": "Anweisungen zum Zurücksetzen wurden an Ihre E-Mail gesendet",
"pageTitle": "Passwort vergessen"
},
"home": {
"description": "Die Open-Source-Alternative zu WeTransfer. Teilen Sie Dateien sicher, ohne Tracking oder Einschränkungen.",
"documentation": "Dokumentation",
"starOnGithub": "Auf GitHub Sternchen vergeben",
"privacyMessage": "Mit Blick auf den Datenschutz entwickelt. Ihre Dateien sind vor dem Hochladen nur für diejenigen zugänglich, die den Freigabelink haben. Immer kostenlos und Open Source.",
"header": {
"fileSharing": "Dateifreigabe",
"tagline": "einfach und kostenlos"
},
"pageTitle": "Startseite"
},
"profile": {
"password": {
"title": "Passwort ändern",
"newPassword": "Neues Passwort",
"confirmPassword": "Neues Passwort bestätigen",
"updateButton": "Passwort aktualisieren"
},
"form": {
"title": "Profilinformationen",
"firstName": "Vorname",
"lastName": "Nachname",
"username": "Benutzername",
"email": "E-Mail",
"updateButton": "Profil aktualisieren"
},
"header": {
"title": "Profil",
"subtitle": "Verwalten Sie Ihre persönlichen Informationen und Ihr Passwort"
},
"picture": {
"title": "Profilbild",
"description": "Klicken Sie auf das Kamerasymbol, um Ihr Profilbild zu ändern",
"uploadPhoto": "Foto hochladen",
"removePhoto": "Foto entfernen"
},
"errors": {
"loadFailed": "Fehler beim Laden der Benutzerdaten",
"updateFailed": "Fehler beim Aktualisieren des Profils",
"passwordFailed": "Fehler beim Aktualisieren des Passworts",
"imageFailed": "Fehler beim Aktualisieren des Profilbilds",
"imageRemoveFailed": "Fehler beim Entfernen des Profilbilds"
},
"messages": {
"noChanges": "Keine Änderungen zum Speichern",
"updateSuccess": "Profil erfolgreich aktualisiert",
"fillPasswords": "Bitte beide Passwortfelder ausfüllen",
"passwordSuccess": "Passwort erfolgreich aktualisiert",
"imageSuccess": "Profilbild erfolgreich aktualisiert",
"imageRemoved": "Profilbild erfolgreich entfernt"
},
"pageTitle": "Profil"
},
"resetPassword": {
"pageTitle": "Passwort zurücksetzen",
"header": {
"title": "Passwort zurücksetzen",
"description": "Geben Sie unten Ihr neues Passwort ein"
},
"form": {
"newPassword": "Neues Passwort",
"newPasswordPlaceholder": "Geben Sie Ihr neues Passwort ein",
"confirmPassword": "Neues Passwort bestätigen",
"confirmPasswordPlaceholder": "Bestätigen Sie Ihr neues Passwort",
"resetting": "Passwort wird zurückgesetzt...",
"submit": "Passwort zurücksetzen",
"backToLogin": "Zurück zur Anmeldung"
},
"messages": {
"success": "Passwort erfolgreich zurückgesetzt"
},
"errors": {
"serverError": "Fehler beim Zurücksetzen des Passworts. Bitte versuchen Sie es erneut.",
"invalidToken": "Ungültiges oder fehlendes Zurücksetzungstoken"
}
},
"settings": {
"groups": {
"defaultDescription": "Konfigurationsoptionen",
"general": {
"title": "Allgemein",
"description": "Grundlegende Anwendungseinstellungen"
},
"email": {
"title": "E-Mail",
"description": "Konfiguration des E-Mail-Servers"
},
"security": {
"title": "Sicherheit",
"description": "Sicherheits- und Authentifizierungseinstellungen"
},
"storage": {
"title": "Speicher",
"description": "Konfiguration des Dateispeichers"
}
},
"fields": {
"noDescription": "Keine Beschreibung verfügbar",
"appLogo": {
"title": "Anwendungslogo",
"description": "Logo-Bild der Anwendung"
},
"appName": {
"title": "Anwendungsname",
"description": "Anwendungsname, der den Benutzern angezeigt wird"
},
"appDescription": {
"title": "Anwendungsbeschreibung",
"description": "Kurze Beschreibung der Anwendung"
},
"showHomePage": {
"title": "Startseite anzeigen",
"description": "Startseite nach der Installation anzeigen"
},
"smtpEnabled": {
"title": "SMTP aktiviert",
"description": "SMTP-E-Mail-Funktionalität aktivieren oder deaktivieren"
},
"smtpHost": {
"title": "SMTP-Server",
"description": "Adresse des SMTP-Servers"
},
"smtpPort": {
"title": "SMTP-Port",
"description": "Port des SMTP-Servers"
},
"smtpUser": {
"title": "SMTP-Benutzer",
"description": "Benutzername für die SMTP-Authentifizierung"
},
"smtpPass": {
"title": "SMTP-Passwort",
"description": "Passwort für die SMTP-Authentifizierung"
},
"smtpFromName": {
"title": "Absendername",
"description": "Anzeigename für gesendete E-Mails"
},
"smtpFromEmail": {
"title": "Absender-E-Mail",
"description": "E-Mail-Adresse des Absenders"
},
"maxLoginAttempts": {
"title": "Maximale Anmeldeversuche",
"description": "Maximale Anzahl von Anmeldeversuchen, bevor gesperrt wird"
},
"loginBlockDuration": {
"title": "Sperrdauer",
"description": "Dauer (in Sekunden) der Sperre nach Überschreiten der Versuche"
},
"passwordMinLength": {
"title": "Minimale Passwortlänge",
"description": "Minimale Anzahl an Zeichen für Passwörter"
},
"passwordResetTokenExpiration": {
"title": "Ablauf des Reset-Tokens",
"description": "Gültigkeitsdauer (in Sekunden) des Passwort-Reset-Tokens"
},
"maxFileSize": {
"title": "Maximale Dateigröße",
"description": "Maximal erlaubte Dateigröße für Uploads (in Bytes)"
},
"maxTotalStoragePerUser": {
"title": "Maximaler Speicher pro Benutzer",
"description": "Gesamtspeicherlimit pro Benutzer (in Bytes)"
}
},
"buttons": {
"save": "{{group}} speichern"
},
"errors": {
"loadFailed": "Fehler beim Laden der Einstellungen",
"updateFailed": "Fehler beim Aktualisieren der Einstellungen"
},
"messages": {
"noChanges": "Keine Änderungen zum Speichern",
"updateSuccess": "{{group}}-Einstellungen erfolgreich aktualisiert"
},
"title": "Einstellungen",
"breadcrumb": "Einstellungen",
"pageTitle": "Einstellungen"
},
"share": {
"errors": {
"invalidPassword": "Ungültiges Passwort. Bitte versuchen Sie es erneut.",
"loadFailed": "Fehler beim Laden der Freigabe",
"downloadFailed": "Fehler beim Herunterladen der Datei"
},
"messages": {
"downloadStarted": "Download gestartet"
},
"password": {
"title": "Passwortgeschützte Freigabe",
"protected": "Diese Freigabe ist passwortgeschützt",
"incorrect": "Falsches Passwort. Bitte versuchen Sie es erneut.",
"label": "Passwort",
"placeholder": "Passwort der Freigabe eingeben",
"submit": "Absenden"
},
"details": {
"untitled": "Unbenannte Freigabe",
"created": "Erstellt: {{date}}",
"expires": "Läuft ab: {{date}}"
},
"notFound": {
"title": "Freigabe nicht gefunden",
"description": "Diese Freigabe wurde möglicherweise gelöscht oder ist abgelaufen."
},
"pageTitle": "Freigabe"
},
"shares": {
"errors": {
"loadFailed": "Fehler beim Laden der Freigaben",
"notifyFailed": "Fehler beim Benachrichtigen der Empfänger",
"smtpConfigFailed": "Fehler beim Laden der SMTP-Konfiguration"
},
"messages": {
"linkCopied": "Link in die Zwischenablage kopiert",
"recipientsNotified": "Empfänger erfolgreich benachrichtigt"
},
"empty": {
"message": "Noch keine Freigaben erstellt",
"createButton": "Freigabe erstellen"
},
"header": {
"title": "Meine Freigaben",
"myShares": "Meine Freigaben"
},
"search": {
"title": "Alle Freigaben",
"createButton": "Freigabe erstellen",
"placeholder": "Freigaben suchen...",
"results": "Gefunden {{filtered}} von {{total}} Freigaben"
},
"pageTitle": "Freigaben"
},
"users": {
"modes": {
"create": "erstellen",
"edit": "bearbeiten"
},
"errors": {
"loadFailed": "Fehler beim Laden der Benutzer",
"submitFailed": "Fehler beim {{mode}} des Benutzers",
"deleteFailed": "Fehler beim Löschen des Benutzers",
"statusUpdateFailed": "Fehler beim Aktualisieren des Benutzerstatus"
},
"messages": {
"createSuccess": "Benutzer erfolgreich erstellt",
"updateSuccess": "Benutzer erfolgreich aktualisiert",
"deleteSuccess": "Benutzer erfolgreich gelöscht",
"activateSuccess": "Benutzer erfolgreich aktiviert",
"deactivateSuccess": "Benutzer erfolgreich deaktiviert"
},
"actions": {
"edit": "Bearbeiten",
"activate": "Aktivieren",
"deactivate": "Deaktivieren",
"delete": "Löschen"
},
"delete": {
"title": "Löschen des Benutzers bestätigen",
"confirmation": "Sind Sie sicher, dass Sie den Benutzer {{firstName}} {{lastName}} löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.",
"confirm": "Benutzer löschen"
},
"form": {
"titleCreate": "Neuen Benutzer hinzufügen",
"titleEdit": "Benutzer bearbeiten",
"firstName": "Vorname",
"lastName": "Nachname",
"username": "Benutzername",
"email": "E-Mail",
"password": "Passwort",
"newPassword": "Neues Passwort (optional)",
"passwordPlaceholder": "Leer lassen, um das aktuelle Passwort zu behalten",
"role": "Rolle",
"roleUser": "Benutzer",
"roleAdmin": "Administrator",
"create": "Erstellen",
"save": "Speichern"
},
"status": {
"title": "Statusänderung bestätigen",
"confirmation": "Sind Sie sicher, dass Sie den Benutzer {{firstName}} {{lastName}} {{action}} möchten?",
"activate": "aktivieren",
"deactivate": "deaktivieren",
"user": "Benutzer"
},
"header": {
"title": "Benutzerverwaltung",
"addUser": "Benutzer hinzufügen",
"management": "Benutzerverwaltung"
},
"table": {
"user": "BENUTZER",
"email": "E-MAIL",
"status": "STATUS",
"role": "ROLLE",
"actions": "AKTIONEN",
"active": "Aktiv",
"inactive": "Inaktiv",
"admin": "Administrator",
"userr": "Benutzer"
}
},
"logo": {
"labels": {
"appLogo": "Anwendungslogo"
},
"buttons": {
"upload": "Logo hochladen",
"remove": "Logo entfernen"
},
"messages": {
"uploadSuccess": "Logo erfolgreich hochgeladen",
"removeSuccess": "Logo erfolgreich entfernt"
},
"errors": {
"uploadFailed": "Fehler beim Hochladen des Logos",
"removeFailed": "Fehler beim Entfernen des Logos"
}
},
"navbar": {
"logoAlt": "Anwendungslogo",
"profileMenu": "Profilmenü",
"profile": "Profil",
"settings": "Einstellungen",
"usersManagement": "Benutzerverwaltung",
"logout": "Abmelden"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Welcome to",
"signInToContinue": "Sign in to continue",
"emailLabel": "Email Address",
"emailPlaceholder": "Enter your email",
"passwordLabel": "Password",
"passwordPlaceholder": "Enter your password",
"signIn": "Sign In",
"signingIn": "Signing in...",
"forgotPassword": "Forgot password?",
"pageTitle": "Login"
},
"errors": {
"invalidCredentials": "Invalid email or password",
"userNotFound": "User not found",
"accountLocked": "Account locked. Please try again later",
"unexpectedError": "An unexpected error occurred. Please try again"
},
"validation": {
"invalidEmail": "Invalid email address",
"passwordMinLength": "Password must be at least 6 characters",
"firstNameRequired": "First name is required",
"lastNameRequired": "Last name is required",
"usernameLength": "Username must be at least 3 characters",
"usernameSpaces": "Username cannot contain spaces",
"passwordLength": "Password must be at least 8 characters",
"passwordsMatch": "Passwords do not match",
"emailRequired": "Email is required",
"passwordRequired": "Password is required"
},
"fileSelector": {
"availableFiles": "Available Files ({{count}})",
"shareFiles": "Share Files ({{count}})",
"searchPlaceholder": "Search files...",
"noMatchingFiles": "No matching files",
"noAvailableFiles": "No files available",
"noFilesInShare": "No files in share",
"saveChanges": "Save Changes"
},
"recipientSelector": {
"emailPlaceholder": "Enter recipient email",
"add": "Add",
"recipients": "Recipients ({{count}})",
"notifyAll": "Notify All",
"noRecipients": "No recipients added yet",
"addSuccess": "Recipient added successfully",
"addError": "Failed to add recipient",
"removeSuccess": "Recipient removed successfully",
"removeError": "Failed to remove recipient",
"sendingNotifications": "Sending notifications...",
"notifySuccess": "Recipients notified successfully",
"notifyError": "Failed to notify recipients"
},
"navigation": {
"dashboard": "Dashboard"
},
"common": {
"loading": "Loading, please wait...",
"cancel": "Cancel",
"save": "Save",
"delete": "Delete",
"close": "Close",
"download": "Download",
"unexpectedError": "An unexpected error occurred. Please try again.",
"yes": "Yes",
"no": "No",
"dashboard": "Dashboard"
},
"createShare": {
"title": "Create Share",
"nameLabel": "Share Name",
"expirationLabel": "Expiration Date",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "Max Views",
"maxViewsPlaceholder": "Leave empty for unlimited",
"passwordProtection": "Password Protected",
"passwordLabel": "Password",
"create": "Create Share",
"success": "Share created successfully",
"error": "Failed to create share"
},
"fileActions": {
"editFile": "Edit File",
"nameLabel": "Name",
"namePlaceholder": "Enter new name",
"extension": "Extension",
"descriptionLabel": "Description",
"descriptionPlaceholder": "Enter file description",
"deleteFile": "Delete File",
"deleteConfirmation": "Are you sure you want to delete \"{{fileName}}\"?",
"deleteWarning": "This action cannot be undone."
},
"filePreview": {
"loading": "Loading preview...",
"notAvailable": "Preview not available",
"downloadToView": "Download file to view contents",
"audioNotSupported": "Your browser does not support the audio element",
"videoNotSupported": "Your browser does not support the video element",
"loadError": "Failed to load preview",
"downloadError": "Failed to download file"
},
"generateShareLink": {
"generateTitle": "Generate Share Link",
"updateTitle": "Update Share Link",
"generateDescription": "Generate a link to share your files",
"updateDescription": "Update the alias for this share link",
"aliasPlaceholder": "Enter alias",
"linkReady": "Your share link is ready:",
"generateButton": "Generate Link",
"updateButton": "Update Link",
"copyButton": "Copy Link",
"success": "Link generated successfully",
"error": "Failed to generate link",
"copied": "Link copied to clipboard"
},
"shareActions": {
"deleteTitle": "Delete Share",
"deleteConfirmation": "Are you sure you want to delete this share? This action cannot be undone.",
"editTitle": "Edit Share",
"nameLabel": "Share Name",
"expirationLabel": "Expiration Date",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "Max Views",
"maxViewsPlaceholder": "Leave empty for unlimited",
"passwordProtection": "Password Protected",
"passwordLabel": "Password",
"passwordPlaceholder": "Enter password",
"newPasswordLabel": "New Password (leave empty to keep current)",
"newPasswordPlaceholder": "Enter new password",
"manageFilesTitle": "Manage Files",
"manageRecipientsTitle": "Manage Recipients",
"editSuccess": "Share updated successfully",
"editError": "Failed to update share"
},
"shareDetails": {
"title": "Share Details",
"subtitle": "Detailed information about this share",
"basicInfo": "Basic Information",
"name": "Name",
"untitled": "Untitled",
"views": "Views",
"dates": "Dates",
"created": "Created",
"expires": "Expires",
"never": "Never",
"security": "Security",
"passwordProtected": "Password Protected",
"publicAccess": "Public Access",
"maxViews": "Max Views: {{count}}",
"files": "Files ({{count}})",
"recipients": "Recipients ({{count}})",
"notAvailable": "N/A",
"invalidDate": "Invalid date",
"loadError": "Failed to load share details"
},
"uploadFile": {
"title": "Upload File",
"selectFile": "Click to select a file",
"preview": "Preview",
"uploadProgress": "Upload progress",
"upload": "Upload",
"success": "File uploaded successfully",
"error": "Failed to upload file"
},
"filesTable": {
"ariaLabel": "Files table",
"columns": {
"name": "NAME",
"description": "DESCRIPTION",
"size": "SIZE",
"createdAt": "CREATED AT",
"updatedAt": "UPDATED AT",
"actions": "ACTIONS"
},
"actions": {
"menu": "File actions menu",
"preview": "Preview",
"edit": "Edit",
"download": "Download",
"delete": "Delete"
}
},
"sharesTable": {
"ariaLabel": "Shares table",
"never": "Never",
"columns": {
"name": "NAME",
"createdAt": "CREATED AT",
"expiresAt": "EXPIRES AT",
"status": "STATUS",
"security": "SECURITY",
"files": "FILES",
"recipients": "RECIPIENTS",
"actions": "ACTIONS"
},
"status": {
"neverExpires": "Never Expires",
"active": "Active",
"expired": "Expired"
},
"security": {
"protected": "Protected",
"public": "Public"
},
"filesCount": "{{count}} files",
"recipientsCount": "{{count}} recipients",
"actions": {
"menu": "Share actions menu",
"edit": "Edit",
"manageFiles": "Manage Files",
"manageRecipients": "Manage Recipients",
"viewDetails": "View Details",
"generateLink": "Generate Link",
"editLink": "Edit Link",
"copyLink": "Copy Link",
"notifyRecipients": "Notify Recipients",
"delete": "Delete"
}
},
"footer": {
"poweredBy": "Powered by",
"kyanHomepage": "Kyantech homepage"
},
"fileManager": {
"downloadError": "Failed to download file",
"updateSuccess": "File updated successfully",
"updateError": "Failed to update file",
"deleteSuccess": "File deleted successfully",
"deleteError": "Failed to delete file"
},
"shareManager": {
"deleteSuccess": "Share deleted successfully",
"deleteError": "Failed to delete share",
"updateSuccess": "Share updated successfully",
"updateError": "Failed to update share",
"filesUpdateSuccess": "Files updated successfully",
"filesUpdateError": "Failed to update files",
"recipientsUpdateSuccess": "Recipients updated successfully",
"recipientsUpdateError": "Failed to update recipients",
"linkGenerateSuccess": "Share link generated successfully",
"linkGenerateError": "Failed to generate share link",
"notifyLoading": "Sending notifications...",
"notifySuccess": "Recipients notified successfully",
"notifyError": "Failed to notify recipients"
},
"quickAccess": {
"files": {
"title": "My Files",
"description": "Access and manage your uploaded files"
},
"shares": {
"title": "My Shares",
"description": "View and manage your shared files"
}
},
"recentFiles": {
"title": "Recent Uploads",
"viewAll": "View All",
"uploadFile": "Upload File",
"noFiles": "No files uploaded yet"
},
"recentShares": {
"title": "Recent Shares",
"viewAll": "View All",
"createShare": "Create Share",
"noShares": "No shares created yet",
"createFirst": "Create your first share"
},
"storageUsage": {
"title": "Storage Usage",
"ariaLabel": "Storage usage progress bar",
"used": "{{size}} used",
"available": "{{size}} available"
},
"dashboard": {
"loadError": "Failed to load dashboard data",
"linkCopied": "Link copied to clipboard",
"pageTitle": "Dashboard",
"breadcrumb": "Dashboard"
},
"emptyState": {
"noFiles": "No files uploaded yet",
"uploadFile": "Upload File"
},
"files": {
"title": "All Files",
"uploadFile": "Upload File",
"loadError": "Failed to load files",
"pageTitle": "My Files",
"breadcrumb": "My Files"
},
"searchBar": {
"placeholder": "Search files...",
"results": "Found {{filtered}} of {{total}} files"
},
"forgotPassword": {
"emailLabel": "Email Address",
"emailPlaceholder": "Enter your email",
"sending": "Sending...",
"submit": "Send Reset Instructions",
"backToLogin": "Back to Login",
"title": "Forgot Password",
"description": "Enter your email address and we'll send you instructions to reset your password.",
"resetInstructions": "Reset instructions sent to your email",
"pageTitle": "Forgot Password"
},
"home": {
"description": "The open-source alternative to WeTransfer. Share files securely, without tracking, or limitations.",
"documentation": "Documentation",
"starOnGithub": "Star on GitHub",
"privacyMessage": "Built with privacy in mind. Your files before upload only accessible by those with the sharing link. Forever free and open source.",
"header": {
"fileSharing": "File sharing",
"tagline": "made simple and free"
},
"pageTitle": "Home"
},
"profile": {
"password": {
"title": "Change Password",
"newPassword": "New Password",
"confirmPassword": "Confirm New Password",
"updateButton": "Update Password"
},
"form": {
"title": "Profile Information",
"firstName": "First Name",
"lastName": "Last Name",
"username": "Username",
"email": "Email",
"updateButton": "Update Profile"
},
"header": {
"title": "Profile",
"subtitle": "Manage your personal information and password"
},
"picture": {
"title": "Profile Picture",
"description": "Click the camera icon to change your profile picture",
"uploadPhoto": "Upload Photo",
"removePhoto": "Remove Photo"
},
"errors": {
"loadFailed": "Failed to load user data",
"updateFailed": "Failed to update profile",
"passwordFailed": "Failed to update password",
"imageFailed": "Failed to update profile image",
"imageRemoveFailed": "Failed to remove profile image"
},
"messages": {
"noChanges": "No changes to save",
"updateSuccess": "Profile updated successfully",
"fillPasswords": "Please fill in both password fields",
"passwordSuccess": "Password updated successfully",
"imageSuccess": "Profile image updated successfully",
"imageRemoved": "Profile image removed successfully"
},
"pageTitle": "Profile"
},
"resetPassword": {
"pageTitle": "Reset Password",
"header": {
"title": "Reset Password",
"description": "Enter your new password below"
},
"form": {
"newPassword": "New Password",
"newPasswordPlaceholder": "Enter your new password",
"confirmPassword": "Confirm New Password",
"confirmPasswordPlaceholder": "Confirm your new password",
"resetting": "Resetting Password...",
"submit": "Reset Password",
"backToLogin": "Back to Login"
},
"messages": {
"success": "Password reset successfully"
},
"errors": {
"serverError": "Failed to reset password. Please try again.",
"invalidToken": "Invalid or missing reset token"
}
},
"settings": {
"groups": {
"defaultDescription": "Configuration options",
"general": {
"title": "General",
"description": "Basic application settings"
},
"email": {
"title": "Email",
"description": "Email server configuration"
},
"security": {
"title": "Security",
"description": "Security and authentication settings"
},
"storage": {
"title": "Storage",
"description": "File storage configuration"
}
},
"fields": {
"noDescription": "No description available",
"appLogo": {
"title": "Application Logo",
"description": "Application logo image"
},
"appName": {
"title": "Application Name",
"description": "Application name displayed to users"
},
"appDescription": {
"title": "Application Description",
"description": "Brief description of the application"
},
"showHomePage": {
"title": "Show Home Page",
"description": "Show Home Page after installation"
},
"smtpEnabled": {
"title": "SMTP Enabled",
"description": "Enable or disable SMTP email functionality"
},
"smtpHost": {
"title": "SMTP Server",
"description": "SMTP server address"
},
"smtpPort": {
"title": "SMTP Port",
"description": "SMTP server port"
},
"smtpUser": {
"title": "SMTP Username",
"description": "Username for SMTP authentication"
},
"smtpPass": {
"title": "SMTP Password",
"description": "Password for SMTP authentication"
},
"smtpFromName": {
"title": "Sender Name",
"description": "Display name for sent emails"
},
"smtpFromEmail": {
"title": "Sender Email",
"description": "Sender email address"
},
"maxLoginAttempts": {
"title": "Maximum Login Attempts",
"description": "Maximum number of login attempts before blocking"
},
"loginBlockDuration": {
"title": "Block Duration",
"description": "Duration (in seconds) to block after exceeding attempts"
},
"passwordMinLength": {
"title": "Minimum Password Length",
"description": "Minimum number of characters for passwords"
},
"passwordResetTokenExpiration": {
"title": "Reset Token Expiration",
"description": "Validity time (in seconds) for password reset token"
},
"maxFileSize": {
"title": "Maximum File Size",
"description": "Maximum allowed file size for uploads (in bytes)"
},
"maxTotalStoragePerUser": {
"title": "Maximum Storage Per User",
"description": "Total storage limit per user (in bytes)"
}
},
"buttons": {
"save": "Save {{group}}"
},
"errors": {
"loadFailed": "Failed to load settings",
"updateFailed": "Failed to update settings"
},
"messages": {
"noChanges": "No changes to save",
"updateSuccess": "{{group}} settings updated successfully"
},
"title": "Settings",
"breadcrumb": "Settings",
"pageTitle": "Settings"
},
"share": {
"errors": {
"invalidPassword": "Invalid password. Please try again.",
"loadFailed": "Failed to load share",
"downloadFailed": "Failed to download file"
},
"messages": {
"downloadStarted": "Download started"
},
"password": {
"title": "Password Protected Share",
"protected": "This share is password protected",
"incorrect": "Incorrect password. Please try again.",
"label": "Password",
"placeholder": "Enter share password",
"submit": "Submit"
},
"details": {
"untitled": "Untitled Share",
"created": "Created: {{date}}",
"expires": "Expires: {{date}}"
},
"notFound": {
"title": "Share Not Found",
"description": "This share may have been deleted or expired."
},
"pageTitle": "Share"
},
"shares": {
"errors": {
"loadFailed": "Failed to load shares",
"notifyFailed": "Failed to notify recipients",
"smtpConfigFailed": "Failed to load SMTP configuration"
},
"messages": {
"linkCopied": "Link copied to clipboard",
"recipientsNotified": "Recipients notified successfully"
},
"empty": {
"message": "No shares created yet",
"createButton": "Create Share"
},
"header": {
"title": "My Shares",
"myShares": "My Shares"
},
"search": {
"title": "All Shares",
"createButton": "Create Share",
"placeholder": "Search shares...",
"results": "Found {{filtered}} of {{total}} shares"
},
"pageTitle": "Shares"
},
"users": {
"modes": {
"create": "create",
"edit": "edit"
},
"errors": {
"loadFailed": "Failed to load users",
"submitFailed": "Failed to {{mode}} user",
"deleteFailed": "Failed to delete user",
"statusUpdateFailed": "Failed to update user status"
},
"messages": {
"createSuccess": "User created successfully",
"updateSuccess": "User updated successfully",
"deleteSuccess": "User deleted successfully",
"activateSuccess": "User activated successfully",
"deactivateSuccess": "User deactivated successfully"
},
"actions": {
"edit": "Edit",
"activate": "Activate",
"deactivate": "Deactivate",
"delete": "Delete"
},
"delete": {
"title": "Confirm Delete User",
"confirmation": "Are you sure you want to delete user {{firstName}} {{lastName}}? This action cannot be undone.",
"confirm": "Delete User"
},
"form": {
"titleCreate": "Add New User",
"titleEdit": "Edit User",
"firstName": "First Name",
"lastName": "Last Name",
"username": "Username",
"email": "Email",
"password": "Password",
"newPassword": "New Password (optional)",
"passwordPlaceholder": "Leave blank to keep current password",
"role": "Role",
"roleUser": "User",
"roleAdmin": "Admin",
"create": "Create",
"save": "Save"
},
"status": {
"title": "Confirm Status Change",
"confirmation": "Are you sure you want to {{action}} user {{firstName}} {{lastName}}?",
"activate": "activate",
"deactivate": "deactivate",
"user": "User"
},
"header": {
"title": "User Management",
"addUser": "Add User",
"management": "User Management"
},
"table": {
"user": "USER",
"email": "EMAIL",
"status": "STATUS",
"role": "ROLE",
"actions": "ACTIONS",
"active": "Active",
"inactive": "Inactive",
"admin": "Admin",
"userr": "User"
}
},
"logo": {
"labels": {
"appLogo": "App Logo"
},
"buttons": {
"upload": "Upload Logo",
"remove": "Remove Logo"
},
"messages": {
"uploadSuccess": "Logo uploaded successfully",
"removeSuccess": "Logo removed successfully"
},
"errors": {
"uploadFailed": "Failed to upload logo",
"removeFailed": "Failed to remove logo"
}
},
"navbar": {
"logoAlt": "App Logo",
"profileMenu": "Profile Menu",
"profile": "Profile",
"settings": "Settings",
"usersManagement": "Users Management",
"logout": "Log Out"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Bienvenido a",
"signInToContinue": "Inicia sesión para continuar",
"emailLabel": "Dirección de correo electrónico",
"emailPlaceholder": "Introduce tu correo electrónico",
"passwordLabel": "Contraseña",
"passwordPlaceholder": "Introduce tu contraseña",
"signIn": "Iniciar sesión",
"signingIn": "Iniciando sesión...",
"forgotPassword": "¿Olvidaste tu contraseña?",
"pageTitle": "Iniciar sesión"
},
"errors": {
"invalidCredentials": "Correo electrónico o contraseña inválidos",
"userNotFound": "Usuario no encontrado",
"accountLocked": "Cuenta bloqueada. Por favor, inténtalo de nuevo más tarde",
"unexpectedError": "Ocurrió un error inesperado. Por favor, inténtalo de nuevo"
},
"validation": {
"invalidEmail": "Dirección de correo electrónico no válida",
"passwordMinLength": "La contraseña debe tener al menos 6 caracteres",
"firstNameRequired": "Se requiere el nombre",
"lastNameRequired": "Se requiere el apellido",
"usernameLength": "El nombre de usuario debe tener al menos 3 caracteres",
"usernameSpaces": "El nombre de usuario no puede contener espacios",
"passwordLength": "La contraseña debe tener al menos 8 caracteres",
"passwordsMatch": "Las contraseñas no coinciden",
"emailRequired": "Se requiere el correo electrónico",
"passwordRequired": "Se requiere la contraseña"
},
"fileSelector": {
"availableFiles": "Archivos disponibles ({{count}})",
"shareFiles": "Compartir archivos ({{count}})",
"searchPlaceholder": "Buscar archivos...",
"noMatchingFiles": "No hay archivos que coincidan",
"noAvailableFiles": "No hay archivos disponibles",
"noFilesInShare": "No hay archivos compartidos",
"saveChanges": "Guardar cambios"
},
"recipientSelector": {
"emailPlaceholder": "Introduce el correo del destinatario",
"add": "Agregar",
"recipients": "Destinatarios ({{count}})",
"notifyAll": "Notificar a todos",
"noRecipients": "Aún no se han agregado destinatarios",
"addSuccess": "Destinatario agregado exitosamente",
"addError": "Error al agregar el destinatario",
"removeSuccess": "Destinatario eliminado exitosamente",
"removeError": "Error al eliminar el destinatario",
"sendingNotifications": "Enviando notificaciones...",
"notifySuccess": "Destinatarios notificados exitosamente",
"notifyError": "Error al notificar a los destinatarios"
},
"navigation": {
"dashboard": "Panel de control"
},
"common": {
"loading": "Cargando, por favor espera...",
"cancel": "Cancelar",
"save": "Guardar",
"delete": "Eliminar",
"close": "Cerrar",
"download": "Descargar",
"unexpectedError": "Ocurrió un error inesperado. Por favor, inténtalo de nuevo.",
"yes": "Sí",
"no": "No",
"dashboard": "Panel de control"
},
"createShare": {
"title": "Crear compartición",
"nameLabel": "Nombre de la compartición",
"expirationLabel": "Fecha de expiración",
"expirationPlaceholder": "MM/DD/AAAA HH:MM",
"maxViewsLabel": "Máximo de visualizaciones",
"maxViewsPlaceholder": "Dejar vacío para ilimitado",
"passwordProtection": "Protección por contraseña",
"passwordLabel": "Contraseña",
"create": "Crear compartición",
"success": "Compartición creada exitosamente",
"error": "Error al crear la compartición"
},
"fileActions": {
"editFile": "Editar archivo",
"nameLabel": "Nombre",
"namePlaceholder": "Introduce un nuevo nombre",
"extension": "Extensión",
"descriptionLabel": "Descripción",
"descriptionPlaceholder": "Introduce una descripción del archivo",
"deleteFile": "Eliminar archivo",
"deleteConfirmation": "¿Estás seguro de que deseas eliminar \"{{fileName}}\"?",
"deleteWarning": "Esta acción no se puede deshacer."
},
"filePreview": {
"loading": "Cargando vista previa...",
"notAvailable": "Vista previa no disponible",
"downloadToView": "Descarga el archivo para ver su contenido",
"audioNotSupported": "Tu navegador no soporta el elemento de audio",
"videoNotSupported": "Tu navegador no soporta el elemento de video",
"loadError": "Error al cargar la vista previa",
"downloadError": "Error al descargar el archivo"
},
"generateShareLink": {
"generateTitle": "Generar enlace de compartición",
"updateTitle": "Actualizar enlace de compartición",
"generateDescription": "Genera un enlace para compartir tus archivos",
"updateDescription": "Actualiza el alias para este enlace de compartición",
"aliasPlaceholder": "Introduce un alias",
"linkReady": "Tu enlace de compartición está listo:",
"generateButton": "Generar enlace",
"updateButton": "Actualizar enlace",
"copyButton": "Copiar enlace",
"success": "Enlace generado exitosamente",
"error": "Error al generar el enlace",
"copied": "Enlace copiado al portapapeles"
},
"shareActions": {
"deleteTitle": "Eliminar compartición",
"deleteConfirmation": "¿Estás seguro de que deseas eliminar esta compartición? Esta acción no se puede deshacer.",
"editTitle": "Editar compartición",
"nameLabel": "Nombre de la compartición",
"expirationLabel": "Fecha de expiración",
"expirationPlaceholder": "MM/DD/AAAA HH:MM",
"maxViewsLabel": "Máximo de visualizaciones",
"maxViewsPlaceholder": "Dejar vacío para ilimitado",
"passwordProtection": "Protegido con contraseña",
"passwordLabel": "Contraseña",
"passwordPlaceholder": "Introduce la contraseña",
"newPasswordLabel": "Nueva contraseña (dejar vacío para mantener la actual)",
"newPasswordPlaceholder": "Introduce la nueva contraseña",
"manageFilesTitle": "Gestionar archivos",
"manageRecipientsTitle": "Gestionar destinatarios",
"editSuccess": "Compartición actualizada exitosamente",
"editError": "Error al actualizar la compartición"
},
"shareDetails": {
"title": "Detalles de la compartición",
"subtitle": "Información detallada sobre esta compartición",
"basicInfo": "Información básica",
"name": "Nombre",
"untitled": "Sin título",
"views": "Visualizaciones",
"dates": "Fechas",
"created": "Creada",
"expires": "Expira",
"never": "Nunca",
"security": "Seguridad",
"passwordProtected": "Protegido con contraseña",
"publicAccess": "Acceso público",
"maxViews": "Máximo de visualizaciones: {{count}}",
"files": "Archivos ({{count}})",
"recipients": "Destinatarios ({{count}})",
"notAvailable": "N/D",
"invalidDate": "Fecha inválida",
"loadError": "Error al cargar los detalles de la compartición"
},
"uploadFile": {
"title": "Subir archivo",
"selectFile": "Haz clic para seleccionar un archivo",
"preview": "Vista previa",
"uploadProgress": "Progreso de la subida",
"upload": "Subir",
"success": "Archivo subido exitosamente",
"error": "Error al subir el archivo"
},
"filesTable": {
"ariaLabel": "Tabla de archivos",
"columns": {
"name": "NOMBRE",
"description": "DESCRIPCIÓN",
"size": "TAMAÑO",
"createdAt": "CREADO",
"updatedAt": "ACTUALIZADO",
"actions": "ACCIONES"
},
"actions": {
"menu": "Menú de acciones del archivo",
"preview": "Vista previa",
"edit": "Editar",
"download": "Descargar",
"delete": "Eliminar"
}
},
"sharesTable": {
"ariaLabel": "Tabla de comparticiones",
"never": "Nunca",
"columns": {
"name": "NOMBRE",
"createdAt": "CREADO",
"expiresAt": "EXPIRA",
"status": "ESTADO",
"security": "SEGURIDAD",
"files": "ARCHIVOS",
"recipients": "DESTINATARIOS",
"actions": "ACCIONES"
},
"status": {
"neverExpires": "Nunca expira",
"active": "Activa",
"expired": "Expirada"
},
"security": {
"protected": "Protegida",
"public": "Pública"
},
"filesCount": "{{count}} archivos",
"recipientsCount": "{{count}} destinatarios",
"actions": {
"menu": "Menú de acciones de la compartición",
"edit": "Editar",
"manageFiles": "Gestionar archivos",
"manageRecipients": "Gestionar destinatarios",
"viewDetails": "Ver detalles",
"generateLink": "Generar enlace",
"editLink": "Editar enlace",
"copyLink": "Copiar enlace",
"notifyRecipients": "Notificar destinatarios",
"delete": "Eliminar"
}
},
"footer": {
"poweredBy": "Desarrollado por",
"kyanHomepage": "Página principal de Kyantech"
},
"fileManager": {
"downloadError": "Error al descargar el archivo",
"updateSuccess": "Archivo actualizado exitosamente",
"updateError": "Error al actualizar el archivo",
"deleteSuccess": "Archivo eliminado exitosamente",
"deleteError": "Error al eliminar el archivo"
},
"shareManager": {
"deleteSuccess": "Compartición eliminada exitosamente",
"deleteError": "Error al eliminar la compartición",
"updateSuccess": "Compartición actualizada exitosamente",
"updateError": "Error al actualizar la compartición",
"filesUpdateSuccess": "Archivos actualizados exitosamente",
"filesUpdateError": "Error al actualizar los archivos",
"recipientsUpdateSuccess": "Destinatarios actualizados exitosamente",
"recipientsUpdateError": "Error al actualizar los destinatarios",
"linkGenerateSuccess": "Enlace de compartición generado exitosamente",
"linkGenerateError": "Error al generar el enlace de compartición",
"notifyLoading": "Enviando notificaciones...",
"notifySuccess": "Destinatarios notificados exitosamente",
"notifyError": "Error al notificar a los destinatarios"
},
"quickAccess": {
"files": {
"title": "Mis archivos",
"description": "Accede y gestiona tus archivos subidos"
},
"shares": {
"title": "Mis comparticiones",
"description": "Visualiza y gestiona tus archivos compartidos"
}
},
"recentFiles": {
"title": "Subidas recientes",
"viewAll": "Ver todo",
"uploadFile": "Subir archivo",
"noFiles": "Aún no se han subido archivos"
},
"recentShares": {
"title": "Comparticiones recientes",
"viewAll": "Ver todo",
"createShare": "Crear compartición",
"noShares": "Aún no se han creado comparticiones",
"createFirst": "Crea tu primera compartición"
},
"storageUsage": {
"title": "Uso de almacenamiento",
"ariaLabel": "Barra de progreso del uso de almacenamiento",
"used": "{{size}} usados",
"available": "{{size}} disponibles"
},
"dashboard": {
"loadError": "Error al cargar los datos del tablero",
"linkCopied": "Enlace copiado al portapapeles",
"pageTitle": "Panel de control",
"breadcrumb": "Panel de control"
},
"emptyState": {
"noFiles": "Aún no se han subido archivos",
"uploadFile": "Subir archivo"
},
"files": {
"title": "Todos los archivos",
"uploadFile": "Subir archivo",
"loadError": "Error al cargar los archivos",
"pageTitle": "Mis archivos",
"breadcrumb": "Mis archivos"
},
"searchBar": {
"placeholder": "Buscar archivos...",
"results": "Se encontraron {{filtered}} de {{total}} archivos"
},
"forgotPassword": {
"emailLabel": "Dirección de correo electrónico",
"emailPlaceholder": "Introduce tu correo electrónico",
"sending": "Enviando...",
"submit": "Enviar instrucciones de restablecimiento",
"backToLogin": "Volver a iniciar sesión",
"title": "Recuperar contraseña",
"description": "Introduce tu dirección de correo electrónico y te enviaremos instrucciones para restablecer tu contraseña.",
"resetInstructions": "Instrucciones de restablecimiento enviadas a tu correo electrónico",
"pageTitle": "Recuperar contraseña"
},
"home": {
"description": "La alternativa de código abierto a WeTransfer. Comparte archivos de forma segura, sin rastreo ni limitaciones.",
"documentation": "Documentación",
"starOnGithub": "Dale una estrella en GitHub",
"privacyMessage": "Construido con la privacidad en mente. Tus archivos antes de la subida son accesibles solo para aquellos con el enlace de compartición. Siempre libre y de código abierto.",
"header": {
"fileSharing": "Compartir archivos",
"tagline": "simple y gratuito"
},
"pageTitle": "Inicio"
},
"profile": {
"password": {
"title": "Cambiar contraseña",
"newPassword": "Nueva contraseña",
"confirmPassword": "Confirmar nueva contraseña",
"updateButton": "Actualizar contraseña"
},
"form": {
"title": "Información del perfil",
"firstName": "Nombre",
"lastName": "Apellido",
"username": "Nombre de usuario",
"email": "Correo electrónico",
"updateButton": "Actualizar perfil"
},
"header": {
"title": "Perfil",
"subtitle": "Gestiona tu información personal y contraseña"
},
"picture": {
"title": "Foto de perfil",
"description": "Haz clic en el icono de la cámara para cambiar tu foto de perfil",
"uploadPhoto": "Subir foto",
"removePhoto": "Eliminar foto"
},
"errors": {
"loadFailed": "Error al cargar los datos del usuario",
"updateFailed": "Error al actualizar el perfil",
"passwordFailed": "Error al actualizar la contraseña",
"imageFailed": "Error al actualizar la imagen del perfil",
"imageRemoveFailed": "Error al eliminar la imagen del perfil"
},
"messages": {
"noChanges": "No hay cambios para guardar",
"updateSuccess": "Perfil actualizado exitosamente",
"fillPasswords": "Por favor, completa ambos campos de contraseña",
"passwordSuccess": "Contraseña actualizada exitosamente",
"imageSuccess": "Imagen de perfil actualizada exitosamente",
"imageRemoved": "Imagen de perfil eliminada exitosamente"
},
"pageTitle": "Perfil"
},
"resetPassword": {
"pageTitle": "Restablecer contraseña",
"header": {
"title": "Restablecer contraseña",
"description": "Introduce tu nueva contraseña abajo"
},
"form": {
"newPassword": "Nueva contraseña",
"newPasswordPlaceholder": "Introduce tu nueva contraseña",
"confirmPassword": "Confirmar nueva contraseña",
"confirmPasswordPlaceholder": "Confirma tu nueva contraseña",
"resetting": "Restableciendo contraseña...",
"submit": "Restablecer contraseña",
"backToLogin": "Volver a iniciar sesión"
},
"messages": {
"success": "Contraseña restablecida exitosamente"
},
"errors": {
"serverError": "Error al restablecer la contraseña. Por favor, inténtalo de nuevo.",
"invalidToken": "Token de restablecimiento inválido o ausente"
}
},
"settings": {
"groups": {
"defaultDescription": "Opciones de configuración",
"general": {
"title": "General",
"description": "Configuraciones básicas de la aplicación"
},
"email": {
"title": "Correo electrónico",
"description": "Configuración del servidor de correo electrónico"
},
"security": {
"title": "Seguridad",
"description": "Configuraciones de seguridad y autenticación"
},
"storage": {
"title": "Almacenamiento",
"description": "Configuración del almacenamiento de archivos"
}
},
"fields": {
"noDescription": "No hay descripción disponible",
"appLogo": {
"title": "Logo de la aplicación",
"description": "Imagen del logo de la aplicación"
},
"appName": {
"title": "Nombre de la aplicación",
"description": "Nombre de la aplicación mostrado a los usuarios"
},
"appDescription": {
"title": "Descripción de la aplicación",
"description": "Breve descripción de la aplicación"
},
"showHomePage": {
"title": "Mostrar página de inicio",
"description": "Mostrar la página de inicio después de la instalación"
},
"smtpEnabled": {
"title": "SMTP activado",
"description": "Habilitar o deshabilitar la funcionalidad de correo electrónico SMTP"
},
"smtpHost": {
"title": "Servidor SMTP",
"description": "Dirección del servidor SMTP"
},
"smtpPort": {
"title": "Puerto SMTP",
"description": "Puerto del servidor SMTP"
},
"smtpUser": {
"title": "Usuario SMTP",
"description": "Nombre de usuario para la autenticación SMTP"
},
"smtpPass": {
"title": "Contraseña SMTP",
"description": "Contraseña para la autenticación SMTP"
},
"smtpFromName": {
"title": "Nombre del remitente",
"description": "Nombre mostrado para los correos enviados"
},
"smtpFromEmail": {
"title": "Correo del remitente",
"description": "Dirección de correo del remitente"
},
"maxLoginAttempts": {
"title": "Máximo de intentos de inicio de sesión",
"description": "Número máximo de intentos antes de bloquear"
},
"loginBlockDuration": {
"title": "Duración del bloqueo",
"description": "Duración (en segundos) del bloqueo tras exceder los intentos"
},
"passwordMinLength": {
"title": "Longitud mínima de contraseña",
"description": "Número mínimo de caracteres para las contraseñas"
},
"passwordResetTokenExpiration": {
"title": "Expiración del token de restablecimiento",
"description": "Tiempo de validez (en segundos) para el token de restablecimiento de contraseña"
},
"maxFileSize": {
"title": "Tamaño máximo de archivo",
"description": "Tamaño máximo permitido para subir archivos (en bytes)"
},
"maxTotalStoragePerUser": {
"title": "Almacenamiento máximo por usuario",
"description": "Límite total de almacenamiento por usuario (en bytes)"
}
},
"buttons": {
"save": "Guardar {{group}}"
},
"errors": {
"loadFailed": "Error al cargar la configuración",
"updateFailed": "Error al actualizar la configuración"
},
"messages": {
"noChanges": "No hay cambios para guardar",
"updateSuccess": "Configuración de {{group}} actualizada exitosamente"
},
"title": "Configuración",
"breadcrumb": "Configuración",
"pageTitle": "Configuración"
},
"share": {
"errors": {
"invalidPassword": "Contraseña inválida. Por favor, inténtalo de nuevo.",
"loadFailed": "Error al cargar la compartición",
"downloadFailed": "Error al descargar el archivo"
},
"messages": {
"downloadStarted": "Descarga iniciada"
},
"password": {
"title": "Compartición protegida por contraseña",
"protected": "Esta compartición está protegida por contraseña",
"incorrect": "Contraseña incorrecta. Por favor, inténtalo de nuevo.",
"label": "Contraseña",
"placeholder": "Introduce la contraseña de la compartición",
"submit": "Enviar"
},
"details": {
"untitled": "Compartición sin título",
"created": "Creada: {{date}}",
"expires": "Expira: {{date}}"
},
"notFound": {
"title": "Compartición no encontrada",
"description": "Esta compartición puede haber sido eliminada o haber expirado."
},
"pageTitle": "Compartición"
},
"shares": {
"errors": {
"loadFailed": "Error al cargar las comparticiones",
"notifyFailed": "Error al notificar a los destinatarios",
"smtpConfigFailed": "Error al cargar la configuración SMTP"
},
"messages": {
"linkCopied": "Enlace copiado al portapapeles",
"recipientsNotified": "Destinatarios notificados exitosamente"
},
"empty": {
"message": "Aún no se han creado comparticiones",
"createButton": "Crear compartición"
},
"header": {
"title": "Mis comparticiones",
"myShares": "Mis comparticiones"
},
"search": {
"title": "Todas las comparticiones",
"createButton": "Crear compartición",
"placeholder": "Buscar comparticiones...",
"results": "Se encontraron {{filtered}} de {{total}} comparticiones"
},
"pageTitle": "Comparticiones"
},
"users": {
"modes": {
"create": "crear",
"edit": "editar"
},
"errors": {
"loadFailed": "Error al cargar los usuarios",
"submitFailed": "Error al {{mode}} el usuario",
"deleteFailed": "Error al eliminar el usuario",
"statusUpdateFailed": "Error al actualizar el estado del usuario"
},
"messages": {
"createSuccess": "Usuario creado exitosamente",
"updateSuccess": "Usuario actualizado exitosamente",
"deleteSuccess": "Usuario eliminado exitosamente",
"activateSuccess": "Usuario activado exitosamente",
"deactivateSuccess": "Usuario desactivado exitosamente"
},
"actions": {
"edit": "Editar",
"activate": "Activar",
"deactivate": "Desactivar",
"delete": "Eliminar"
},
"delete": {
"title": "Confirmar eliminación del usuario",
"confirmation": "¿Estás seguro de que deseas eliminar al usuario {{firstName}} {{lastName}}? Esta acción no se puede deshacer.",
"confirm": "Eliminar usuario"
},
"form": {
"titleCreate": "Agregar nuevo usuario",
"titleEdit": "Editar usuario",
"firstName": "Nombre",
"lastName": "Apellido",
"username": "Nombre de usuario",
"email": "Correo electrónico",
"password": "Contraseña",
"newPassword": "Nueva contraseña (opcional)",
"passwordPlaceholder": "Dejar en blanco para mantener la contraseña actual",
"role": "Rol",
"roleUser": "Usuario",
"roleAdmin": "Administrador",
"create": "Crear",
"save": "Guardar"
},
"status": {
"title": "Confirmar cambio de estado",
"confirmation": "¿Estás seguro de que deseas {{action}} al usuario {{firstName}} {{lastName}}?",
"activate": "activar",
"deactivate": "desactivar",
"user": "Usuario"
},
"header": {
"title": "Gestión de usuarios",
"addUser": "Agregar usuario",
"management": "Gestión de usuarios"
},
"table": {
"user": "USUARIO",
"email": "CORREO",
"status": "ESTADO",
"role": "ROL",
"actions": "ACCIONES",
"active": "Activo",
"inactive": "Inactivo",
"admin": "Administrador",
"userr": "Usuario"
}
},
"logo": {
"labels": {
"appLogo": "Logo de la aplicación"
},
"buttons": {
"upload": "Subir logo",
"remove": "Eliminar logo"
},
"messages": {
"uploadSuccess": "Logo subido exitosamente",
"removeSuccess": "Logo eliminado exitosamente"
},
"errors": {
"uploadFailed": "Error al subir el logo",
"removeFailed": "Error al eliminar el logo"
}
},
"navbar": {
"logoAlt": "Logo de la aplicación",
"profileMenu": "Menú de perfil",
"profile": "Perfil",
"settings": "Configuración",
"usersManagement": "Gestión de usuarios",
"logout": "Cerrar sesión"
}
}

View File

@@ -0,0 +1,637 @@
{
"login": {
"welcome": "Bienvenue à",
"signInToContinue": "Connectez-vous pour continuer",
"emailLabel": "Adresse e-mail",
"emailPlaceholder": "Entrez votre e-mail",
"passwordLabel": "Mot de passe",
"passwordPlaceholder": "Entrez votre mot de passe",
"signIn": "Se connecter",
"signingIn": "Connexion en cours...",
"forgotPassword": "Mot de passe oublié ?",
"pageTitle": "Connexion"
},
"errors": {
"invalidCredentials": "E-mail ou mot de passe invalide",
"userNotFound": "Utilisateur non trouvé",
"accountLocked": "Compte bloqué. Veuillez réessayer plus tard",
"unexpectedError": "Une erreur inattendue s'est produite. Veuillez réessayer"
},
"validation": {
"invalidEmail": "Adresse email invalide",
"passwordMinLength": "Le mot de passe doit contenir au moins 6 caractères",
"firstNameRequired": "Le prénom est requis",
"lastNameRequired": "Le nom est requis",
"usernameLength": "Le nom d'utilisateur doit contenir au moins 3 caractères",
"usernameSpaces": "Le nom d'utilisateur ne peut pas contenir d'espaces",
"passwordLength": "Le mot de passe doit contenir au moins 8 caractères",
"passwordsMatch": "Les mots de passe ne correspondent pas",
"emailRequired": "L'email est requis",
"passwordRequired": "Le mot de passe est requis"
},
"fileSelector": {
"availableFiles": "Fichiers Disponibles ({{count}})",
"shareFiles": "Fichiers Partagés ({{count}})",
"searchPlaceholder": "Rechercher des fichiers...",
"noMatchingFiles": "Aucun fichier correspondant",
"noAvailableFiles": "Aucun fichier disponible",
"noFilesInShare": "Aucun fichier partagé",
"saveChanges": "Enregistrer les Modifications"
},
"recipientSelector": {
"emailPlaceholder": "Entrez l'e-mail du destinataire",
"add": "Ajouter",
"recipients": "Destinataires ({{count}})",
"notifyAll": "Notifier Tous",
"noRecipients": "Aucun destinataire ajouté",
"addSuccess": "Destinataire ajouté avec succès",
"addError": "Échec de l'ajout du destinataire",
"removeSuccess": "Destinataire supprimé avec succès",
"removeError": "Échec de la suppression du destinataire",
"sendingNotifications": "Envoi des notifications...",
"notifySuccess": "Destinataires notifiés avec succès",
"notifyError": "Échec de la notification des destinataires"
},
"navigation": {
"dashboard": "Tableau de bord"
},
"common": {
"loading": "Chargement, veuillez patienter...",
"cancel": "Annuler",
"save": "Enregistrer",
"delete": "Supprimer",
"close": "Fermer",
"download": "Télécharger",
"unexpectedError": "Une erreur inattendue s'est produite. Veuillez réessayer.",
"yes": "Oui",
"no": "Non",
"dashboard": "Tableau de Bord"
},
"createShare": {
"title": "Créer un Partage",
"nameLabel": "Nom du Partage",
"expirationLabel": "Date d'Expiration",
"expirationPlaceholder": "JJ/MM/AAAA HH:MM",
"maxViewsLabel": "Vues Maximales",
"maxViewsPlaceholder": "Laisser vide pour illimité",
"passwordProtection": "Protégé par Mot de Passe",
"passwordLabel": "Mot de Passe",
"create": "Créer le Partage",
"success": "Partage créé avec succès",
"error": "Échec de la création du partage"
},
"fileActions": {
"editFile": "Modifier le Fichier",
"nameLabel": "Nom",
"namePlaceholder": "Entrez le nouveau nom",
"extension": "Extension",
"descriptionLabel": "Description",
"descriptionPlaceholder": "Entrez la description du fichier",
"deleteFile": "Supprimer le Fichier",
"deleteConfirmation": "Êtes-vous sûr de vouloir supprimer \"{{fileName}}\" ?",
"deleteWarning": "Cette action ne peut pas être annulée."
},
"filePreview": {
"loading": "Chargement de l'aperçu...",
"notAvailable": "Aperçu non disponible",
"downloadToView": "Téléchargez le fichier pour voir le contenu",
"audioNotSupported": "Votre navigateur ne prend pas en charge l'élément audio",
"videoNotSupported": "Votre navigateur ne prend pas en charge l'élément vidéo",
"loadError": "Échec du chargement de l'aperçu",
"downloadError": "Échec du téléchargement du fichier"
},
"generateShareLink": {
"generateTitle": "Générer un Lien de Partage",
"updateTitle": "Mettre à Jour le Lien de Partage",
"generateDescription": "Générez un lien pour partager vos fichiers",
"updateDescription": "Mettez à jour l'alias de ce lien de partage",
"aliasPlaceholder": "Entrez l'alias",
"linkReady": "Votre lien de partage est prêt :",
"generateButton": "Générer le Lien",
"updateButton": "Mettre à Jour le Lien",
"copyButton": "Copier le Lien",
"success": "Lien généré avec succès",
"error": "Échec de la génération du lien",
"copied": "Lien copié dans le presse-papiers"
},
"shareActions": {
"deleteTitle": "Supprimer le Partage",
"deleteConfirmation": "Êtes-vous sûr de vouloir supprimer ce partage ? Cette action ne peut pas être annulée.",
"editTitle": "Modifier le Partage",
"nameLabel": "Nom du Partage",
"expirationLabel": "Date d'Expiration",
"expirationPlaceholder": "JJ/MM/AAAA HH:MM",
"maxViewsLabel": "Vues Maximales",
"maxViewsPlaceholder": "Laisser vide pour illimité",
"passwordProtection": "Protégé par Mot de Passe",
"passwordLabel": "Mot de Passe",
"passwordPlaceholder": "Entrez le mot de passe",
"newPasswordLabel": "Nouveau Mot de Passe (laisser vide pour garder l'actuel)",
"newPasswordPlaceholder": "Entrez le nouveau mot de passe",
"manageFilesTitle": "Gérer les Fichiers",
"manageRecipientsTitle": "Gérer les Destinataires",
"editSuccess": "Partage mis à jour avec succès",
"editError": "Échec de la mise à jour du partage"
},
"shareDetails": {
"title": "Détails du Partage",
"subtitle": "Informations détaillées sur ce partage",
"basicInfo": "Informations de Base",
"name": "Nom",
"untitled": "Partage sans titre",
"views": "Vues",
"dates": "Dates",
"created": "Créé le: {{date}}",
"expires": "Expire le: {{date}}",
"never": "Jamais",
"security": "Sécurité",
"passwordProtected": "Protégé par Mot de Passe",
"publicAccess": "Accès Public",
"maxViews": "Vues Maximales : {{count}}",
"files": "Fichiers ({{count}})",
"recipients": "Destinataires ({{count}})",
"notAvailable": "N/D",
"invalidDate": "Date invalide",
"loadError": "Échec du chargement des détails du partage"
},
"uploadFile": {
"title": "Envoyer un Fichier",
"selectFile": "Cliquez pour sélectionner un fichier",
"preview": "Aperçu",
"uploadProgress": "Progression de l'envoi",
"upload": "Envoyer",
"success": "Fichier envoyé avec succès",
"error": "Échec de l'envoi du fichier"
},
"filesTable": {
"ariaLabel": "Tableau des fichiers",
"columns": {
"name": "NOM",
"description": "DESCRIPTION",
"size": "TAILLE",
"createdAt": "CRÉÉ LE",
"updatedAt": "MODIFIÉ LE",
"actions": "ACTIONS"
},
"actions": {
"menu": "Menu d'actions du fichier",
"preview": "Aperçu",
"edit": "Modifier",
"download": "Télécharger",
"delete": "Supprimer"
}
},
"sharesTable": {
"ariaLabel": "Tableau des partages",
"never": "Jamais",
"columns": {
"name": "NOM",
"createdAt": "CRÉÉ LE",
"expiresAt": "EXPIRE LE",
"status": "STATUT",
"security": "SÉCURITÉ",
"files": "FICHIERS",
"recipients": "DESTINATAIRES",
"actions": "ACTIONS"
},
"status": {
"neverExpires": "N'expire Jamais",
"active": "Actif",
"expired": "Expiré"
},
"security": {
"protected": "Protégé",
"public": "Public"
},
"filesCount": "{{count}} fichiers",
"recipientsCount": "{{count}} destinataires",
"actions": {
"menu": "Menu d'actions du partage",
"edit": "Modifier",
"manageFiles": "Gérer les Fichiers",
"manageRecipients": "Gérer les Destinataires",
"viewDetails": "Voir les Détails",
"generateLink": "Générer un Lien",
"editLink": "Modifier le Lien",
"copyLink": "Copier le Lien",
"notifyRecipients": "Notifier les Destinataires",
"delete": "Supprimer"
}
},
"footer": {
"poweredBy": "Propulsé par",
"kyanHomepage": "Page d'accueil de Kyantech"
},
"fileManager": {
"downloadError": "Échec du téléchargement du fichier",
"updateSuccess": "Fichier mis à jour avec succès",
"updateError": "Échec de la mise à jour du fichier",
"deleteSuccess": "Fichier supprimé avec succès",
"deleteError": "Échec de la suppression du fichier"
},
"shareManager": {
"deleteSuccess": "Partage supprimé avec succès",
"deleteError": "Échec de la suppression du partage",
"updateSuccess": "Partage mis à jour avec succès",
"updateError": "Échec de la mise à jour du partage",
"filesUpdateSuccess": "Fichiers mis à jour avec succès",
"filesUpdateError": "Échec de la mise à jour des fichiers",
"recipientsUpdateSuccess": "Destinataires mis à jour avec succès",
"recipientsUpdateError": "Échec de la mise à jour des destinataires",
"linkGenerateSuccess": "Lien de partage généré avec succès",
"linkGenerateError": "Échec de la génération du lien de partage",
"notifyLoading": "Envoi des notifications...",
"notifySuccess": "Destinataires notifiés avec succès",
"notifyError": "Échec de la notification des destinataires"
},
"quickAccess": {
"files": {
"title": "Mes Fichiers",
"description": "Accédez et gérez vos fichiers téléchargés"
},
"shares": {
"title": "Mes Partages",
"description": "Visualisez et gérez vos fichiers partagés"
}
},
"recentFiles": {
"title": "Téléchargements Récents",
"viewAll": "Voir Tout",
"uploadFile": "Envoyer un Fichier",
"noFiles": "Aucun fichier téléchargé pour le moment"
},
"recentShares": {
"title": "Partages Récents",
"viewAll": "Voir Tout",
"createShare": "Créer un Partage",
"noShares": "Aucun partage créé pour le moment",
"createFirst": "Créer votre premier partage"
},
"storageUsage": {
"title": "Utilisation du Stockage",
"ariaLabel": "Barre de progression de l'utilisation du stockage",
"used": "{{size}} utilisé",
"available": "{{size}} disponible"
},
"dashboard": {
"loadError": "Échec du chargement des données du tableau de bord",
"linkCopied": "Lien copié dans le presse-papiers",
"pageTitle": "Tableau de Bord",
"breadcrumb": "Tableau de Bord"
},
"emptyState": {
"noFiles": "Aucun fichier téléchargé pour le moment",
"uploadFile": "Envoyer un Fichier"
},
"files": {
"title": "Tous les Fichiers",
"uploadFile": "Envoyer un Fichier",
"loadError": "Échec du chargement des fichiers",
"pageTitle": "Mes Fichiers",
"breadcrumb": "Mes Fichiers"
},
"searchBar": {
"placeholder": "Rechercher des fichiers...",
"results": "Trouvé {{filtered}} sur {{total}} fichiers"
},
"forgotPassword": {
"emailLabel": "Adresse Email",
"emailPlaceholder": "Entrez votre email",
"sending": "Envoi en cours...",
"submit": "Envoyer les Instructions",
"backToLogin": "Retour à la Connexion",
"title": "Mot de Passe Oublié",
"description": "Entrez votre adresse email et nous vous enverrons les instructions pour réinitialiser votre mot de passe.",
"resetInstructions": "Instructions de réinitialisation envoyées à votre email",
"pageTitle": "Mot de Passe Oublié"
},
"home": {
"description": "L'alternative open-source à WeTransfer. Partagez des fichiers en toute sécurité, sans suivi ni limitations.",
"documentation": "Documentation",
"starOnGithub": "Star sur GitHub",
"privacyMessage": "Conçu avec la confidentialité à l'esprit. Vos fichiers avant téléchargement ne sont accessibles que par ceux ayant le lien de partage. Gratuit et open source pour toujours.",
"header": {
"fileSharing": "Partage de fichiers",
"tagline": "simple et gratuit"
},
"pageTitle": "Accueil"
},
"profile": {
"password": {
"title": "Changer le Mot de Passe",
"newPassword": "Nouveau Mot de Passe",
"confirmPassword": "Confirmer le Nouveau Mot de Passe",
"updateButton": "Mettre à Jour le Mot de Passe"
},
"form": {
"title": "Informations du Profil",
"firstName": "Prénom",
"lastName": "Nom",
"username": "Nom d'Utilisateur",
"email": "Email",
"updateButton": "Mettre à Jour le Profil"
},
"header": {
"title": "Profil",
"subtitle": "Gérez vos informations personnelles et votre mot de passe"
},
"picture": {
"title": "Photo de Profil",
"description": "Cliquez sur l'icône de l'appareil photo pour changer votre photo de profil",
"uploadPhoto": "Télécharger une Photo",
"removePhoto": "Supprimer la Photo"
},
"errors": {
"loadFailed": "Échec du chargement des données utilisateur",
"updateFailed": "Échec de la mise à jour du profil",
"passwordFailed": "Échec de la mise à jour du mot de passe",
"imageFailed": "Échec de la mise à jour de l'image",
"imageRemoveFailed": "Échec de la suppression de l'image"
},
"messages": {
"noChanges": "Aucun changement à enregistrer",
"updateSuccess": "Profil mis à jour avec succès",
"fillPasswords": "Veuillez remplir les deux champs de mot de passe",
"passwordSuccess": "Mot de passe mis à jour avec succès",
"imageSuccess": "Image de profil mise à jour avec succès",
"imageRemoved": "Image de profil supprimée avec succès"
},
"pageTitle": "Profil"
},
"resetPassword": {
"pageTitle": "Réinitialiser le Mot de Passe",
"header": {
"title": "Réinitialiser le Mot de Passe",
"description": "Entrez votre nouveau mot de passe ci-dessous"
},
"form": {
"newPassword": "Nouveau Mot de Passe",
"newPasswordPlaceholder": "Entrez votre nouveau mot de passe",
"confirmPassword": "Confirmer le Nouveau Mot de Passe",
"confirmPasswordPlaceholder": "Confirmez votre nouveau mot de passe",
"resetting": "Réinitialisation en Cours...",
"submit": "Réinitialiser le Mot de Passe",
"backToLogin": "Retour à la Connexion"
},
"messages": {
"success": "Mot de passe réinitialisé avec succès"
},
"errors": {
"serverError": "Échec de la réinitialisation du mot de passe. Veuillez réessayer.",
"invalidToken": "Jeton de réinitialisation invalide ou manquant"
}
},
"settings": {
"title": "Paramètres",
"breadcrumb": "Paramètres",
"pageTitle": "Paramètres",
"groups": {
"defaultDescription": "Options de configuration",
"general": {
"title": "Général",
"description": "Paramètres de base de l'application"
},
"email": {
"title": "Email",
"description": "Configuration du serveur de messagerie"
},
"security": {
"title": "Sécurité",
"description": "Paramètres de sécurité et d'authentification"
},
"storage": {
"title": "Stockage",
"description": "Configuration du stockage des fichiers"
}
},
"fields": {
"noDescription": "Aucune description disponible",
"appLogo": {
"title": "Logo de l'Application",
"description": "Image du logo de l'application"
},
"appName": {
"title": "Nom de l'Application",
"description": "Nom de l'application affiché aux utilisateurs"
},
"appDescription": {
"title": "Description de l'Application",
"description": "Brève description de l'application"
},
"showHomePage": {
"title": "Afficher la Page d'Accueil",
"description": "Afficher la page d'accueil après l'installation"
},
"smtpEnabled": {
"description": "Activer les notifications par email"
},
"smtpHost": {
"title": "Serveur SMTP",
"description": "Adresse du serveur SMTP"
},
"smtpPort": {
"title": "Port SMTP",
"description": "Port du serveur SMTP"
},
"smtpUser": {
"title": "Utilisateur SMTP",
"description": "Nom d'utilisateur pour l'authentification SMTP"
},
"smtpPass": {
"title": "Mot de passe SMTP",
"description": "Mot de passe pour l'authentification SMTP"
},
"smtpFromName": {
"title": "Nom de l'Expéditeur",
"description": "Nom affiché dans les emails envoyés"
},
"smtpFromEmail": {
"title": "Email de l'Expéditeur",
"description": "Adresse email de l'expéditeur"
},
"maxLoginAttempts": {
"title": "Tentatives de Connexion Maximum",
"description": "Nombre maximum de tentatives de connexion avant le blocage"
},
"loginBlockDuration": {
"title": "Durée du Blocage",
"description": "Durée (en secondes) du blocage après dépassement des tentatives"
},
"passwordMinLength": {
"title": "Longueur Minimale du Mot de Passe",
"description": "Nombre minimum de caractères pour les mots de passe"
},
"passwordResetTokenExpiration": {
"title": "Expiration du Jeton de Réinitialisation",
"description": "Durée de validité (en secondes) du jeton de réinitialisation"
},
"maxFileSize": {
"title": "Taille Maximale de Fichier",
"description": "Taille maximale autorisée pour les fichiers (en octets)"
},
"maxTotalStoragePerUser": {
"title": "Stockage Maximum par Utilisateur",
"description": "Limite totale de stockage par utilisateur (en octets)"
}
},
"buttons": {
"save": "Enregistrer {{group}}"
},
"errors": {
"loadFailed": "Échec du chargement des paramètres",
"updateFailed": "Échec de la mise à jour des paramètres"
},
"messages": {
"noChanges": "Aucun changement à enregistrer",
"updateSuccess": "Paramètres {{group}} mis à jour avec succès"
}
},
"share": {
"errors": {
"invalidPassword": "Mot de passe invalide. Veuillez réessayer.",
"loadFailed": "Échec du chargement du partage",
"downloadFailed": "Échec du téléchargement du fichier"
},
"messages": {
"downloadStarted": "Téléchargement commencé"
},
"password": {
"title": "Partage Protégé par Mot de Passe",
"protected": "Ce partage est protégé par mot de passe",
"incorrect": "Mot de passe incorrect. Veuillez réessayer.",
"label": "Mot de passe",
"placeholder": "Entrez le mot de passe du partage",
"submit": "Envoyer"
},
"details": {
"untitled": "Partage sans titre",
"created": "Créé le: {{date}}",
"expires": "Expire le: {{date}}"
},
"notFound": {
"title": "Partage Non Trouvé",
"description": "Ce partage a peut-être été supprimé ou a expiré."
},
"pageTitle": "Partage"
},
"shares": {
"errors": {
"loadFailed": "Échec du chargement des partages",
"notifyFailed": "Échec de la notification des destinataires",
"smtpConfigFailed": "Échec du chargement de la configuration SMTP"
},
"messages": {
"linkCopied": "Lien copié dans le presse-papiers",
"recipientsNotified": "Destinataires notifiés avec succès"
},
"empty": {
"message": "Aucun partage créé pour le moment",
"createButton": "Créer un Partage"
},
"header": {
"title": "Mes Partages",
"myShares": "Mes Partages"
},
"search": {
"title": "Tous les Partages",
"createButton": "Créer un Partage",
"placeholder": "Rechercher des partages...",
"results": "Trouvé {{filtered}} sur {{total}} partages"
},
"pageTitle": "Partages"
},
"users": {
"modes": {
"create": "créer",
"edit": "modifier"
},
"errors": {
"loadFailed": "Échec du chargement des utilisateurs",
"submitFailed": "Échec de {{mode}} l'utilisateur",
"deleteFailed": "Échec de la suppression de l'utilisateur",
"statusUpdateFailed": "Échec de la mise à jour du statut de l'utilisateur"
},
"messages": {
"createSuccess": "Utilisateur créé avec succès",
"updateSuccess": "Utilisateur mis à jour avec succès",
"deleteSuccess": "Utilisateur supprimé avec succès",
"activateSuccess": "Utilisateur activé avec succès",
"deactivateSuccess": "Utilisateur désactivé avec succès"
},
"actions": {
"edit": "Modifier",
"activate": "Activer",
"deactivate": "Désactiver",
"delete": "Supprimer"
},
"delete": {
"title": "Confirmer la Suppression de l'Utilisateur",
"confirmation": "Êtes-vous sûr de vouloir supprimer l'utilisateur {{firstName}} {{lastName}} ? Cette action ne peut pas être annulée.",
"confirm": "Supprimer l'Utilisateur"
},
"form": {
"titleCreate": "Ajouter un Nouvel Utilisateur",
"titleEdit": "Modifier l'Utilisateur",
"firstName": "Prénom",
"lastName": "Nom",
"username": "Nom d'Utilisateur",
"email": "Email",
"password": "Mot de Passe",
"newPassword": "Nouveau Mot de Passe (optionnel)",
"passwordPlaceholder": "Laisser vide pour garder le mot de passe actuel",
"role": "Rôle",
"roleUser": "Utilisateur",
"roleAdmin": "Administrateur",
"create": "Créer",
"save": "Enregistrer"
},
"status": {
"title": "Confirmer le Changement de Statut",
"confirmation": "Êtes-vous sûr de vouloir {{action}} l'utilisateur {{firstName}} {{lastName}} ?",
"activate": "activer",
"deactivate": "désactiver",
"user": "Utilisateur"
},
"header": {
"title": "Gestion des Utilisateurs",
"addUser": "Ajouter un Utilisateur",
"management": "Gestion des Utilisateurs"
},
"table": {
"user": "UTILISATEUR",
"email": "EMAIL",
"status": "STATUT",
"role": "RÔLE",
"actions": "ACTIONS",
"active": "Actif",
"inactive": "Inactif",
"admin": "Admin",
"userr": "Utilisateur"
}
},
"logo": {
"labels": {
"appLogo": "Logo de l'application"
},
"buttons": {
"upload": "Télécharger le logo",
"remove": "Supprimer le logo"
},
"messages": {
"uploadSuccess": "Logo téléchargé avec succès",
"removeSuccess": "Logo supprimé avec succès"
},
"errors": {
"uploadFailed": "Échec du téléchargement du logo",
"removeFailed": "Échec de la suppression du logo"
}
},
"navbar": {
"logoAlt": "Logo de l'Application",
"profileMenu": "Menu du Profil",
"profile": "Profil",
"settings": "Paramètres",
"usersManagement": "Gestion des Utilisateurs",
"logout": "Déconnexion"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "स्वागत है में",
"signInToContinue": "जारी रखने के लिए साइन इन करें",
"emailLabel": "ईमेल पता",
"emailPlaceholder": "अपना ईमेल दर्ज करें",
"passwordLabel": "पासवर्ड",
"passwordPlaceholder": "अपना पासवर्ड दर्ज करें",
"signIn": "साइन इन करें",
"signingIn": "साइन इन हो रहा है...",
"forgotPassword": "पासवर्ड भूल गए?",
"pageTitle": "लॉगिन"
},
"errors": {
"invalidCredentials": "गलत ईमेल या पासवर्ड",
"userNotFound": "उपयोगकर्ता नहीं मिला",
"accountLocked": "खाता लॉक है। कृपया बाद में प्रयास करें",
"unexpectedError": "एक अप्रत्याशित त्रुटि हुई। कृपया पुनः प्रयास करें"
},
"validation": {
"invalidEmail": "अमान्य ईमेल पता",
"passwordMinLength": "पासवर्ड कम से कम 6 अक्षर का होना चाहिए",
"firstNameRequired": "पहला नाम आवश्यक है",
"lastNameRequired": "अंतिम नाम आवश्यक है",
"usernameLength": "उपयोगकर्ता नाम कम से कम 3 अक्षर का होना चाहिए",
"usernameSpaces": "उपयोगकर्ता नाम में रिक्त स्थान नहीं हो सकते",
"passwordLength": "पासवर्ड कम से कम 8 अक्षर का होना चाहिए",
"passwordsMatch": "पासवर्ड मेल नहीं खाते",
"emailRequired": "ईमेल आवश्यक है",
"passwordRequired": "पासवर्ड आवश्यक है"
},
"fileSelector": {
"availableFiles": "उपलब्ध फाइलें ({{count}})",
"shareFiles": "फाइलें साझा करें ({{count}})",
"searchPlaceholder": "फाइलें खोजें...",
"noMatchingFiles": "कोई मेल खाने वाली फाइलें नहीं",
"noAvailableFiles": "कोई फाइल उपलब्ध नहीं",
"noFilesInShare": "साझाकरण में कोई फाइलें नहीं",
"saveChanges": "परिवर्तन सहेजें"
},
"recipientSelector": {
"emailPlaceholder": "प्राप्तकर्ता का ईमेल दर्ज करें",
"add": "जोड़ें",
"recipients": "प्राप्तकर्ता ({{count}})",
"notifyAll": "सभी को सूचित करें",
"noRecipients": "अभी तक कोई प्राप्तकर्ता नहीं जोड़ा गया",
"addSuccess": "प्राप्तकर्ता सफलतापूर्वक जोड़ा गया",
"addError": "प्राप्तकर्ता जोड़ने में विफल",
"removeSuccess": "प्राप्तकर्ता सफलतापूर्वक हटाया गया",
"removeError": "प्राप्तकर्ता हटाने में विफल",
"sendingNotifications": "सूचनाएँ भेजी जा रही हैं...",
"notifySuccess": "प्राप्तकर्ताओं को सफलतापूर्वक सूचित किया गया",
"notifyError": "प्राप्तकर्ताओं को सूचित करने में विफल"
},
"navigation": {
"dashboard": "डैशबोर्ड"
},
"common": {
"loading": "लोड हो रहा है, कृपया प्रतीक्षा करें...",
"cancel": "रद्द करें",
"save": "सहेजें",
"delete": "हटाएं",
"close": "बंद करें",
"download": "डाउनलोड करें",
"unexpectedError": "एक अप्रत्याशित त्रुटि हुई। कृपया पुनः प्रयास करें।",
"yes": "हाँ",
"no": "नहीं",
"dashboard": "डैशबोर्ड"
},
"createShare": {
"title": "साझा करें बनाएं",
"nameLabel": "साझाकरण का नाम",
"expirationLabel": "समाप्ति तिथि",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "अधिकतम दृश्य",
"maxViewsPlaceholder": "अनलिमिटेड के लिए खाली छोड़ें",
"passwordProtection": "पासवर्ड सुरक्षा",
"passwordLabel": "पासवर्ड",
"create": "साझा करें बनाएं",
"success": "साझाकरण सफलतापूर्वक बनाया गया",
"error": "साझाकरण बनाने में विफल"
},
"fileActions": {
"editFile": "फाइल संपादित करें",
"nameLabel": "नाम",
"namePlaceholder": "नया नाम दर्ज करें",
"extension": "एक्सटेंशन",
"descriptionLabel": "विवरण",
"descriptionPlaceholder": "फाइल का विवरण दर्ज करें",
"deleteFile": "फाइल हटाएं",
"deleteConfirmation": "क्या आप वाकई \"{{fileName}}\" हटाना चाहते हैं?",
"deleteWarning": "यह क्रिया अपरिवर्तनीय है।"
},
"filePreview": {
"loading": "पूर्वावलोकन लोड हो रहा है...",
"notAvailable": "पूर्वावलोकन उपलब्ध नहीं",
"downloadToView": "सामग्री देखने के लिए फाइल डाउनलोड करें",
"audioNotSupported": "आपका ब्राउज़र ऑडियो तत्व का समर्थन नहीं करता",
"videoNotSupported": "आपका ब्राउज़र वीडियो तत्व का समर्थन नहीं करता",
"loadError": "पूर्वावलोकन लोड करने में विफल",
"downloadError": "फाइल डाउनलोड करने में विफल"
},
"generateShareLink": {
"generateTitle": "साझाकरण लिंक उत्पन्न करें",
"updateTitle": "साझाकरण लिंक अपडेट करें",
"generateDescription": "अपनी फाइलें साझा करने के लिए एक लिंक उत्पन्न करें",
"updateDescription": "इस साझाकरण लिंक के लिए उपनाम अपडेट करें",
"aliasPlaceholder": "उपनाम दर्ज करें",
"linkReady": "आपका साझाकरण लिंक तैयार है:",
"generateButton": "लिंक उत्पन्न करें",
"updateButton": "लिंक अपडेट करें",
"copyButton": "लिंक कॉपी करें",
"success": "लिंक सफलतापूर्वक उत्पन्न हुआ",
"error": "लिंक उत्पन्न करने में विफल",
"copied": "लिंक क्लिपबोर्ड में कॉपी किया गया"
},
"shareActions": {
"deleteTitle": "साझाकरण हटाएं",
"deleteConfirmation": "क्या आप वाकई इस साझाकरण को हटाना चाहते हैं? यह क्रिया अपरिवर्तनीय है।",
"editTitle": "साझाकरण संपादित करें",
"nameLabel": "साझाकरण का नाम",
"expirationLabel": "समाप्ति तिथि",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "अधिकतम दृश्य",
"maxViewsPlaceholder": "अनलिमिटेड के लिए खाली छोड़ें",
"passwordProtection": "पासवर्ड सुरक्षा",
"passwordLabel": "पासवर्ड",
"passwordPlaceholder": "पासवर्ड दर्ज करें",
"newPasswordLabel": "नया पासवर्ड (वर्तमान रखने के लिए खाली छोड़ें)",
"newPasswordPlaceholder": "नया पासवर्ड दर्ज करें",
"manageFilesTitle": "फाइलें प्रबंधित करें",
"manageRecipientsTitle": "प्राप्तकर्ताओं का प्रबंधन करें",
"editSuccess": "साझाकरण सफलतापूर्वक अपडेट हुआ",
"editError": "साझाकरण अपडेट करने में विफल"
},
"shareDetails": {
"title": "साझाकरण विवरण",
"subtitle": "इस साझाकरण की विस्तृत जानकारी",
"basicInfo": "मूल जानकारी",
"name": "नाम",
"untitled": "बिना शीर्षक के",
"views": "दृश्य",
"dates": "तिथियाँ",
"created": "बनाया गया",
"expires": "समाप्त होता है",
"never": "कभी नहीं",
"security": "सुरक्षा",
"passwordProtected": "पासवर्ड द्वारा संरक्षित",
"publicAccess": "सार्वजनिक पहुँच",
"maxViews": "अधिकतम दृश्य: {{count}}",
"files": "फाइलें ({{count}})",
"recipients": "प्राप्तकर्ता ({{count}})",
"notAvailable": "एन/ए",
"invalidDate": "अमान्य तिथि",
"loadError": "साझाकरण विवरण लोड करने में विफल"
},
"uploadFile": {
"title": "फाइल अपलोड करें",
"selectFile": "फाइल चुनने के लिए क्लिक करें",
"preview": "पूर्वावलोकन",
"uploadProgress": "अपलोड प्रगति",
"upload": "अपलोड करें",
"success": "फाइल सफलतापूर्वक अपलोड हुई",
"error": "फाइल अपलोड करने में विफल"
},
"filesTable": {
"ariaLabel": "फाइल टेबल",
"columns": {
"name": "नाम",
"description": "विवरण",
"size": "आकार",
"createdAt": "बनाया गया",
"updatedAt": "अपडेट किया गया",
"actions": "क्रियाएं"
},
"actions": {
"menu": "फाइल क्रिया मेनू",
"preview": "पूर्वावलोकन",
"edit": "संपादित करें",
"download": "डाउनलोड करें",
"delete": "हटाएं"
}
},
"sharesTable": {
"ariaLabel": "साझाकरण टेबल",
"never": "कभी नहीं",
"columns": {
"name": "नाम",
"createdAt": "बनाया गया",
"expiresAt": "समाप्त होता है",
"status": "स्थिति",
"security": "सुरक्षा",
"files": "फाइलें",
"recipients": "प्राप्तकर्ता",
"actions": "क्रियाएं"
},
"status": {
"neverExpires": "कभी समाप्त नहीं",
"active": "सक्रिय",
"expired": "समाप्त"
},
"security": {
"protected": "संरक्षित",
"public": "सार्वजनिक"
},
"filesCount": "{{count}} फाइलें",
"recipientsCount": "{{count}} प्राप्तकर्ता",
"actions": {
"menu": "साझाकरण क्रिया मेनू",
"edit": "संपादित करें",
"manageFiles": "फाइलें प्रबंधित करें",
"manageRecipients": "प्राप्तकर्ताओं का प्रबंधन करें",
"viewDetails": "विवरण देखें",
"generateLink": "लिंक उत्पन्न करें",
"editLink": "लिंक संपादित करें",
"copyLink": "लिंक कॉपी करें",
"notifyRecipients": "प्राप्तकर्ताओं को सूचित करें",
"delete": "हटाएं"
}
},
"footer": {
"poweredBy": "द्वारा संचालित",
"kyanHomepage": "Kyantech होमपेज"
},
"fileManager": {
"downloadError": "फाइल डाउनलोड करने में त्रुटि",
"updateSuccess": "फाइल सफलतापूर्वक अपडेट हुई",
"updateError": "फाइल अपडेट करने में त्रुटि",
"deleteSuccess": "फाइल सफलतापूर्वक हटाई गई",
"deleteError": "फाइल हटाने में त्रुटि"
},
"shareManager": {
"deleteSuccess": "साझाकरण सफलतापूर्वक हटाया गया",
"deleteError": "साझाकरण हटाने में त्रुटि",
"updateSuccess": "साझाकरण सफलतापूर्वक अपडेट हुआ",
"updateError": "साझाकरण अपडेट करने में त्रुटि",
"filesUpdateSuccess": "फाइलें सफलतापूर्वक अपडेट हुईं",
"filesUpdateError": "फाइलें अपडेट करने में त्रुटि",
"recipientsUpdateSuccess": "प्राप्तकर्ता सफलतापूर्वक अपडेट हुए",
"recipientsUpdateError": "प्राप्तकर्ता अपडेट करने में त्रुटि",
"linkGenerateSuccess": "साझाकरण लिंक सफलतापूर्वक उत्पन्न हुआ",
"linkGenerateError": "साझाकरण लिंक उत्पन्न करने में त्रुटि",
"notifyLoading": "सूचनाएँ भेजी जा रही हैं...",
"notifySuccess": "प्राप्तकर्ताओं को सफलतापूर्वक सूचित किया गया",
"notifyError": "प्राप्तकर्ताओं को सूचित करने में त्रुटि"
},
"quickAccess": {
"files": {
"title": "मेरी फाइलें",
"description": "अपलोड की गई फाइलों तक पहुंच और प्रबंधन"
},
"shares": {
"title": "मेरे साझाकरण",
"description": "साझा की गई फाइलों को देखें और प्रबंधित करें"
}
},
"recentFiles": {
"title": "हाल की अपलोड्स",
"viewAll": "सभी देखें",
"uploadFile": "फाइल अपलोड करें",
"noFiles": "अभी तक कोई फाइल अपलोड नहीं हुई"
},
"recentShares": {
"title": "हाल के साझाकरण",
"viewAll": "सभी देखें",
"createShare": "साझा करें बनाएं",
"noShares": "अभी तक कोई साझाकरण नहीं बनाया गया",
"createFirst": "अपना पहला साझाकरण बनाएं"
},
"storageUsage": {
"title": "स्टोरेज उपयोग",
"ariaLabel": "स्टोरेज उपयोग प्रगति पट्टी",
"used": "{{size}} उपयोग किया गया",
"available": "{{size}} उपलब्ध"
},
"dashboard": {
"loadError": "डैशबोर्ड डेटा लोड करने में त्रुटि",
"linkCopied": "लिंक क्लिपबोर्ड में कॉपी हुआ",
"pageTitle": "डैशबोर्ड",
"breadcrumb": "डैशबोर्ड"
},
"emptyState": {
"noFiles": "अभी तक कोई फाइल अपलोड नहीं हुई",
"uploadFile": "फाइल अपलोड करें"
},
"files": {
"title": "सभी फाइलें",
"uploadFile": "फाइल अपलोड करें",
"loadError": "फाइलें लोड करने में त्रुटि",
"pageTitle": "मेरी फाइलें",
"breadcrumb": "मेरी फाइलें"
},
"searchBar": {
"placeholder": "फाइलें खोजें...",
"results": "{{total}} में से {{filtered}} फाइलें मिलीं"
},
"forgotPassword": {
"emailLabel": "ईमेल पता",
"emailPlaceholder": "अपना ईमेल दर्ज करें",
"sending": "भेजा जा रहा है...",
"submit": "रीसेट निर्देश भेजें",
"backToLogin": "लॉगिन पर वापस जाएं",
"title": "पासवर्ड भूल गए",
"description": "अपना ईमेल पता दर्ज करें और हम आपको पासवर्ड रीसेट करने के निर्देश भेजेंगे।",
"resetInstructions": "रीसेट निर्देश आपके ईमेल पर भेज दिए गए हैं",
"pageTitle": "पासवर्ड भूल गए"
},
"home": {
"description": "WeTransfer का ओपन-सोर्स विकल्प। फाइलें सुरक्षित रूप से साझा करें, बिना ट्रैकिंग या सीमाओं के।",
"documentation": "दस्तावेज",
"starOnGithub": "GitHub पर स्टार करें",
"privacyMessage": "गोपनीयता को ध्यान में रखते हुए बनाया गया। अपलोड से पहले आपकी फाइलें केवल उनके लिए उपलब्ध हैं जिनके पास साझाकरण लिंक है। हमेशा मुफ्त और ओपन सोर्स।",
"header": {
"fileSharing": "फाइल साझा करें",
"tagline": "सरल और मुफ्त"
},
"pageTitle": "होम"
},
"profile": {
"password": {
"title": "पासवर्ड बदलें",
"newPassword": "नया पासवर्ड",
"confirmPassword": "नया पासवर्ड पुष्टि करें",
"updateButton": "पासवर्ड अपडेट करें"
},
"form": {
"title": "प्रोफ़ाइल जानकारी",
"firstName": "पहला नाम",
"lastName": "अंतिम नाम",
"username": "उपयोगकर्ता नाम",
"email": "ईमेल",
"updateButton": "प्रोफ़ाइल अपडेट करें"
},
"header": {
"title": "प्रोफ़ाइल",
"subtitle": "अपनी व्यक्तिगत जानकारी और पासवर्ड प्रबंधित करें"
},
"picture": {
"title": "प्रोफ़ाइल चित्र",
"description": "प्रोफ़ाइल चित्र बदलने के लिए कैमरा आइकन पर क्लिक करें",
"uploadPhoto": "फोटो अपलोड करें",
"removePhoto": "फोटो हटाएं"
},
"errors": {
"loadFailed": "उपयोगकर्ता डेटा लोड करने में विफल",
"updateFailed": "प्रोफ़ाइल अपडेट करने में त्रुटि",
"passwordFailed": "पासवर्ड अपडेट करने में त्रुटि",
"imageFailed": "प्रोफ़ाइल चित्र अपडेट करने में त्रुटि",
"imageRemoveFailed": "प्रोफ़ाइल चित्र हटाने में त्रुटि"
},
"messages": {
"noChanges": "सहेजने के लिए कोई परिवर्तन नहीं",
"updateSuccess": "प्रोफ़ाइल सफलतापूर्वक अपडेट हुई",
"fillPasswords": "कृपया दोनों पासवर्ड फील्ड भरें",
"passwordSuccess": "पासवर्ड सफलतापूर्वक अपडेट हुआ",
"imageSuccess": "प्रोफ़ाइल चित्र सफलतापूर्वक अपडेट हुआ",
"imageRemoved": "प्रोफ़ाइल चित्र सफलतापूर्वक हटाया गया"
},
"pageTitle": "प्रोफ़ाइल"
},
"resetPassword": {
"pageTitle": "पासवर्ड रीसेट करें",
"header": {
"title": "पासवर्ड रीसेट करें",
"description": "नीचे अपना नया पासवर्ड दर्ज करें"
},
"form": {
"newPassword": "नया पासवर्ड",
"newPasswordPlaceholder": "अपना नया पासवर्ड दर्ज करें",
"confirmPassword": "नया पासवर्ड पुष्टि करें",
"confirmPasswordPlaceholder": "अपना नया पासवर्ड पुष्टि करें",
"resetting": "पासवर्ड रीसेट हो रहा है...",
"submit": "पासवर्ड रीसेट करें",
"backToLogin": "लॉगिन पर वापस जाएं"
},
"messages": {
"success": "पासवर्ड सफलतापूर्वक रीसेट हुआ"
},
"errors": {
"serverError": "पासवर्ड रीसेट करने में विफल। कृपया पुनः प्रयास करें।",
"invalidToken": "अमान्य या गायब रीसेट टोकन"
}
},
"settings": {
"groups": {
"defaultDescription": "कॉन्फ़िगरेशन विकल्प",
"general": {
"title": "सामान्य",
"description": "एप्लिकेशन की बुनियादी सेटिंग्स"
},
"email": {
"title": "ईमेल",
"description": "ईमेल सर्वर कॉन्फ़िगरेशन"
},
"security": {
"title": "सुरक्षा",
"description": "सुरक्षा और प्रमाणीकरण सेटिंग्स"
},
"storage": {
"title": "स्टोरेज",
"description": "फाइल स्टोरेज कॉन्फ़िगरेशन"
}
},
"fields": {
"noDescription": "कोई विवरण उपलब्ध नहीं",
"appLogo": {
"title": "एप्लिकेशन लोगो",
"description": "एप्लिकेशन का लोगो चित्र"
},
"appName": {
"title": "एप्लिकेशन नाम",
"description": "उपयोगकर्ताओं को दिखाया जाने वाला एप्लिकेशन नाम"
},
"appDescription": {
"title": "एप्लिकेशन विवरण",
"description": "एप्लिकेशन का संक्षिप्त विवरण"
},
"showHomePage": {
"title": "होम पेज दिखाएं",
"description": "इंस्टॉलेशन के बाद होम पेज दिखाएं"
},
"smtpEnabled": {
"title": "SMTP सक्षम",
"description": "SMTP ईमेल कार्यक्षमता सक्षम या अक्षम करें"
},
"smtpHost": {
"title": "SMTP सर्वर",
"description": "SMTP सर्वर पता"
},
"smtpPort": {
"title": "SMTP पोर्ट",
"description": "SMTP सर्वर पोर्ट"
},
"smtpUser": {
"title": "SMTP उपयोगकर्ता",
"description": "SMTP प्रमाणीकरण के लिए उपयोगकर्ता नाम"
},
"smtpPass": {
"title": "SMTP पासवर्ड",
"description": "SMTP प्रमाणीकरण के लिए पासवर्ड"
},
"smtpFromName": {
"title": "प्रेषक का नाम",
"description": "भेजे गए ईमेल के लिए डिस्प्ले नाम"
},
"smtpFromEmail": {
"title": "प्रेषक का ईमेल",
"description": "प्रेषक का ईमेल पता"
},
"maxLoginAttempts": {
"title": "अधिकतम लॉगिन प्रयास",
"description": "ब्लॉक करने से पहले अधिकतम लॉगिन प्रयासों की संख्या"
},
"loginBlockDuration": {
"title": "लॉगिन ब्लॉक अवधि",
"description": "प्रयासों की सीमा पार करने पर ब्लॉक की अवधि (सेकंड में)"
},
"passwordMinLength": {
"title": "न्यूनतम पासवर्ड लंबाई",
"description": "पासवर्ड के लिए न्यूनतम अक्षरों की संख्या"
},
"passwordResetTokenExpiration": {
"title": "रीसेट टोकन समाप्ति",
"description": "पासवर्ड रीसेट टोकन की वैधता (सेकंड में)"
},
"maxFileSize": {
"title": "अधिकतम फाइल आकार",
"description": "अपलोड के लिए अधिकतम अनुमत फाइल आकार (बाइट में)"
},
"maxTotalStoragePerUser": {
"title": "प्रति उपयोगकर्ता अधिकतम स्टोरेज",
"description": "प्रति उपयोगकर्ता कुल स्टोरेज सीमा (बाइट में)"
}
},
"buttons": {
"save": "{{group}} सहेजें"
},
"errors": {
"loadFailed": "सेटिंग्स लोड करने में विफल",
"updateFailed": "सेटिंग्स अपडेट करने में विफल"
},
"messages": {
"noChanges": "सहेजने के लिए कोई परिवर्तन नहीं",
"updateSuccess": "{{group}} सेटिंग्स सफलतापूर्वक अपडेट हुईं"
},
"title": "सेटिंग्स",
"breadcrumb": "सेटिंग्स",
"pageTitle": "सेटिंग्स"
},
"share": {
"errors": {
"invalidPassword": "अमान्य पासवर्ड। कृपया पुनः प्रयास करें।",
"loadFailed": "साझाकरण लोड करने में विफल",
"downloadFailed": "फाइल डाउनलोड करने में विफल"
},
"messages": {
"downloadStarted": "डाउनलोड शुरू हुआ"
},
"password": {
"title": "पासवर्ड संरक्षित साझाकरण",
"protected": "यह साझाकरण पासवर्ड द्वारा संरक्षित है",
"incorrect": "गलत पासवर्ड। कृपया पुनः प्रयास करें।",
"label": "पासवर्ड",
"placeholder": "साझाकरण का पासवर्ड दर्ज करें",
"submit": "सबमिट करें"
},
"details": {
"untitled": "बिना शीर्षक के",
"created": "बनाया गया: {{date}}",
"expires": "समाप्त होता है: {{date}}"
},
"notFound": {
"title": "साझाकरण नहीं मिला",
"description": "यह साझाकरण हटा दिया गया हो सकता है या समाप्त हो चुका है।"
},
"pageTitle": "साझाकरण"
},
"shares": {
"errors": {
"loadFailed": "साझाकरण लोड करने में विफल",
"notifyFailed": "प्राप्तकर्ताओं को सूचित करने में विफल",
"smtpConfigFailed": "SMTP कॉन्फ़िगरेशन लोड करने में विफल"
},
"messages": {
"linkCopied": "लिंक क्लिपबोर्ड में कॉपी किया गया",
"recipientsNotified": "प्राप्तकर्ताओं को सफलतापूर्वक सूचित किया गया"
},
"empty": {
"message": "अभी तक कोई साझाकरण नहीं बनाया गया",
"createButton": "साझाकरण बनाएं"
},
"header": {
"title": "मेरे साझाकरण",
"myShares": "मेरे साझाकरण"
},
"search": {
"title": "सभी साझाकरण",
"createButton": "साझाकरण बनाएं",
"placeholder": "साझाकरण खोजें...",
"results": "{{total}} में से {{filtered}} साझाकरण मिले"
},
"pageTitle": "साझाकरण"
},
"users": {
"modes": {
"create": "बनाएं",
"edit": "संपादित करें"
},
"errors": {
"loadFailed": "उपयोगकर्ता लोड करने में विफल",
"submitFailed": "{{mode}} करने में विफल",
"deleteFailed": "उपयोगकर्ता हटाने में विफल",
"statusUpdateFailed": "उपयोगकर्ता की स्थिति अपडेट करने में विफल"
},
"messages": {
"createSuccess": "उपयोगकर्ता सफलतापूर्वक बनाया गया",
"updateSuccess": "उपयोगकर्ता सफलतापूर्वक अपडेट हुआ",
"deleteSuccess": "उपयोगकर्ता सफलतापूर्वक हटाया गया",
"activateSuccess": "उपयोगकर्ता सफलतापूर्वक सक्रिय हुआ",
"deactivateSuccess": "उपयोगकर्ता सफलतापूर्वक निष्क्रिय हुआ"
},
"actions": {
"edit": "संपादित करें",
"activate": "सक्रिय करें",
"deactivate": "निष्क्रिय करें",
"delete": "हटाएं"
},
"delete": {
"title": "उपयोगकर्ता हटाने की पुष्टि करें",
"confirmation": "क्या आप वाकई {{firstName}} {{lastName}} को हटाना चाहते हैं? यह क्रिया अपरिवर्तनीय है।",
"confirm": "उपयोगकर्ता हटाएं"
},
"form": {
"titleCreate": "नया उपयोगकर्ता जोड़ें",
"titleEdit": "उपयोगकर्ता संपादित करें",
"firstName": "पहला नाम",
"lastName": "अंतिम नाम",
"username": "उपयोगकर्ता नाम",
"email": "ईमेल",
"password": "पासवर्ड",
"newPassword": "नया पासवर्ड (वैकल्पिक)",
"passwordPlaceholder": "वर्तमान पासवर्ड रखने के लिए खाली छोड़ें",
"role": "भूमिका",
"roleUser": "उपयोगकर्ता",
"roleAdmin": "व्यवस्थापक",
"create": "बनाएं",
"save": "सहेजें"
},
"status": {
"title": "स्थिति परिवर्तन की पुष्टि करें",
"confirmation": "क्या आप वाकई {{firstName}} {{lastName}} को {{action}} करना चाहते हैं?",
"activate": "सक्रिय करें",
"deactivate": "निष्क्रिय करें",
"user": "उपयोगकर्ता"
},
"header": {
"title": "उपयोगकर्ता प्रबंधन",
"addUser": "उपयोगकर्ता जोड़ें",
"management": "उपयोगकर्ता प्रबंधन"
},
"table": {
"user": "उपयोगकर्ता",
"email": "ईमेल",
"status": "स्थिति",
"role": "भूमिका",
"actions": "क्रियाएं",
"active": "सक्रिय",
"inactive": "निष्क्रिय",
"admin": "व्यवस्थापक",
"userr": "उपयोगकर्ता"
}
},
"logo": {
"labels": {
"appLogo": "एप्लिकेशन लोगो"
},
"buttons": {
"upload": "लोगो अपलोड करें",
"remove": "लोगो हटाएं"
},
"messages": {
"uploadSuccess": "लोगो सफलतापूर्वक अपलोड हुआ",
"removeSuccess": "लोगो सफलतापूर्वक हटाया गया"
},
"errors": {
"uploadFailed": "लोगो अपलोड करने में विफल",
"removeFailed": "लोगो हटाने में विफल"
}
},
"navbar": {
"logoAlt": "एप्लिकेशन लोगो",
"profileMenu": "प्रोफ़ाइल मेन्यू",
"profile": "प्रोफ़ाइल",
"settings": "सेटिंग्स",
"usersManagement": "उपयोगकर्ता प्रबंधन",
"logout": "लॉग आउट"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "ようこそへ",
"signInToContinue": "続行するにはサインインしてください",
"emailLabel": "メールアドレス",
"emailPlaceholder": "メールアドレスを入力してください",
"passwordLabel": "パスワード",
"passwordPlaceholder": "パスワードを入力してください",
"signIn": "サインイン",
"signingIn": "サインイン中...",
"forgotPassword": "パスワードをお忘れですか?",
"pageTitle": "ログイン"
},
"errors": {
"invalidCredentials": "無効なメールアドレスまたはパスワードです",
"userNotFound": "ユーザーが見つかりません",
"accountLocked": "アカウントがロックされています。後でもう一度お試しください",
"unexpectedError": "予期しないエラーが発生しました。もう一度お試しください"
},
"validation": {
"invalidEmail": "無効なメールアドレスです",
"passwordMinLength": "パスワードは最低6文字必要です",
"firstNameRequired": "名は必須です",
"lastNameRequired": "姓は必須です",
"usernameLength": "ユーザー名は最低3文字必要です",
"usernameSpaces": "ユーザー名にスペースは使用できません",
"passwordLength": "パスワードは最低8文字必要です",
"passwordsMatch": "パスワードが一致しません",
"emailRequired": "メールアドレスは必須です",
"passwordRequired": "パスワードは必須です"
},
"fileSelector": {
"availableFiles": "利用可能なファイル ({{count}})",
"shareFiles": "ファイルを共有 ({{count}})",
"searchPlaceholder": "ファイルを検索...",
"noMatchingFiles": "一致するファイルがありません",
"noAvailableFiles": "利用可能なファイルがありません",
"noFilesInShare": "共有ファイルがありません",
"saveChanges": "変更を保存"
},
"recipientSelector": {
"emailPlaceholder": "受信者のメールを入力してください",
"add": "追加",
"recipients": "受信者 ({{count}})",
"notifyAll": "全員に通知",
"noRecipients": "まだ受信者が追加されていません",
"addSuccess": "受信者が正常に追加されました",
"addError": "受信者の追加に失敗しました",
"removeSuccess": "受信者が正常に削除されました",
"removeError": "受信者の削除に失敗しました",
"sendingNotifications": "通知を送信中...",
"notifySuccess": "受信者に正常に通知しました",
"notifyError": "受信者への通知に失敗しました"
},
"navigation": {
"dashboard": "ダッシュボード"
},
"common": {
"loading": "読み込み中です。しばらくお待ちください...",
"cancel": "キャンセル",
"save": "保存",
"delete": "削除",
"close": "閉じる",
"download": "ダウンロード",
"unexpectedError": "予期しないエラーが発生しました。もう一度お試しください。",
"yes": "はい",
"no": "いいえ",
"dashboard": "ダッシュボード"
},
"createShare": {
"title": "共有を作成",
"nameLabel": "共有名",
"expirationLabel": "有効期限",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "最大ビュー数",
"maxViewsPlaceholder": "無制限の場合は空白のままにする",
"passwordProtection": "パスワード保護",
"passwordLabel": "パスワード",
"create": "共有を作成",
"success": "共有が正常に作成されました",
"error": "共有の作成に失敗しました"
},
"fileActions": {
"editFile": "ファイルを編集",
"nameLabel": "名前",
"namePlaceholder": "新しい名前を入力してください",
"extension": "拡張子",
"descriptionLabel": "説明",
"descriptionPlaceholder": "ファイルの説明を入力してください",
"deleteFile": "ファイルを削除",
"deleteConfirmation": "\"{{fileName}}\"を削除してもよろしいですか?",
"deleteWarning": "この操作は元に戻せません。"
},
"filePreview": {
"loading": "プレビューを読み込み中...",
"notAvailable": "プレビューは利用できません",
"downloadToView": "内容を見るためにファイルをダウンロードしてください",
"audioNotSupported": "お使いのブラウザはオーディオ要素をサポートしていません",
"videoNotSupported": "お使いのブラウザはビデオ要素をサポートしていません",
"loadError": "プレビューの読み込みに失敗しました",
"downloadError": "ファイルのダウンロードに失敗しました"
},
"generateShareLink": {
"generateTitle": "共有リンクを生成",
"updateTitle": "共有リンクを更新",
"generateDescription": "ファイルを共有するためのリンクを生成します",
"updateDescription": "この共有リンクのエイリアスを更新します",
"aliasPlaceholder": "エイリアスを入力してください",
"linkReady": "共有リンクの準備ができました:",
"generateButton": "リンクを生成",
"updateButton": "リンクを更新",
"copyButton": "リンクをコピー",
"success": "リンクが正常に生成されました",
"error": "リンクの生成に失敗しました",
"copied": "リンクがクリップボードにコピーされました"
},
"shareActions": {
"deleteTitle": "共有を削除",
"deleteConfirmation": "この共有を削除してもよろしいですか?この操作は元に戻せません。",
"editTitle": "共有を編集",
"nameLabel": "共有名",
"expirationLabel": "有効期限",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "最大ビュー数",
"maxViewsPlaceholder": "無制限の場合は空白のままにする",
"passwordProtection": "パスワード保護",
"passwordLabel": "パスワード",
"passwordPlaceholder": "パスワードを入力してください",
"newPasswordLabel": "新しいパスワード(現在のパスワードを保持する場合は空白のまま)",
"newPasswordPlaceholder": "新しいパスワードを入力してください",
"manageFilesTitle": "ファイルの管理",
"manageRecipientsTitle": "受信者の管理",
"editSuccess": "共有が正常に更新されました",
"editError": "共有の更新に失敗しました"
},
"shareDetails": {
"title": "共有の詳細",
"subtitle": "この共有の詳細情報",
"basicInfo": "基本情報",
"name": "名前",
"untitled": "無題",
"views": "ビュー数",
"dates": "日付",
"created": "作成日",
"expires": "有効期限",
"never": "なし",
"security": "セキュリティ",
"passwordProtected": "パスワード保護",
"publicAccess": "公開アクセス",
"maxViews": "最大ビュー数: {{count}}",
"files": "ファイル ({{count}})",
"recipients": "受信者 ({{count}})",
"notAvailable": "該当なし",
"invalidDate": "無効な日付です",
"loadError": "共有の詳細の読み込みに失敗しました"
},
"uploadFile": {
"title": "ファイルをアップロード",
"selectFile": "ファイルを選択するにはクリックしてください",
"preview": "プレビュー",
"uploadProgress": "アップロードの進行状況",
"upload": "アップロード",
"success": "ファイルが正常にアップロードされました",
"error": "ファイルのアップロードに失敗しました"
},
"filesTable": {
"ariaLabel": "ファイルテーブル",
"columns": {
"name": "名前",
"description": "説明",
"size": "サイズ",
"createdAt": "作成日",
"updatedAt": "更新日",
"actions": "操作"
},
"actions": {
"menu": "ファイル操作メニュー",
"preview": "プレビュー",
"edit": "編集",
"download": "ダウンロード",
"delete": "削除"
}
},
"sharesTable": {
"ariaLabel": "共有テーブル",
"never": "なし",
"columns": {
"name": "名前",
"createdAt": "作成日",
"expiresAt": "有効期限",
"status": "ステータス",
"security": "セキュリティ",
"files": "ファイル",
"recipients": "受信者",
"actions": "操作"
},
"status": {
"neverExpires": "無期限",
"active": "アクティブ",
"expired": "期限切れ"
},
"security": {
"protected": "保護済み",
"public": "公開"
},
"filesCount": "{{count}} ファイル",
"recipientsCount": "{{count}} 受信者",
"actions": {
"menu": "共有操作メニュー",
"edit": "編集",
"manageFiles": "ファイル管理",
"manageRecipients": "受信者管理",
"viewDetails": "詳細を表示",
"generateLink": "リンクを生成",
"editLink": "リンクを編集",
"copyLink": "リンクをコピー",
"notifyRecipients": "受信者に通知",
"delete": "削除"
}
},
"footer": {
"poweredBy": "提供:",
"kyanHomepage": "Kyantech ホームページ"
},
"fileManager": {
"downloadError": "ファイルのダウンロードに失敗しました",
"updateSuccess": "ファイルが正常に更新されました",
"updateError": "ファイルの更新に失敗しました",
"deleteSuccess": "ファイルが正常に削除されました",
"deleteError": "ファイルの削除に失敗しました"
},
"shareManager": {
"deleteSuccess": "共有が正常に削除されました",
"deleteError": "共有の削除に失敗しました",
"updateSuccess": "共有が正常に更新されました",
"updateError": "共有の更新に失敗しました",
"filesUpdateSuccess": "ファイルが正常に更新されました",
"filesUpdateError": "ファイルの更新に失敗しました",
"recipientsUpdateSuccess": "受信者が正常に更新されました",
"recipientsUpdateError": "受信者の更新に失敗しました",
"linkGenerateSuccess": "共有リンクが正常に生成されました",
"linkGenerateError": "共有リンクの生成に失敗しました",
"notifyLoading": "通知を送信中...",
"notifySuccess": "受信者に正常に通知しました",
"notifyError": "受信者への通知に失敗しました"
},
"quickAccess": {
"files": {
"title": "マイファイル",
"description": "アップロードされたファイルにアクセスし、管理します"
},
"shares": {
"title": "マイ共有",
"description": "共有されたファイルを表示および管理します"
}
},
"recentFiles": {
"title": "最近のアップロード",
"viewAll": "すべて表示",
"uploadFile": "ファイルをアップロード",
"noFiles": "まだファイルがアップロードされていません"
},
"recentShares": {
"title": "最近の共有",
"viewAll": "すべて表示",
"createShare": "共有を作成",
"noShares": "まだ共有が作成されていません",
"createFirst": "最初の共有を作成してください"
},
"storageUsage": {
"title": "ストレージ使用量",
"ariaLabel": "ストレージ使用状況のプログレスバー",
"used": "{{size}} 使用済み",
"available": "{{size}} 利用可能"
},
"dashboard": {
"loadError": "ダッシュボードデータの読み込みに失敗しました",
"linkCopied": "リンクがクリップボードにコピーされました",
"pageTitle": "ダッシュボード",
"breadcrumb": "ダッシュボード"
},
"emptyState": {
"noFiles": "まだファイルがアップロードされていません",
"uploadFile": "ファイルをアップロード"
},
"files": {
"title": "すべてのファイル",
"uploadFile": "ファイルをアップロード",
"loadError": "ファイルの読み込みに失敗しました",
"pageTitle": "マイファイル",
"breadcrumb": "マイファイル"
},
"searchBar": {
"placeholder": "ファイルを検索...",
"results": "全{{total}}件中{{filtered}}件が見つかりました"
},
"forgotPassword": {
"emailLabel": "メールアドレス",
"emailPlaceholder": "メールアドレスを入力してください",
"sending": "送信中...",
"submit": "パスワードリセットの指示を送信",
"backToLogin": "ログインに戻る",
"title": "パスワードをお忘れですか?",
"description": "メールアドレスを入力すると、パスワードリセットの指示を送信します。",
"resetInstructions": "パスワードリセットの指示がメールに送信されました",
"pageTitle": "パスワードをお忘れですか?"
},
"home": {
"description": "WeTransferのオープンソース代替です。トラッキングや制限なしに安全にファイルを共有します。",
"documentation": "ドキュメント",
"starOnGithub": "GitHubでスターを付ける",
"privacyMessage": "プライバシーを重視して作られています。アップロード前のファイルは、共有リンクを持つ人だけがアクセスできます。常に無料でオープンソースです。",
"header": {
"fileSharing": "ファイル共有",
"tagline": "シンプルで無料"
},
"pageTitle": "ホーム"
},
"profile": {
"password": {
"title": "パスワードを変更",
"newPassword": "新しいパスワード",
"confirmPassword": "新しいパスワードの確認",
"updateButton": "パスワードを更新"
},
"form": {
"title": "プロフィール情報",
"firstName": "名",
"lastName": "姓",
"username": "ユーザー名",
"email": "メール",
"updateButton": "プロフィールを更新"
},
"header": {
"title": "プロフィール",
"subtitle": "個人情報とパスワードを管理"
},
"picture": {
"title": "プロフィール写真",
"description": "写真アイコンをクリックしてプロフィール写真を変更",
"uploadPhoto": "写真をアップロード",
"removePhoto": "写真を削除"
},
"errors": {
"loadFailed": "ユーザーデータの読み込みに失敗しました",
"updateFailed": "プロフィールの更新に失敗しました",
"passwordFailed": "パスワードの更新に失敗しました",
"imageFailed": "プロフィール画像の更新に失敗しました",
"imageRemoveFailed": "プロフィール画像の削除に失敗しました"
},
"messages": {
"noChanges": "保存する変更はありません",
"updateSuccess": "プロフィールが正常に更新されました",
"fillPasswords": "両方のパスワードフィールドに入力してください",
"passwordSuccess": "パスワードが正常に更新されました",
"imageSuccess": "プロフィール画像が正常に更新されました",
"imageRemoved": "プロフィール画像が正常に削除されました"
},
"pageTitle": "プロフィール"
},
"resetPassword": {
"pageTitle": "パスワードリセット",
"header": {
"title": "パスワードリセット",
"description": "以下に新しいパスワードを入力してください"
},
"form": {
"newPassword": "新しいパスワード",
"newPasswordPlaceholder": "新しいパスワードを入力してください",
"confirmPassword": "新しいパスワードの確認",
"confirmPasswordPlaceholder": "新しいパスワードを再入力してください",
"resetting": "パスワードをリセット中...",
"submit": "パスワードをリセット",
"backToLogin": "ログインに戻る"
},
"messages": {
"success": "パスワードが正常にリセットされました"
},
"errors": {
"serverError": "パスワードのリセットに失敗しました。もう一度お試しください。",
"invalidToken": "無効なリセットトークン、またはトークンが存在しません"
}
},
"settings": {
"groups": {
"defaultDescription": "構成オプション",
"general": {
"title": "一般",
"description": "基本的なアプリケーション設定"
},
"email": {
"title": "メール",
"description": "メールサーバーの設定"
},
"security": {
"title": "セキュリティ",
"description": "セキュリティおよび認証設定"
},
"storage": {
"title": "ストレージ",
"description": "ファイルストレージの設定"
}
},
"fields": {
"noDescription": "利用可能な説明はありません",
"appLogo": {
"title": "アプリケーションロゴ",
"description": "アプリケーションのロゴ画像"
},
"appName": {
"title": "アプリケーション名",
"description": "ユーザーに表示されるアプリケーション名"
},
"appDescription": {
"title": "アプリケーションの説明",
"description": "アプリケーションの簡単な説明"
},
"showHomePage": {
"title": "ホームページを表示",
"description": "インストール後にホームページを表示"
},
"smtpEnabled": {
"title": "SMTP有効",
"description": "SMTPメール機能を有効または無効にする"
},
"smtpHost": {
"title": "SMTPサーバー",
"description": "SMTPサーバーのアドレス"
},
"smtpPort": {
"title": "SMTPポート",
"description": "SMTPサーバーのポート"
},
"smtpUser": {
"title": "SMTPユーザー",
"description": "SMTP認証用のユーザー名"
},
"smtpPass": {
"title": "SMTPパスワード",
"description": "SMTP認証用のパスワード"
},
"smtpFromName": {
"title": "送信者名",
"description": "送信されるメールの表示名"
},
"smtpFromEmail": {
"title": "送信者メール",
"description": "送信者のメールアドレス"
},
"maxLoginAttempts": {
"title": "最大ログイン試行回数",
"description": "ブロックする前の最大ログイン試行回数"
},
"loginBlockDuration": {
"title": "ログインブロック期間",
"description": "試行回数超過後のブロック期間(秒単位)"
},
"passwordMinLength": {
"title": "パスワードの最小長",
"description": "パスワードに必要な最小文字数"
},
"passwordResetTokenExpiration": {
"title": "リセットトークンの有効期限",
"description": "パスワードリセットトークンの有効期間(秒単位)"
},
"maxFileSize": {
"title": "最大ファイルサイズ",
"description": "アップロード可能な最大ファイルサイズ(バイト単位)"
},
"maxTotalStoragePerUser": {
"title": "ユーザーごとの最大ストレージ",
"description": "ユーザーごとの総ストレージ制限(バイト単位)"
}
},
"buttons": {
"save": "{{group}}を保存"
},
"errors": {
"loadFailed": "設定の読み込みに失敗しました",
"updateFailed": "設定の更新に失敗しました"
},
"messages": {
"noChanges": "保存する変更はありません",
"updateSuccess": "{{group}}の設定が正常に更新されました"
},
"title": "設定",
"breadcrumb": "設定",
"pageTitle": "設定"
},
"share": {
"errors": {
"invalidPassword": "無効なパスワードです。もう一度お試しください。",
"loadFailed": "共有の読み込みに失敗しました",
"downloadFailed": "ファイルのダウンロードに失敗しました"
},
"messages": {
"downloadStarted": "ダウンロードが開始されました"
},
"password": {
"title": "パスワード保護された共有",
"protected": "この共有はパスワードで保護されています",
"incorrect": "パスワードが正しくありません。もう一度お試しください。",
"label": "パスワード",
"placeholder": "共有のパスワードを入力してください",
"submit": "送信"
},
"details": {
"untitled": "無題",
"created": "作成日: {{date}}",
"expires": "有効期限: {{date}}"
},
"notFound": {
"title": "共有が見つかりません",
"description": "この共有は削除されたか、期限が切れている可能性があります。"
},
"pageTitle": "共有"
},
"shares": {
"errors": {
"loadFailed": "共有の読み込みに失敗しました",
"notifyFailed": "受信者への通知に失敗しました",
"smtpConfigFailed": "SMTP設定の読み込みに失敗しました"
},
"messages": {
"linkCopied": "リンクがクリップボードにコピーされました",
"recipientsNotified": "受信者に正常に通知されました"
},
"empty": {
"message": "まだ共有が作成されていません",
"createButton": "共有を作成"
},
"header": {
"title": "マイ共有",
"myShares": "マイ共有"
},
"search": {
"title": "すべての共有",
"createButton": "共有を作成",
"placeholder": "共有を検索...",
"results": "全{{total}}件中{{filtered}}件が見つかりました"
},
"pageTitle": "共有"
},
"users": {
"modes": {
"create": "作成",
"edit": "編集"
},
"errors": {
"loadFailed": "ユーザーの読み込みに失敗しました",
"submitFailed": "ユーザーの{{mode}}に失敗しました",
"deleteFailed": "ユーザーの削除に失敗しました",
"statusUpdateFailed": "ユーザー状態の更新に失敗しました"
},
"messages": {
"createSuccess": "ユーザーが正常に作成されました",
"updateSuccess": "ユーザーが正常に更新されました",
"deleteSuccess": "ユーザーが正常に削除されました",
"activateSuccess": "ユーザーが正常にアクティブ化されました",
"deactivateSuccess": "ユーザーが正常に非アクティブ化されました"
},
"actions": {
"edit": "編集",
"activate": "アクティブ化",
"deactivate": "非アクティブ化",
"delete": "削除"
},
"delete": {
"title": "ユーザー削除の確認",
"confirmation": "{{firstName}} {{lastName}} を削除してもよろしいですか?この操作は元に戻せません。",
"confirm": "ユーザーを削除"
},
"form": {
"titleCreate": "新しいユーザーを追加",
"titleEdit": "ユーザーを編集",
"firstName": "名",
"lastName": "姓",
"username": "ユーザー名",
"email": "メール",
"password": "パスワード",
"newPassword": "新しいパスワード(任意)",
"passwordPlaceholder": "現在のパスワードを保持する場合は空白のままにする",
"role": "役割",
"roleUser": "ユーザー",
"roleAdmin": "管理者",
"create": "作成",
"save": "保存"
},
"status": {
"title": "状態変更の確認",
"confirmation": "{{firstName}} {{lastName}} を{{action}}してもよろしいですか?",
"activate": "アクティブ化",
"deactivate": "非アクティブ化",
"user": "ユーザー"
},
"header": {
"title": "ユーザー管理",
"addUser": "ユーザーを追加",
"management": "ユーザー管理"
},
"table": {
"user": "ユーザー",
"email": "メール",
"status": "状態",
"role": "役割",
"actions": "操作",
"active": "アクティブ",
"inactive": "非アクティブ",
"admin": "管理者",
"userr": "ユーザー"
}
},
"logo": {
"labels": {
"appLogo": "アプリケーションロゴ"
},
"buttons": {
"upload": "ロゴをアップロード",
"remove": "ロゴを削除"
},
"messages": {
"uploadSuccess": "ロゴが正常にアップロードされました",
"removeSuccess": "ロゴが正常に削除されました"
},
"errors": {
"uploadFailed": "ロゴのアップロードに失敗しました",
"removeFailed": "ロゴの削除に失敗しました"
}
},
"navbar": {
"logoAlt": "アプリケーションロゴ",
"profileMenu": "プロフィールメニュー",
"profile": "プロフィール",
"settings": "設定",
"usersManagement": "ユーザー管理",
"logout": "ログアウト"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "에 오신 것을 환영합니다",
"signInToContinue": "계속하려면 로그인하세요",
"emailLabel": "이메일 주소",
"emailPlaceholder": "이메일을 입력하세요",
"passwordLabel": "비밀번호",
"passwordPlaceholder": "비밀번호를 입력하세요",
"signIn": "로그인",
"signingIn": "로그인 중...",
"forgotPassword": "비밀번호를 잊으셨나요?",
"pageTitle": "로그인"
},
"errors": {
"invalidCredentials": "잘못된 이메일 또는 비밀번호입니다",
"userNotFound": "사용자를 찾을 수 없습니다",
"accountLocked": "계정이 잠겼습니다. 나중에 다시 시도하세요",
"unexpectedError": "예기치 않은 오류가 발생했습니다. 다시 시도해주세요"
},
"validation": {
"invalidEmail": "유효하지 않은 이메일 주소입니다",
"passwordMinLength": "비밀번호는 최소 6자 이상이어야 합니다",
"firstNameRequired": "이름은 필수입니다",
"lastNameRequired": "성을 입력하세요",
"usernameLength": "사용자 이름은 최소 3자 이상이어야 합니다",
"usernameSpaces": "사용자 이름에는 공백을 사용할 수 없습니다",
"passwordLength": "비밀번호는 최소 8자 이상이어야 합니다",
"passwordsMatch": "비밀번호가 일치하지 않습니다",
"emailRequired": "이메일은 필수입니다",
"passwordRequired": "비밀번호는 필수입니다"
},
"fileSelector": {
"availableFiles": "사용 가능한 파일 ({{count}})",
"shareFiles": "파일 공유 ({{count}})",
"searchPlaceholder": "파일 검색...",
"noMatchingFiles": "일치하는 파일이 없습니다",
"noAvailableFiles": "사용 가능한 파일이 없습니다",
"noFilesInShare": "공유된 파일이 없습니다",
"saveChanges": "변경 사항 저장"
},
"recipientSelector": {
"emailPlaceholder": "수신자 이메일을 입력하세요",
"add": "추가",
"recipients": "수신자 ({{count}})",
"notifyAll": "모두에게 알림",
"noRecipients": "아직 수신자가 추가되지 않았습니다",
"addSuccess": "수신자가 성공적으로 추가되었습니다",
"addError": "수신자 추가에 실패했습니다",
"removeSuccess": "수신자가 성공적으로 제거되었습니다",
"removeError": "수신자 제거에 실패했습니다",
"sendingNotifications": "알림 전송 중...",
"notifySuccess": "수신자에게 성공적으로 알렸습니다",
"notifyError": "수신자 알림 전송에 실패했습니다"
},
"navigation": {
"dashboard": "대시보드"
},
"common": {
"loading": "로딩 중입니다. 잠시 기다려주세요...",
"cancel": "취소",
"save": "저장",
"delete": "삭제",
"close": "닫기",
"download": "다운로드",
"unexpectedError": "예기치 않은 오류가 발생했습니다. 다시 시도해주세요.",
"yes": "예",
"no": "아니오",
"dashboard": "대시보드"
},
"createShare": {
"title": "공유 생성",
"nameLabel": "공유 이름",
"expirationLabel": "만료 날짜",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "최대 조회수",
"maxViewsPlaceholder": "무제한인 경우 비워두세요",
"passwordProtection": "비밀번호 보호",
"passwordLabel": "비밀번호",
"create": "공유 생성",
"success": "공유가 성공적으로 생성되었습니다",
"error": "공유 생성에 실패했습니다"
},
"fileActions": {
"editFile": "파일 편집",
"nameLabel": "이름",
"namePlaceholder": "새 이름을 입력하세요",
"extension": "확장자",
"descriptionLabel": "설명",
"descriptionPlaceholder": "파일 설명을 입력하세요",
"deleteFile": "파일 삭제",
"deleteConfirmation": "\"{{fileName}}\"을(를) 삭제하시겠습니까?",
"deleteWarning": "이 작업은 취소할 수 없습니다."
},
"filePreview": {
"loading": "미리보기를 불러오는 중...",
"notAvailable": "미리보기를 사용할 수 없습니다",
"downloadToView": "내용을 보려면 파일을 다운로드하세요",
"audioNotSupported": "브라우저가 오디오 요소를 지원하지 않습니다",
"videoNotSupported": "브라우저가 비디오 요소를 지원하지 않습니다",
"loadError": "미리보기 불러오기에 실패했습니다",
"downloadError": "파일 다운로드에 실패했습니다"
},
"generateShareLink": {
"generateTitle": "공유 링크 생성",
"updateTitle": "공유 링크 업데이트",
"generateDescription": "파일을 공유할 링크를 생성합니다",
"updateDescription": "이 공유 링크의 별칭을 업데이트합니다",
"aliasPlaceholder": "별칭을 입력하세요",
"linkReady": "공유 링크가 준비되었습니다:",
"generateButton": "링크 생성",
"updateButton": "링크 업데이트",
"copyButton": "링크 복사",
"success": "링크가 성공적으로 생성되었습니다",
"error": "링크 생성에 실패했습니다",
"copied": "링크가 클립보드에 복사되었습니다"
},
"shareActions": {
"deleteTitle": "공유 삭제",
"deleteConfirmation": "이 공유를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.",
"editTitle": "공유 편집",
"nameLabel": "공유 이름",
"expirationLabel": "만료 날짜",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "최대 조회수",
"maxViewsPlaceholder": "무제한인 경우 비워두세요",
"passwordProtection": "비밀번호 보호",
"passwordLabel": "비밀번호",
"passwordPlaceholder": "비밀번호를 입력하세요",
"newPasswordLabel": "새 비밀번호 (현재 비밀번호 유지 시 비워두세요)",
"newPasswordPlaceholder": "새 비밀번호를 입력하세요",
"manageFilesTitle": "파일 관리",
"manageRecipientsTitle": "수신자 관리",
"editSuccess": "공유가 성공적으로 업데이트되었습니다",
"editError": "공유 업데이트에 실패했습니다"
},
"shareDetails": {
"title": "공유 세부 정보",
"subtitle": "이 공유에 대한 자세한 정보",
"basicInfo": "기본 정보",
"name": "이름",
"untitled": "제목 없음",
"views": "조회수",
"dates": "날짜",
"created": "생성됨",
"expires": "만료됨",
"never": "없음",
"security": "보안",
"passwordProtected": "비밀번호 보호됨",
"publicAccess": "공개 접근",
"maxViews": "최대 조회수: {{count}}",
"files": "파일 ({{count}})",
"recipients": "수신자 ({{count}})",
"notAvailable": "해당 없음",
"invalidDate": "유효하지 않은 날짜입니다",
"loadError": "공유 세부 정보를 불러오는데 실패했습니다"
},
"uploadFile": {
"title": "파일 업로드",
"selectFile": "파일 선택을 위해 클릭하세요",
"preview": "미리보기",
"uploadProgress": "업로드 진행",
"upload": "업로드",
"success": "파일이 성공적으로 업로드되었습니다",
"error": "파일 업로드에 실패했습니다"
},
"filesTable": {
"ariaLabel": "파일 테이블",
"columns": {
"name": "이름",
"description": "설명",
"size": "크기",
"createdAt": "생성일",
"updatedAt": "수정일",
"actions": "작업"
},
"actions": {
"menu": "파일 작업 메뉴",
"preview": "미리보기",
"edit": "편집",
"download": "다운로드",
"delete": "삭제"
}
},
"sharesTable": {
"ariaLabel": "공유 테이블",
"never": "없음",
"columns": {
"name": "이름",
"createdAt": "생성일",
"expiresAt": "만료일",
"status": "상태",
"security": "보안",
"files": "파일",
"recipients": "수신자",
"actions": "작업"
},
"status": {
"neverExpires": "만료되지 않음",
"active": "활성",
"expired": "만료됨"
},
"security": {
"protected": "보호됨",
"public": "공개"
},
"filesCount": "{{count}}개의 파일",
"recipientsCount": "{{count}}명의 수신자",
"actions": {
"menu": "공유 작업 메뉴",
"edit": "편집",
"manageFiles": "파일 관리",
"manageRecipients": "수신자 관리",
"viewDetails": "세부 정보 보기",
"generateLink": "링크 생성",
"editLink": "링크 편집",
"copyLink": "링크 복사",
"notifyRecipients": "수신자 알림",
"delete": "삭제"
}
},
"footer": {
"poweredBy": "제공:",
"kyanHomepage": "Kyantech 홈페이지"
},
"fileManager": {
"downloadError": "파일 다운로드에 실패했습니다",
"updateSuccess": "파일이 성공적으로 업데이트되었습니다",
"updateError": "파일 업데이트에 실패했습니다",
"deleteSuccess": "파일이 성공적으로 삭제되었습니다",
"deleteError": "파일 삭제에 실패했습니다"
},
"shareManager": {
"deleteSuccess": "공유가 성공적으로 삭제되었습니다",
"deleteError": "공유 삭제에 실패했습니다",
"updateSuccess": "공유가 성공적으로 업데이트되었습니다",
"updateError": "공유 업데이트에 실패했습니다",
"filesUpdateSuccess": "파일이 성공적으로 업데이트되었습니다",
"filesUpdateError": "파일 업데이트에 실패했습니다",
"recipientsUpdateSuccess": "수신자가 성공적으로 업데이트되었습니다",
"recipientsUpdateError": "수신자 업데이트에 실패했습니다",
"linkGenerateSuccess": "공유 링크가 성공적으로 생성되었습니다",
"linkGenerateError": "공유 링크 생성에 실패했습니다",
"notifyLoading": "알림 전송 중...",
"notifySuccess": "수신자에게 성공적으로 알렸습니다",
"notifyError": "수신자 알림 전송에 실패했습니다"
},
"quickAccess": {
"files": {
"title": "내 파일",
"description": "업로드된 파일에 접근하고 관리합니다"
},
"shares": {
"title": "내 공유",
"description": "공유된 파일을 보고 관리합니다"
}
},
"recentFiles": {
"title": "최근 업로드",
"viewAll": "전체 보기",
"uploadFile": "파일 업로드",
"noFiles": "아직 파일이 업로드되지 않았습니다"
},
"recentShares": {
"title": "최근 공유",
"viewAll": "전체 보기",
"createShare": "공유 생성",
"noShares": "아직 공유가 생성되지 않았습니다",
"createFirst": "첫 번째 공유를 생성하세요"
},
"storageUsage": {
"title": "스토리지 사용량",
"ariaLabel": "스토리지 사용량 진행 바",
"used": "{{size}} 사용됨",
"available": "{{size}} 사용 가능"
},
"dashboard": {
"loadError": "대시보드 데이터를 불러오는데 실패했습니다",
"linkCopied": "링크가 클립보드에 복사되었습니다",
"pageTitle": "대시보드",
"breadcrumb": "대시보드"
},
"emptyState": {
"noFiles": "아직 파일이 업로드되지 않았습니다",
"uploadFile": "파일 업로드"
},
"files": {
"title": "모든 파일",
"uploadFile": "파일 업로드",
"loadError": "파일을 불러오는데 실패했습니다",
"pageTitle": "내 파일",
"breadcrumb": "내 파일"
},
"searchBar": {
"placeholder": "파일 검색...",
"results": "전체 {{total}}개 중 {{filtered}}개 파일을 찾았습니다"
},
"forgotPassword": {
"emailLabel": "이메일 주소",
"emailPlaceholder": "이메일을 입력하세요",
"sending": "전송 중...",
"submit": "비밀번호 재설정 지침 전송",
"backToLogin": "로그인으로 돌아가기",
"title": "비밀번호를 잊으셨나요?",
"description": "이메일 주소를 입력하면 비밀번호 재설정 지침을 보내드립니다.",
"resetInstructions": "비밀번호 재설정 지침이 이메일로 전송되었습니다",
"pageTitle": "비밀번호를 잊으셨나요?"
},
"home": {
"description": "WeTransfer의 오픈소스 대안입니다. 추적이나 제한 없이 파일을 안전하게 공유하세요.",
"documentation": "문서",
"starOnGithub": "GitHub에서 별표 달기",
"privacyMessage": "개인정보 보호를 고려하여 제작되었습니다. 업로드 전 파일은 공유 링크가 있는 사람만 접근할 수 있습니다. 항상 무료이며 오픈소스입니다.",
"header": {
"fileSharing": "파일 공유",
"tagline": "심플하고 무료"
},
"pageTitle": "홈"
},
"profile": {
"password": {
"title": "비밀번호 변경",
"newPassword": "새 비밀번호",
"confirmPassword": "새 비밀번호 확인",
"updateButton": "비밀번호 업데이트"
},
"form": {
"title": "프로필 정보",
"firstName": "이름",
"lastName": "성",
"username": "사용자 이름",
"email": "이메일",
"updateButton": "프로필 업데이트"
},
"header": {
"title": "프로필",
"subtitle": "개인 정보와 비밀번호를 관리하세요"
},
"picture": {
"title": "프로필 사진",
"description": "프로필 사진을 변경하려면 카메라 아이콘을 클릭하세요",
"uploadPhoto": "사진 업로드",
"removePhoto": "사진 삭제"
},
"errors": {
"loadFailed": "사용자 데이터를 불러오는데 실패했습니다",
"updateFailed": "프로필 업데이트에 실패했습니다",
"passwordFailed": "비밀번호 업데이트에 실패했습니다",
"imageFailed": "프로필 이미지 업데이트에 실패했습니다",
"imageRemoveFailed": "프로필 이미지 삭제에 실패했습니다"
},
"messages": {
"noChanges": "저장할 변경 사항이 없습니다",
"updateSuccess": "프로필이 성공적으로 업데이트되었습니다",
"fillPasswords": "두 비밀번호 필드를 모두 입력하세요",
"passwordSuccess": "비밀번호가 성공적으로 업데이트되었습니다",
"imageSuccess": "프로필 이미지가 성공적으로 업데이트되었습니다",
"imageRemoved": "프로필 이미지가 성공적으로 삭제되었습니다"
},
"pageTitle": "프로필"
},
"resetPassword": {
"pageTitle": "비밀번호 재설정",
"header": {
"title": "비밀번호 재설정",
"description": "아래에 새 비밀번호를 입력하세요"
},
"form": {
"newPassword": "새 비밀번호",
"newPasswordPlaceholder": "새 비밀번호를 입력하세요",
"confirmPassword": "새 비밀번호 확인",
"confirmPasswordPlaceholder": "새 비밀번호를 다시 입력하세요",
"resetting": "비밀번호 재설정 중...",
"submit": "비밀번호 재설정",
"backToLogin": "로그인으로 돌아가기"
},
"messages": {
"success": "비밀번호가 성공적으로 재설정되었습니다"
},
"errors": {
"serverError": "비밀번호 재설정에 실패했습니다. 다시 시도해주세요.",
"invalidToken": "유효하지 않거나 누락된 재설정 토큰"
}
},
"settings": {
"groups": {
"defaultDescription": "구성 옵션",
"general": {
"title": "일반",
"description": "기본 애플리케이션 설정"
},
"email": {
"title": "이메일",
"description": "이메일 서버 구성"
},
"security": {
"title": "보안",
"description": "보안 및 인증 설정"
},
"storage": {
"title": "스토리지",
"description": "파일 스토리지 구성"
}
},
"fields": {
"noDescription": "설명이 제공되지 않았습니다",
"appLogo": {
"title": "애플리케이션 로고",
"description": "애플리케이션 로고 이미지"
},
"appName": {
"title": "애플리케이션 이름",
"description": "사용자에게 표시되는 애플리케이션 이름"
},
"appDescription": {
"title": "애플리케이션 설명",
"description": "애플리케이션에 대한 간략한 설명"
},
"showHomePage": {
"title": "홈페이지 표시",
"description": "설치 후 홈페이지를 표시합니다"
},
"smtpEnabled": {
"title": "SMTP 사용",
"description": "SMTP 이메일 기능을 활성화 또는 비활성화합니다"
},
"smtpHost": {
"title": "SMTP 서버",
"description": "SMTP 서버 주소"
},
"smtpPort": {
"title": "SMTP 포트",
"description": "SMTP 서버 포트"
},
"smtpUser": {
"title": "SMTP 사용자",
"description": "SMTP 인증을 위한 사용자 이름"
},
"smtpPass": {
"title": "SMTP 비밀번호",
"description": "SMTP 인증을 위한 비밀번호"
},
"smtpFromName": {
"title": "발신자 이름",
"description": "보내는 이메일에 표시될 이름"
},
"smtpFromEmail": {
"title": "발신자 이메일",
"description": "발신자 이메일 주소"
},
"maxLoginAttempts": {
"title": "최대 로그인 시도 횟수",
"description": "차단되기 전 최대 로그인 시도 횟수"
},
"loginBlockDuration": {
"title": "로그인 차단 기간",
"description": "시도 초과 시 차단되는 시간(초 단위)"
},
"passwordMinLength": {
"title": "최소 비밀번호 길이",
"description": "비밀번호에 필요한 최소 문자 수"
},
"passwordResetTokenExpiration": {
"title": "비밀번호 재설정 토큰 만료",
"description": "비밀번호 재설정 토큰의 유효 기간(초 단위)"
},
"maxFileSize": {
"title": "최대 파일 크기",
"description": "업로드 가능한 최대 파일 크기(바이트 단위)"
},
"maxTotalStoragePerUser": {
"title": "사용자당 최대 스토리지",
"description": "사용자당 총 스토리지 제한(바이트 단위)"
}
},
"buttons": {
"save": "{{group}} 저장"
},
"errors": {
"loadFailed": "설정을 불러오는데 실패했습니다",
"updateFailed": "설정 업데이트에 실패했습니다"
},
"messages": {
"noChanges": "저장할 변경 사항이 없습니다",
"updateSuccess": "{{group}} 설정이 성공적으로 업데이트되었습니다"
},
"title": "설정",
"breadcrumb": "설정",
"pageTitle": "설정"
},
"share": {
"errors": {
"invalidPassword": "잘못된 비밀번호입니다. 다시 시도해주세요.",
"loadFailed": "공유를 불러오는데 실패했습니다",
"downloadFailed": "파일 다운로드에 실패했습니다"
},
"messages": {
"downloadStarted": "다운로드가 시작되었습니다"
},
"password": {
"title": "비밀번호 보호 공유",
"protected": "이 공유는 비밀번호로 보호되어 있습니다",
"incorrect": "비밀번호가 올바르지 않습니다. 다시 시도해주세요.",
"label": "비밀번호",
"placeholder": "공유 비밀번호를 입력하세요",
"submit": "제출"
},
"details": {
"untitled": "제목 없음",
"created": "생성됨: {{date}}",
"expires": "만료됨: {{date}}"
},
"notFound": {
"title": "공유를 찾을 수 없습니다",
"description": "이 공유는 삭제되었거나 만료되었을 수 있습니다."
},
"pageTitle": "공유"
},
"shares": {
"errors": {
"loadFailed": "공유 목록을 불러오는데 실패했습니다",
"notifyFailed": "수신자 알림에 실패했습니다",
"smtpConfigFailed": "SMTP 설정을 불러오는데 실패했습니다"
},
"messages": {
"linkCopied": "링크가 클립보드에 복사되었습니다",
"recipientsNotified": "수신자에게 성공적으로 알렸습니다"
},
"empty": {
"message": "아직 공유가 생성되지 않았습니다",
"createButton": "공유 생성"
},
"header": {
"title": "내 공유",
"myShares": "내 공유"
},
"search": {
"title": "전체 공유",
"createButton": "공유 생성",
"placeholder": "공유 검색...",
"results": "전체 {{total}}개 중 {{filtered}}개가 검색되었습니다"
},
"pageTitle": "공유"
},
"users": {
"modes": {
"create": "생성",
"edit": "편집"
},
"errors": {
"loadFailed": "사용자 목록을 불러오는데 실패했습니다",
"submitFailed": "사용자 {{mode}}에 실패했습니다",
"deleteFailed": "사용자 삭제에 실패했습니다",
"statusUpdateFailed": "사용자 상태 업데이트에 실패했습니다"
},
"messages": {
"createSuccess": "사용자가 성공적으로 생성되었습니다",
"updateSuccess": "사용자가 성공적으로 업데이트되었습니다",
"deleteSuccess": "사용자가 성공적으로 삭제되었습니다",
"activateSuccess": "사용자가 성공적으로 활성화되었습니다",
"deactivateSuccess": "사용자가 성공적으로 비활성화되었습니다"
},
"actions": {
"edit": "편집",
"activate": "활성화",
"deactivate": "비활성화",
"delete": "삭제"
},
"delete": {
"title": "사용자 삭제 확인",
"confirmation": "{{firstName}} {{lastName}} 사용자를 삭제하시겠습니까? 이 작업은 취소할 수 없습니다.",
"confirm": "사용자 삭제"
},
"form": {
"titleCreate": "새 사용자 추가",
"titleEdit": "사용자 편집",
"firstName": "이름",
"lastName": "성",
"username": "사용자 이름",
"email": "이메일",
"password": "비밀번호",
"newPassword": "새 비밀번호 (선택 사항)",
"passwordPlaceholder": "현재 비밀번호를 유지하려면 비워두세요",
"role": "역할",
"roleUser": "사용자",
"roleAdmin": "관리자",
"create": "생성",
"save": "저장"
},
"status": {
"title": "상태 변경 확인",
"confirmation": "{{firstName}} {{lastName}} 사용자를 {{action}}하시겠습니까?",
"activate": "활성화",
"deactivate": "비활성화",
"user": "사용자"
},
"header": {
"title": "사용자 관리",
"addUser": "사용자 추가",
"management": "사용자 관리"
},
"table": {
"user": "사용자",
"email": "이메일",
"status": "상태",
"role": "역할",
"actions": "작업",
"active": "활성",
"inactive": "비활성",
"admin": "관리자",
"userr": "사용자"
}
},
"logo": {
"labels": {
"appLogo": "애플리케이션 로고"
},
"buttons": {
"upload": "로고 업로드",
"remove": "로고 삭제"
},
"messages": {
"uploadSuccess": "로고가 성공적으로 업로드되었습니다",
"removeSuccess": "로고가 성공적으로 삭제되었습니다"
},
"errors": {
"uploadFailed": "로고 업로드에 실패했습니다",
"removeFailed": "로고 삭제에 실패했습니다"
}
},
"navbar": {
"logoAlt": "애플리케이션 로고",
"profileMenu": "프로필 메뉴",
"profile": "프로필",
"settings": "설정",
"usersManagement": "사용자 관리",
"logout": "로그아웃"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Bem-vindo ao",
"signInToContinue": "Entre para continuar",
"emailLabel": "Endereço de E-mail",
"emailPlaceholder": "Digite seu e-mail",
"passwordLabel": "Senha",
"passwordPlaceholder": "Digite sua senha",
"signIn": "Entrar",
"signingIn": "Entrando...",
"forgotPassword": "Esqueceu a senha?",
"pageTitle": "Entrar"
},
"errors": {
"invalidCredentials": "E-mail ou senha inválidos",
"userNotFound": "Usuário não encontrado",
"accountLocked": "Conta bloqueada. Tente novamente mais tarde",
"unexpectedError": "Ocorreu um erro inesperado. Por favor, tente novamente"
},
"validation": {
"invalidEmail": "Endereço de email inválido",
"passwordMinLength": "A senha deve ter pelo menos 6 caracteres",
"firstNameRequired": "Nome é obrigatório",
"lastNameRequired": "Sobrenome é obrigatório",
"usernameLength": "Nome de usuário deve ter pelo menos 3 caracteres",
"usernameSpaces": "Nome de usuário não pode conter espaços",
"passwordLength": "A senha deve ter pelo menos 8 caracteres",
"passwordsMatch": "As senhas não coincidem",
"emailRequired": "Email é obrigatório",
"passwordRequired": "Senha é obrigatória"
},
"fileSelector": {
"availableFiles": "Arquivos Disponíveis ({{count}})",
"shareFiles": "Arquivos Compartilhados ({{count}})",
"searchPlaceholder": "Buscar arquivos...",
"noMatchingFiles": "Nenhum arquivo encontrado",
"noAvailableFiles": "Nenhum arquivo disponível",
"noFilesInShare": "Nenhum arquivo compartilhado",
"saveChanges": "Salvar Alterações"
},
"recipientSelector": {
"emailPlaceholder": "Digite o e-mail do destinatário",
"add": "Adicionar",
"recipients": "Destinatários ({{count}})",
"notifyAll": "Notificar Todos",
"noRecipients": "Nenhum destinatário adicionado",
"addSuccess": "Destinatário adicionado com sucesso",
"addError": "Falha ao adicionar destinatário",
"removeSuccess": "Destinatário removido com sucesso",
"removeError": "Falha ao remover destinatário",
"sendingNotifications": "Enviando notificações...",
"notifySuccess": "Destinatários notificados com sucesso",
"notifyError": "Falha ao notificar destinatários"
},
"navigation": {
"dashboard": "Painel"
},
"common": {
"loading": "Carregando, aguarde...",
"cancel": "Cancelar",
"save": "Salvar",
"delete": "Excluir",
"close": "Fechar",
"download": "Baixar",
"unexpectedError": "Ocorreu um erro inesperado. Por favor, tente novamente.",
"yes": "Sim",
"no": "Não",
"dashboard": "Painel"
},
"createShare": {
"title": "Criar Compartilhamento",
"nameLabel": "Nome do Compartilhamento",
"expirationLabel": "Data de Expiração",
"expirationPlaceholder": "DD/MM/AAAA HH:MM",
"maxViewsLabel": "Máximo de Visualizações",
"maxViewsPlaceholder": "Deixe vazio para ilimitado",
"passwordProtection": "Protegido por Senha",
"passwordLabel": "Senha",
"create": "Criar Compartilhamento",
"success": "Compartilhamento criado com sucesso",
"error": "Falha ao criar compartilhamento"
},
"fileActions": {
"editFile": "Editar Arquivo",
"nameLabel": "Nome",
"namePlaceholder": "Digite o novo nome",
"extension": "Extensão",
"descriptionLabel": "Descrição",
"descriptionPlaceholder": "Digite a descrição do arquivo",
"deleteFile": "Excluir Arquivo",
"deleteConfirmation": "Tem certeza que deseja excluir \"{{fileName}}\"?",
"deleteWarning": "Esta ação não pode ser desfeita."
},
"filePreview": {
"loading": "Carregando visualização...",
"notAvailable": "Visualização não disponível",
"downloadToView": "Faça o download para visualizar o conteúdo",
"audioNotSupported": "Seu navegador não suporta o elemento de áudio",
"videoNotSupported": "Seu navegador não suporta o elemento de vídeo",
"loadError": "Falha ao carregar a visualização",
"downloadError": "Falha ao baixar o arquivo"
},
"generateShareLink": {
"generateTitle": "Gerar Link de Compartilhamento",
"updateTitle": "Atualizar Link de Compartilhamento",
"generateDescription": "Gere um link para compartilhar seus arquivos",
"updateDescription": "Atualize o alias deste link de compartilhamento",
"aliasPlaceholder": "Digite o alias",
"linkReady": "Seu link de compartilhamento está pronto:",
"generateButton": "Gerar Link",
"updateButton": "Atualizar Link",
"copyButton": "Copiar Link",
"success": "Link gerado com sucesso",
"error": "Erro ao gerar link",
"copied": "Link copiado para a área de transferência"
},
"shareActions": {
"deleteTitle": "Excluir Compartilhamento",
"deleteConfirmation": "Tem certeza que deseja excluir este compartilhamento? Esta ação não pode ser desfeita.",
"editTitle": "Editar Compartilhamento",
"nameLabel": "Nome do Compartilhamento",
"expirationLabel": "Data de Expiração",
"expirationPlaceholder": "DD/MM/AAAA HH:MM",
"maxViewsLabel": "Máximo de Visualizações",
"maxViewsPlaceholder": "Deixe vazio para ilimitado",
"passwordProtection": "Protegido por Senha",
"passwordLabel": "Senha",
"passwordPlaceholder": "Digite a senha",
"newPasswordLabel": "Nova Senha (deixe vazio para manter a atual)",
"newPasswordPlaceholder": "Digite a nova senha",
"manageFilesTitle": "Gerenciar Arquivos",
"manageRecipientsTitle": "Gerenciar Destinatários",
"editSuccess": "Compartilhamento atualizado com sucesso",
"editError": "Falha ao atualizar compartilhamento"
},
"shareDetails": {
"title": "Detalhes do Compartilhamento",
"subtitle": "Informações detalhadas sobre este compartilhamento",
"basicInfo": "Informações Básicas",
"name": "Nome",
"untitled": "Compartilhamento sem título",
"views": "Visualizações",
"dates": "Datas",
"created": "Criado em: {{date}}",
"expires": "Expira em: {{date}}",
"never": "Nunca",
"security": "Segurança",
"passwordProtected": "Protegido por Senha",
"publicAccess": "Acesso Público",
"maxViews": "Máximo de Visualizações: {{count}}",
"files": "Arquivos ({{count}})",
"recipients": "Destinatários ({{count}})",
"notAvailable": "N/A",
"invalidDate": "Data inválida",
"loadError": "Falha ao carregar detalhes do compartilhamento"
},
"uploadFile": {
"title": "Enviar Arquivo",
"selectFile": "Clique para selecionar um arquivo",
"preview": "Pré-visualização",
"uploadProgress": "Progresso do upload",
"upload": "Enviar",
"success": "Arquivo enviado com sucesso",
"error": "Falha ao enviar arquivo"
},
"filesTable": {
"ariaLabel": "Tabela de arquivos",
"columns": {
"name": "NOME",
"description": "DESCRIÇÃO",
"size": "TAMANHO",
"createdAt": "CRIADO EM",
"updatedAt": "ATUALIZADO EM",
"actions": "AÇÕES"
},
"actions": {
"menu": "Menu de ações do arquivo",
"preview": "Visualizar",
"edit": "Editar",
"download": "Baixar",
"delete": "Excluir"
}
},
"sharesTable": {
"ariaLabel": "Tabela de compartilhamentos",
"never": "Nunca",
"columns": {
"name": "NOME",
"createdAt": "CRIADO EM",
"expiresAt": "EXPIRA EM",
"status": "STATUS",
"security": "SEGURANÇA",
"files": "ARQUIVOS",
"recipients": "DESTINATÁRIOS",
"actions": "AÇÕES"
},
"status": {
"neverExpires": "Nunca Expira",
"active": "Ativo",
"expired": "Expirado"
},
"security": {
"protected": "Protegido",
"public": "Público"
},
"filesCount": "{{count}} arquivos",
"recipientsCount": "{{count}} destinatários",
"actions": {
"menu": "Menu de ações do compartilhamento",
"edit": "Editar",
"manageFiles": "Gerenciar Arquivos",
"manageRecipients": "Gerenciar Destinatários",
"viewDetails": "Ver Detalhes",
"generateLink": "Gerar Link",
"editLink": "Editar Link",
"copyLink": "Copiar Link",
"notifyRecipients": "Notificar Destinatários",
"delete": "Excluir"
}
},
"footer": {
"poweredBy": "Desenvolvido por",
"kyanHomepage": "Página inicial da Kyantech"
},
"fileManager": {
"downloadError": "Falha ao baixar arquivo",
"updateSuccess": "Arquivo atualizado com sucesso",
"updateError": "Falha ao atualizar arquivo",
"deleteSuccess": "Arquivo excluído com sucesso",
"deleteError": "Falha ao excluir arquivo"
},
"shareManager": {
"deleteSuccess": "Compartilhamento excluído com sucesso",
"deleteError": "Falha ao excluir compartilhamento",
"updateSuccess": "Compartilhamento atualizado com sucesso",
"updateError": "Falha ao atualizar compartilhamento",
"filesUpdateSuccess": "Arquivos atualizados com sucesso",
"filesUpdateError": "Falha ao atualizar arquivos",
"recipientsUpdateSuccess": "Destinatários atualizados com sucesso",
"recipientsUpdateError": "Falha ao atualizar destinatários",
"linkGenerateSuccess": "Link de compartilhamento gerado com sucesso",
"linkGenerateError": "Falha ao gerar link de compartilhamento",
"notifyLoading": "Enviando notificações...",
"notifySuccess": "Destinatários notificados com sucesso",
"notifyError": "Falha ao notificar destinatários"
},
"quickAccess": {
"files": {
"title": "Meus Arquivos",
"description": "Acesse e gerencie seus arquivos enviados"
},
"shares": {
"title": "Meus Compartilhamentos",
"description": "Visualize e gerencie seus arquivos compartilhados"
}
},
"recentFiles": {
"title": "Uploads Recentes",
"viewAll": "Ver Todos",
"uploadFile": "Enviar Arquivo",
"noFiles": "Nenhum arquivo enviado ainda"
},
"recentShares": {
"title": "Compartilhamentos Recentes",
"viewAll": "Ver Todos",
"createShare": "Criar Compartilhamento",
"noShares": "Nenhum compartilhamento criado ainda",
"createFirst": "Criar seu primeiro compartilhamento"
},
"storageUsage": {
"title": "Uso de Armazenamento",
"ariaLabel": "Barra de progresso do uso de armazenamento",
"used": "{{size}} usado",
"available": "{{size}} disponível"
},
"dashboard": {
"loadError": "Falha ao carregar dados do painel",
"linkCopied": "Link copiado para a área de transferência",
"pageTitle": "Painel",
"breadcrumb": "Painel"
},
"emptyState": {
"noFiles": "Nenhum arquivo enviado ainda",
"uploadFile": "Enviar Arquivo"
},
"files": {
"title": "Todos os Arquivos",
"uploadFile": "Enviar Arquivo",
"loadError": "Falha ao carregar arquivos",
"pageTitle": "Meus Arquivos",
"breadcrumb": "Meus Arquivos"
},
"searchBar": {
"placeholder": "Buscar arquivos...",
"results": "Encontrados {{filtered}} de {{total}} arquivos"
},
"forgotPassword": {
"emailLabel": "Endereço de Email",
"emailPlaceholder": "Digite seu email",
"sending": "Enviando...",
"submit": "Enviar Instruções de Redefinição",
"backToLogin": "Voltar ao Login",
"title": "Esqueceu a Senha",
"description": "Digite seu endereço de email e enviaremos instruções para redefinir sua senha.",
"resetInstructions": "Instruções de redefinição enviadas para seu email",
"pageTitle": "Esqueceu a Senha"
},
"home": {
"description": "A alternativa open-source ao WeTransfer. Compartilhe arquivos com segurança, sem rastreamento ou limitações.",
"documentation": "Documentação",
"starOnGithub": "Estrela no GitHub",
"privacyMessage": "Construído com privacidade em mente. Seus arquivos antes do upload são acessíveis apenas por aqueles com o link de compartilhamento. Para sempre gratuito e open source.",
"header": {
"fileSharing": "Compartilhamento de arquivos",
"tagline": "simples e gratuito"
},
"pageTitle": "Início"
},
"profile": {
"password": {
"title": "Alterar Senha",
"newPassword": "Nova Senha",
"confirmPassword": "Confirmar Nova Senha",
"updateButton": "Atualizar Senha"
},
"form": {
"title": "Informações do Perfil",
"firstName": "Nome",
"lastName": "Sobrenome",
"username": "Nome de Usuário",
"email": "Email",
"updateButton": "Atualizar Perfil"
},
"header": {
"title": "Perfil",
"subtitle": "Gerencie suas informações pessoais e senha"
},
"picture": {
"title": "Foto do Perfil",
"description": "Clique no ícone da câmera para alterar sua foto de perfil",
"uploadPhoto": "Enviar Foto",
"removePhoto": "Remover Foto"
},
"errors": {
"loadFailed": "Falha ao carregar dados do usuário",
"updateFailed": "Falha ao atualizar perfil",
"passwordFailed": "Falha ao atualizar senha",
"imageFailed": "Falha ao atualizar imagem",
"imageRemoveFailed": "Falha ao remover imagem"
},
"messages": {
"noChanges": "Nenhuma alteração para salvar",
"updateSuccess": "Perfil atualizado com sucesso",
"fillPasswords": "Por favor, preencha ambos os campos de senha",
"passwordSuccess": "Senha atualizada com sucesso",
"imageSuccess": "Imagem de perfil atualizada com sucesso",
"imageRemoved": "Imagem de perfil removida com sucesso"
},
"pageTitle": "Perfil"
},
"resetPassword": {
"pageTitle": "Redefinir Senha",
"header": {
"title": "Redefinir Senha",
"description": "Digite sua nova senha abaixo"
},
"form": {
"newPassword": "Nova Senha",
"newPasswordPlaceholder": "Digite sua nova senha",
"confirmPassword": "Confirmar Nova Senha",
"confirmPasswordPlaceholder": "Confirme sua nova senha",
"resetting": "Redefinindo Senha...",
"submit": "Redefinir Senha",
"backToLogin": "Voltar ao Login"
},
"messages": {
"success": "Senha redefinida com sucesso"
},
"errors": {
"serverError": "Falha ao redefinir senha. Tente novamente.",
"invalidToken": "Token de redefinição inválido ou ausente"
}
},
"settings": {
"groups": {
"defaultDescription": "Opções de configuração",
"general": {
"title": "Geral",
"description": "Configurações básicas da aplicação"
},
"email": {
"title": "Email",
"description": "Configuração do servidor de email"
},
"security": {
"title": "Segurança",
"description": "Configurações de segurança e autenticação"
},
"storage": {
"title": "Armazenamento",
"description": "Configuração de armazenamento de arquivos"
}
},
"fields": {
"noDescription": "Sem descrição disponível",
"appLogo": {
"title": "Logo do Aplicativo",
"description": "Imagem do logo do aplicativo"
},
"appName": {
"title": "Nome do Aplicativo",
"description": "Nome do aplicativo exibido para os usuários"
},
"appDescription": {
"title": "Descrição do Aplicativo",
"description": "Descrição breve do aplicativo"
},
"showHomePage": {
"title": "Exibir Página Inicial",
"description": "Exibe a página inicial após a instalação"
},
"smtpEnabled": {
"title": "SMTP Habilitado",
"description": "Ativa ou desativa a funcionalidade de e-mail via SMTP"
},
"smtpHost": {
"title": "Servidor SMTP",
"description": "Endereço do servidor SMTP"
},
"smtpPort": {
"title": "Porta SMTP",
"description": "Porta do servidor SMTP"
},
"smtpUser": {
"title": "Usuário SMTP",
"description": "Nome de usuário para autenticação SMTP"
},
"smtpPass": {
"title": "Senha SMTP",
"description": "Senha para autenticação SMTP"
},
"smtpFromName": {
"title": "Nome do Remetente",
"description": "Nome exibido para os e-mails enviados"
},
"smtpFromEmail": {
"title": "E-mail do Remetente",
"description": "Endereço de e-mail do remetente"
},
"maxLoginAttempts": {
"title": "Número Máximo de Tentativas de Login",
"description": "Número máximo de tentativas de login antes de bloquear"
},
"loginBlockDuration": {
"title": "Duração do Bloqueio",
"description": "Duração (em segundos) do bloqueio após exceder o número de tentativas"
},
"passwordMinLength": {
"title": "Comprimento Mínimo da Senha",
"description": "Número mínimo de caracteres para senhas"
},
"passwordResetTokenExpiration": {
"title": "Expiração do Token de Redefinição",
"description": "Tempo de validade (em segundos) para o token de redefinição de senha"
},
"maxFileSize": {
"title": "Tamanho Máximo do Arquivo",
"description": "Tamanho máximo permitido para uploads (em bytes)"
},
"maxTotalStoragePerUser": {
"title": "Armazenamento Máximo por Usuário",
"description": "Limite total de armazenamento por usuário (em bytes)"
}
},
"buttons": {
"save": "Salvar {{group}}"
},
"errors": {
"loadFailed": "Falha ao carregar configurações",
"updateFailed": "Falha ao atualizar configurações"
},
"messages": {
"noChanges": "Nenhuma alteração para salvar",
"updateSuccess": "Configurações de {{group}} atualizadas com sucesso"
},
"title": "Configurações",
"breadcrumb": "Configurações",
"pageTitle": "Configurações"
},
"share": {
"errors": {
"invalidPassword": "Senha inválida. Por favor, tente novamente.",
"loadFailed": "Falha ao carregar compartilhamento",
"downloadFailed": "Falha ao baixar arquivo"
},
"messages": {
"downloadStarted": "Download iniciado",
"password": {
"title": "Compartilhamento Protegido por Senha",
"protected": "Este compartilhamento está protegido por senha",
"incorrect": "Senha incorreta. Por favor, tente novamente.",
"label": "Senha",
"placeholder": "Digite a senha do compartilhamento",
"submit": "Enviar"
},
"details": {
"untitled": "Compartilhamento sem título",
"created": "Criado em: {{date}}",
"expires": "Expira em: {{date}}"
},
"notFound": {
"title": "Compartilhamento não Encontrado",
"description": "Este compartilhamento pode ter sido excluído ou expirado."
}
},
"pageTitle": "Compartilhamento"
},
"shares": {
"errors": {
"loadFailed": "Falha ao carregar compartilhamentos",
"notifyFailed": "Falha ao notificar destinatários",
"smtpConfigFailed": "Falha ao carregar configuração SMTP"
},
"messages": {
"linkCopied": "Link copiado para a área de transferência",
"recipientsNotified": "Destinatários notificados com sucesso"
},
"empty": {
"message": "Nenhum compartilhamento criado ainda",
"createButton": "Criar Compartilhamento"
},
"header": {
"title": "Meus Compartilhamentos",
"myShares": "Meus Compartilhamentos"
},
"search": {
"title": "Todos os Compartilhamentos",
"createButton": "Criar Compartilhamento",
"placeholder": "Buscar compartilhamentos...",
"results": "Encontrados {{filtered}} de {{total}} compartilhamentos"
},
"pageTitle": "Compartilhamentos"
},
"users": {
"modes": {
"create": "criar",
"edit": "editar"
},
"errors": {
"loadFailed": "Falha ao carregar usuários",
"submitFailed": "Falha ao {{mode}} usuário",
"deleteFailed": "Falha ao excluir usuário",
"statusUpdateFailed": "Falha ao atualizar status do usuário"
},
"messages": {
"createSuccess": "Usuário criado com sucesso",
"updateSuccess": "Usuário atualizado com sucesso",
"deleteSuccess": "Usuário excluído com sucesso",
"activateSuccess": "Usuário ativado com sucesso",
"deactivateSuccess": "Usuário desativado com sucesso"
},
"actions": {
"edit": "Editar",
"activate": "Ativar",
"deactivate": "Desativar",
"delete": "Excluir"
},
"delete": {
"title": "Confirmar Exclusão de Usuário",
"confirmation": "Tem certeza que deseja excluir o usuário {{firstName}} {{lastName}}? Esta ação não pode ser desfeita.",
"confirm": "Excluir Usuário"
},
"form": {
"titleCreate": "Adicionar Novo Usuário",
"titleEdit": "Editar Usuário",
"firstName": "Nome",
"lastName": "Sobrenome",
"username": "Nome de Usuário",
"email": "Email",
"password": "Senha",
"newPassword": "Nova Senha (opcional)",
"passwordPlaceholder": "Deixe em branco para manter a senha atual",
"role": "Função",
"roleUser": "Usuário",
"roleAdmin": "Administrador",
"create": "Criar",
"save": "Salvar"
},
"status": {
"title": "Confirmar Alteração de Status",
"confirmation": "Tem certeza que deseja {{action}} o usuário {{firstName}} {{lastName}}?",
"activate": "ativar",
"deactivate": "desativar",
"user": "Usuário"
},
"header": {
"title": "Gerenciamento de Usuários",
"addUser": "Adicionar Usuário",
"management": "Gerenciamento de Usuários"
},
"table": {
"user": "USUÁRIO",
"email": "EMAIL",
"status": "STATUS",
"role": "FUNÇÃO",
"actions": "AÇÕES",
"active": "Ativo",
"inactive": "Inativo",
"admin": "Admin",
"userr": "Usuário"
}
},
"logo": {
"labels": {
"appLogo": "Logo do Aplicativo"
},
"buttons": {
"upload": "Enviar Logo",
"remove": "Remover Logo"
},
"messages": {
"uploadSuccess": "Logo enviado com sucesso",
"removeSuccess": "Logo removido com sucesso"
},
"errors": {
"uploadFailed": "Falha ao enviar logo",
"removeFailed": "Falha ao remover logo"
}
},
"navbar": {
"logoAlt": "Logo do Aplicativo",
"profileMenu": "Menu do Perfil",
"profile": "Perfil",
"settings": "Configurações",
"usersManagement": "Gerenciar Usuários",
"logout": "Sair"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Добро пожаловать в",
"signInToContinue": "Войдите, чтобы продолжить",
"emailLabel": "Адрес электронной почты",
"emailPlaceholder": "Введите вашу электронную почту",
"passwordLabel": "Пароль",
"passwordPlaceholder": "Введите ваш пароль",
"signIn": "Войти",
"signingIn": "Вход...",
"forgotPassword": "Забыли пароль?",
"pageTitle": "Вход"
},
"errors": {
"invalidCredentials": "Неверный адрес электронной почты или пароль",
"userNotFound": "Пользователь не найден",
"accountLocked": "Аккаунт заблокирован. Пожалуйста, попробуйте позже",
"unexpectedError": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз"
},
"validation": {
"invalidEmail": "Неверный адрес электронной почты",
"passwordMinLength": "Пароль должен содержать не менее 6 символов",
"firstNameRequired": "Имя обязательно",
"lastNameRequired": "Фамилия обязательна",
"usernameLength": "Имя пользователя должно содержать не менее 3 символов",
"usernameSpaces": "Имя пользователя не может содержать пробелов",
"passwordLength": "Пароль должен содержать не менее 8 символов",
"passwordsMatch": "Пароли не совпадают",
"emailRequired": "Требуется электронная почта",
"passwordRequired": "Требуется пароль"
},
"fileSelector": {
"availableFiles": "Доступные файлы ({{count}})",
"shareFiles": "Поделиться файлами ({{count}})",
"searchPlaceholder": "Поиск файлов...",
"noMatchingFiles": "Нет файлов, соответствующих запросу",
"noAvailableFiles": "Нет доступных файлов",
"noFilesInShare": "Нет файлов для совместного использования",
"saveChanges": "Сохранить изменения"
},
"recipientSelector": {
"emailPlaceholder": "Введите электронную почту получателя",
"add": "Добавить",
"recipients": "Получатели ({{count}})",
"notifyAll": "Уведомить всех",
"noRecipients": "Пока нет добавленных получателей",
"addSuccess": "Получатель успешно добавлен",
"addError": "Не удалось добавить получателя",
"removeSuccess": "Получатель успешно удалён",
"removeError": "Не удалось удалить получателя",
"sendingNotifications": "Отправка уведомлений...",
"notifySuccess": "Получатели успешно уведомлены",
"notifyError": "Не удалось уведомить получателей"
},
"navigation": {
"dashboard": "Панель управления"
},
"common": {
"loading": "Загрузка, пожалуйста, подождите...",
"cancel": "Отмена",
"save": "Сохранить",
"delete": "Удалить",
"close": "Закрыть",
"download": "Скачать",
"unexpectedError": "Произошла непредвиденная ошибка. Пожалуйста, попробуйте еще раз.",
"yes": "Да",
"no": "Нет",
"dashboard": "Панель управления"
},
"createShare": {
"title": "Создать общий доступ",
"nameLabel": "Название общего доступа",
"expirationLabel": "Дата истечения",
"expirationPlaceholder": "MM/DD/YYYY ЧЧ:ММ",
"maxViewsLabel": "Максимальное количество просмотров",
"maxViewsPlaceholder": "Оставьте пустым для неограниченного доступа",
"passwordProtection": "Защита паролем",
"passwordLabel": "Пароль",
"create": "Создать общий доступ",
"success": "Общий доступ успешно создан",
"error": "Не удалось создать общий доступ"
},
"fileActions": {
"editFile": "Редактировать файл",
"nameLabel": "Имя",
"namePlaceholder": "Введите новое имя",
"extension": "Расширение",
"descriptionLabel": "Описание",
"descriptionPlaceholder": "Введите описание файла",
"deleteFile": "Удалить файл",
"deleteConfirmation": "Вы уверены, что хотите удалить \"{{fileName}}\"?",
"deleteWarning": "Это действие необратимо."
},
"filePreview": {
"loading": "Загрузка предпросмотра...",
"notAvailable": "Предпросмотр недоступен",
"downloadToView": "Скачайте файл для просмотра содержимого",
"audioNotSupported": "Ваш браузер не поддерживает аудиоэлемент",
"videoNotSupported": "Ваш браузер не поддерживает видеоэлемент",
"loadError": "Ошибка загрузки предпросмотра",
"downloadError": "Ошибка скачивания файла"
},
"generateShareLink": {
"generateTitle": "Создать ссылку для общего доступа",
"updateTitle": "Обновить ссылку для общего доступа",
"generateDescription": "Создайте ссылку для обмена файлами",
"updateDescription": "Обновите псевдоним для этой ссылки",
"aliasPlaceholder": "Введите псевдоним",
"linkReady": "Ваша ссылка готова:",
"generateButton": "Создать ссылку",
"updateButton": "Обновить ссылку",
"copyButton": "Скопировать ссылку",
"success": "Ссылка успешно создана",
"error": "Не удалось создать ссылку",
"copied": "Ссылка скопирована в буфер обмена"
},
"shareActions": {
"deleteTitle": "Удалить общий доступ",
"deleteConfirmation": "Вы уверены, что хотите удалить этот общий доступ? Это действие необратимо.",
"editTitle": "Редактировать общий доступ",
"nameLabel": "Название общего доступа",
"expirationLabel": "Дата истечения",
"expirationPlaceholder": "MM/DD/YYYY ЧЧ:ММ",
"maxViewsLabel": "Максимальное количество просмотров",
"maxViewsPlaceholder": "Оставьте пустым для неограниченного доступа",
"passwordProtection": "Защищено паролем",
"passwordLabel": "Пароль",
"passwordPlaceholder": "Введите пароль",
"newPasswordLabel": "Новый пароль (оставьте пустым, чтобы сохранить текущий)",
"newPasswordPlaceholder": "Введите новый пароль",
"manageFilesTitle": "Управление файлами",
"manageRecipientsTitle": "Управление получателями",
"editSuccess": "Общий доступ успешно обновлён",
"editError": "Ошибка при обновлении общего доступа"
},
"shareDetails": {
"title": "Детали общего доступа",
"subtitle": "Подробная информация об этом общем доступе",
"basicInfo": "Основная информация",
"name": "Название",
"untitled": "Без названия",
"views": "Просмотры",
"dates": "Даты",
"created": "Создано",
"expires": "Истекает",
"never": "Никогда",
"security": "Безопасность",
"passwordProtected": "Защищено паролем",
"publicAccess": "Публичный доступ",
"maxViews": "Максимум просмотров: {{count}}",
"files": "Файлы ({{count}})",
"recipients": "Получатели ({{count}})",
"notAvailable": "Н/Д",
"invalidDate": "Неверная дата",
"loadError": "Ошибка загрузки деталей общего доступа"
},
"uploadFile": {
"title": "Загрузить файл",
"selectFile": "Нажмите, чтобы выбрать файл",
"preview": "Предпросмотр",
"uploadProgress": "Прогресс загрузки",
"upload": "Загрузить",
"success": "Файл успешно загружен",
"error": "Не удалось загрузить файл"
},
"filesTable": {
"ariaLabel": "Таблица файлов",
"columns": {
"name": "ИМЯ",
"description": "ОПИСАНИЕ",
"size": "РАЗМЕР",
"createdAt": "СОЗДАНО",
"updatedAt": "ОБНОВЛЕНО",
"actions": "ДЕЙСТВИЯ"
},
"actions": {
"menu": "Меню действий с файлом",
"preview": "Предпросмотр",
"edit": "Редактировать",
"download": "Скачать",
"delete": "Удалить"
}
},
"sharesTable": {
"ariaLabel": "Таблица общего доступа",
"never": "Никогда",
"columns": {
"name": "ИМЯ",
"createdAt": "СОЗДАНО",
"expiresAt": "ИСТЕКАЕТ",
"status": "СТАТУС",
"security": "БЕЗОПАСНОСТЬ",
"files": "ФАЙЛЫ",
"recipients": "ПОЛУЧАТЕЛИ",
"actions": "ДЕЙСТВИЯ"
},
"status": {
"neverExpires": "Не истекает",
"active": "Активно",
"expired": "Истекло"
},
"security": {
"protected": "Защищено",
"public": "Публично"
},
"filesCount": "{{count}} файлов",
"recipientsCount": "{{count}} получателей",
"actions": {
"menu": "Меню действий общего доступа",
"edit": "Редактировать",
"manageFiles": "Управление файлами",
"manageRecipients": "Управление получателями",
"viewDetails": "Просмотреть детали",
"generateLink": "Создать ссылку",
"editLink": "Редактировать ссылку",
"copyLink": "Скопировать ссылку",
"notifyRecipients": "Уведомить получателей",
"delete": "Удалить"
}
},
"footer": {
"poweredBy": "При поддержке",
"kyanHomepage": "Домашняя страница Kyantech"
},
"fileManager": {
"downloadError": "Ошибка скачивания файла",
"updateSuccess": "Файл успешно обновлен",
"updateError": "Ошибка при обновлении файла",
"deleteSuccess": "Файл успешно удален",
"deleteError": "Ошибка при удалении файла"
},
"shareManager": {
"deleteSuccess": "Общий доступ успешно удален",
"deleteError": "Ошибка при удалении общего доступа",
"updateSuccess": "Общий доступ успешно обновлен",
"updateError": "Ошибка при обновлении общего доступа",
"filesUpdateSuccess": "Файлы успешно обновлены",
"filesUpdateError": "Ошибка при обновлении файлов",
"recipientsUpdateSuccess": "Получатели успешно обновлены",
"recipientsUpdateError": "Ошибка при обновлении получателей",
"linkGenerateSuccess": "Ссылка для общего доступа успешно создана",
"linkGenerateError": "Ошибка при создании ссылки для общего доступа",
"notifyLoading": "Отправка уведомлений...",
"notifySuccess": "Получатели успешно уведомлены",
"notifyError": "Ошибка при уведомлении получателей"
},
"quickAccess": {
"files": {
"title": "Мои файлы",
"description": "Доступ и управление загруженными файлами"
},
"shares": {
"title": "Мои общие доступы",
"description": "Просмотр и управление файлами для совместного использования"
}
},
"recentFiles": {
"title": "Последние загрузки",
"viewAll": "Показать все",
"uploadFile": "Загрузить файл",
"noFiles": "Файлы еще не загружены"
},
"recentShares": {
"title": "Последние общие доступы",
"viewAll": "Показать все",
"createShare": "Создать общий доступ",
"noShares": "Общие доступы еще не созданы",
"createFirst": "Создайте ваш первый общий доступ"
},
"storageUsage": {
"title": "Использование хранилища",
"ariaLabel": "Индикатор использования хранилища",
"used": "Использовано: {{size}}",
"available": "Доступно: {{size}}"
},
"dashboard": {
"loadError": "Ошибка загрузки данных панели управления",
"linkCopied": "Ссылка скопирована в буфер обмена",
"pageTitle": "Панель управления",
"breadcrumb": "Панель управления"
},
"emptyState": {
"noFiles": "Файлы еще не загружены",
"uploadFile": "Загрузить файл"
},
"files": {
"title": "Все файлы",
"uploadFile": "Загрузить файл",
"loadError": "Ошибка загрузки файлов",
"pageTitle": "Мои файлы",
"breadcrumb": "Мои файлы"
},
"searchBar": {
"placeholder": "Поиск файлов...",
"results": "Найдено {{filtered}} из {{total}} файлов"
},
"forgotPassword": {
"emailLabel": "Адрес электронной почты",
"emailPlaceholder": "Введите ваш адрес электронной почты",
"sending": "Отправка...",
"submit": "Отправить инструкции по сбросу",
"backToLogin": "Вернуться ко входу",
"title": "Забыли пароль",
"description": "Введите адрес электронной почты, и мы отправим вам инструкции по сбросу пароля.",
"resetInstructions": "Инструкции по сбросу отправлены на вашу электронную почту",
"pageTitle": "Забыли пароль"
},
"home": {
"description": "Открытая альтернатива WeTransfer. Делитесь файлами безопасно, без отслеживания и ограничений.",
"documentation": "Документация",
"starOnGithub": "Оцените на GitHub",
"privacyMessage": "Создано с учетом конфиденциальности. Ваши файлы до загрузки доступны только тем, у кого есть ссылка для доступа. Всегда бесплатно и с открытым исходным кодом.",
"header": {
"fileSharing": "Обмен файлами",
"tagline": "просто и бесплатно"
},
"pageTitle": "Главная"
},
"profile": {
"password": {
"title": "Изменить пароль",
"newPassword": "Новый пароль",
"confirmPassword": "Подтвердите новый пароль",
"updateButton": "Обновить пароль"
},
"form": {
"title": "Информация профиля",
"firstName": "Имя",
"lastName": "Фамилия",
"username": "Имя пользователя",
"email": "Электронная почта",
"updateButton": "Обновить профиль"
},
"header": {
"title": "Профиль",
"subtitle": "Управляйте вашей личной информацией и паролем"
},
"picture": {
"title": "Изображение профиля",
"description": "Нажмите на значок камеры, чтобы изменить изображение профиля",
"uploadPhoto": "Загрузить фото",
"removePhoto": "Удалить фото"
},
"errors": {
"loadFailed": "Не удалось загрузить данные пользователя",
"updateFailed": "Ошибка при обновлении профиля",
"passwordFailed": "Ошибка при обновлении пароля",
"imageFailed": "Ошибка при обновлении изображения профиля",
"imageRemoveFailed": "Ошибка при удалении изображения профиля"
},
"messages": {
"noChanges": "Изменений для сохранения нет",
"updateSuccess": "Профиль успешно обновлен",
"fillPasswords": "Пожалуйста, заполните оба поля пароля",
"passwordSuccess": "Пароль успешно обновлен",
"imageSuccess": "Изображение профиля успешно обновлено",
"imageRemoved": "Изображение профиля успешно удалено"
},
"pageTitle": "Профиль"
},
"resetPassword": {
"pageTitle": "Сбросить пароль",
"header": {
"title": "Сбросить пароль",
"description": "Введите ваш новый пароль ниже"
},
"form": {
"newPassword": "Новый пароль",
"newPasswordPlaceholder": "Введите новый пароль",
"confirmPassword": "Подтвердите новый пароль",
"confirmPasswordPlaceholder": "Подтвердите новый пароль",
"resetting": "Сброс пароля...",
"submit": "Сбросить пароль",
"backToLogin": "Вернуться ко входу"
},
"messages": {
"success": "Пароль успешно сброшен"
},
"errors": {
"serverError": "Не удалось сбросить пароль. Пожалуйста, попробуйте еще раз.",
"invalidToken": "Неверный или отсутствующий токен сброса"
}
},
"settings": {
"groups": {
"defaultDescription": "Настройки конфигурации",
"general": {
"title": "Общие",
"description": "Основные настройки приложения"
},
"email": {
"title": "Электронная почта",
"description": "Настройки почтового сервера"
},
"security": {
"title": "Безопасность",
"description": "Настройки безопасности и аутентификации"
},
"storage": {
"title": "Хранилище",
"description": "Настройки хранения файлов"
}
},
"fields": {
"noDescription": "Описание отсутствует",
"appLogo": {
"title": "Логотип приложения",
"description": "Изображение логотипа приложения"
},
"appName": {
"title": "Название приложения",
"description": "Название приложения, отображаемое пользователям"
},
"appDescription": {
"title": "Описание приложения",
"description": "Краткое описание приложения"
},
"showHomePage": {
"title": "Показывать главную страницу",
"description": "Показывать главную страницу после установки"
},
"smtpEnabled": {
"title": "Включить SMTP",
"description": "Включить или отключить функцию SMTP для отправки электронной почты"
},
"smtpHost": {
"title": "SMTP-сервер",
"description": "Адрес SMTP-сервера"
},
"smtpPort": {
"title": "SMTP-порт",
"description": "Порт SMTP-сервера"
},
"smtpUser": {
"title": "SMTP-пользователь",
"description": "Имя пользователя для SMTP-аутентификации"
},
"smtpPass": {
"title": "SMTP-пароль",
"description": "Пароль для SMTP-аутентификации"
},
"smtpFromName": {
"title": "Имя отправителя",
"description": "Имя, отображаемое в отправляемых письмах"
},
"smtpFromEmail": {
"title": "Электронная почта отправителя",
"description": "Адрес электронной почты отправителя"
},
"maxLoginAttempts": {
"title": "Максимальное количество попыток входа",
"description": "Максимальное количество попыток входа до блокировки"
},
"loginBlockDuration": {
"title": "Время блокировки",
"description": "Продолжительность блокировки (в секундах) после превышения лимита попыток"
},
"passwordMinLength": {
"title": "Минимальная длина пароля",
"description": "Минимальное количество символов в пароле"
},
"passwordResetTokenExpiration": {
"title": "Время истечения токена сброса пароля",
"description": "Время действия токена сброса пароля (в секундах)"
},
"maxFileSize": {
"title": "Максимальный размер файла",
"description": "Максимальный размер файла для загрузки (в байтах)"
},
"maxTotalStoragePerUser": {
"title": "Максимальное хранилище для пользователя",
"description": "Общий лимит хранилища для каждого пользователя (в байтах)"
}
},
"buttons": {
"save": "Сохранить {{group}}"
},
"errors": {
"loadFailed": "Ошибка загрузки настроек",
"updateFailed": "Ошибка обновления настроек"
},
"messages": {
"noChanges": "Изменений для сохранения нет",
"updateSuccess": "Настройки {{group}} успешно обновлены"
},
"title": "Настройки",
"breadcrumb": "Настройки",
"pageTitle": "Настройки"
},
"share": {
"errors": {
"invalidPassword": "Неверный пароль. Пожалуйста, попробуйте еще раз.",
"loadFailed": "Ошибка загрузки общего доступа",
"downloadFailed": "Ошибка скачивания файла"
},
"messages": {
"downloadStarted": "Скачивание начато"
},
"password": {
"title": "Общий доступ, защищенный паролем",
"protected": "Этот общий доступ защищен паролем",
"incorrect": "Неверный пароль. Пожалуйста, попробуйте снова.",
"label": "Пароль",
"placeholder": "Введите пароль для общего доступа",
"submit": "Отправить"
},
"details": {
"untitled": "Без названия",
"created": "Создано: {{date}}",
"expires": "Истекает: {{date}}"
},
"notFound": {
"title": "Общий доступ не найден",
"description": "Этот общий доступ может быть удален или истек."
},
"pageTitle": "Общий доступ"
},
"shares": {
"errors": {
"loadFailed": "Ошибка загрузки общих доступов",
"notifyFailed": "Ошибка уведомления получателей",
"smtpConfigFailed": "Ошибка загрузки SMTP-настроек"
},
"messages": {
"linkCopied": "Ссылка скопирована в буфер обмена",
"recipientsNotified": "Получатели успешно уведомлены"
},
"empty": {
"message": "Общие доступы еще не созданы",
"createButton": "Создать общий доступ"
},
"header": {
"title": "Мои общие доступы",
"myShares": "Мои общие доступы"
},
"search": {
"title": "Все общие доступы",
"createButton": "Создать общий доступ",
"placeholder": "Поиск общих доступов...",
"results": "Найдено {{filtered}} из {{total}} общих доступов"
},
"pageTitle": "Общие доступы"
},
"users": {
"modes": {
"create": "создать",
"edit": "редактировать"
},
"errors": {
"loadFailed": "Ошибка загрузки пользователей",
"submitFailed": "Ошибка при {{mode}} пользователя",
"deleteFailed": "Ошибка при удалении пользователя",
"statusUpdateFailed": "Ошибка обновления статуса пользователя"
},
"messages": {
"createSuccess": "Пользователь успешно создан",
"updateSuccess": "Пользователь успешно обновлен",
"deleteSuccess": "Пользователь успешно удален",
"activateSuccess": "Пользователь успешно активирован",
"deactivateSuccess": "Пользователь успешно деактивирован"
},
"actions": {
"edit": "Редактировать",
"activate": "Активировать",
"deactivate": "Деактивировать",
"delete": "Удалить"
},
"delete": {
"title": "Подтверждение удаления пользователя",
"confirmation": "Вы уверены, что хотите удалить пользователя {{firstName}} {{lastName}}? Это действие нельзя отменить.",
"confirm": "Удалить пользователя"
},
"form": {
"titleCreate": "Добавить нового пользователя",
"titleEdit": "Редактировать пользователя",
"firstName": "Имя",
"lastName": "Фамилия",
"username": "Имя пользователя",
"email": "Электронная почта",
"password": "Пароль",
"newPassword": "Новый пароль (необязательно)",
"passwordPlaceholder": "Оставьте пустым, чтобы сохранить текущий пароль",
"role": "Роль",
"roleUser": "Пользователь",
"roleAdmin": "Администратор",
"create": "Создать",
"save": "Сохранить"
},
"status": {
"title": "Подтверждение изменения статуса",
"confirmation": "Вы уверены, что хотите {{action}} пользователя {{firstName}} {{lastName}}?",
"activate": "активировать",
"deactivate": "деактивировать",
"user": "Пользователь"
},
"header": {
"title": "Управление пользователями",
"addUser": "Добавить пользователя",
"management": "Управление пользователями"
},
"table": {
"user": "ПОЛЬЗОВАТЕЛЬ",
"email": "ЭЛЕКТРОННАЯ ПОЧТА",
"status": "СТАТУС",
"role": "РОЛЬ",
"actions": "ДЕЙСТВИЯ",
"active": "Активен",
"inactive": "Неактивен",
"admin": "Администратор",
"userr": "Пользователь"
}
},
"logo": {
"labels": {
"appLogo": "Логотип приложения"
},
"buttons": {
"upload": "Загрузить логотип",
"remove": "Удалить логотип"
},
"messages": {
"uploadSuccess": "Логотип успешно загружен",
"removeSuccess": "Логотип успешно удален"
},
"errors": {
"uploadFailed": "Ошибка загрузки логотипа",
"removeFailed": "Ошибка удаления логотипа"
}
},
"navbar": {
"logoAlt": "Логотип приложения",
"profileMenu": "Меню профиля",
"profile": "Профиль",
"settings": "Настройки",
"usersManagement": "Управление пользователями",
"logout": "Выйти"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "Hoş geldiniz'e",
"signInToContinue": "Devam etmek için oturum açın",
"emailLabel": "E-posta Adresi",
"emailPlaceholder": "E-posta adresinizi girin",
"passwordLabel": "Şifre",
"passwordPlaceholder": "Şifrenizi girin",
"signIn": "Oturum Aç",
"signingIn": "Oturum açılıyor...",
"forgotPassword": "Şifrenizi mi unuttunuz?",
"pageTitle": "Giriş"
},
"errors": {
"invalidCredentials": "Geçersiz e-posta veya şifre",
"userNotFound": "Kullanıcı bulunamadı",
"accountLocked": "Hesap kilitlendi. Lütfen daha sonra tekrar deneyin",
"unexpectedError": "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin"
},
"validation": {
"invalidEmail": "Geçersiz e-posta adresi",
"passwordMinLength": "Şifre en az 6 karakter olmalıdır",
"firstNameRequired": "Ad gerekli",
"lastNameRequired": "Soyad gerekli",
"usernameLength": "Kullanıcı adı en az 3 karakter olmalıdır",
"usernameSpaces": "Kullanıcı adında boşluk olamaz",
"passwordLength": "Şifre en az 8 karakter olmalıdır",
"passwordsMatch": "Şifreler eşleşmiyor",
"emailRequired": "E-posta gerekli",
"passwordRequired": "Şifre gerekli"
},
"fileSelector": {
"availableFiles": "Kullanılabilir Dosyalar ({{count}})",
"shareFiles": "Dosyaları Paylaş ({{count}})",
"searchPlaceholder": "Dosya ara...",
"noMatchingFiles": "Eşleşen dosya bulunamadı",
"noAvailableFiles": "Kullanılabilir dosya yok",
"noFilesInShare": "Paylaşımda dosya yok",
"saveChanges": "Değişiklikleri Kaydet"
},
"recipientSelector": {
"emailPlaceholder": "Alıcının e-postasını girin",
"add": "Ekle",
"recipients": "Alıcılar ({{count}})",
"notifyAll": "Hepsini Bildir",
"noRecipients": "Henüz alıcı eklenmedi",
"addSuccess": "Alıcı başarıyla eklendi",
"addError": "Alıcı eklenemedi",
"removeSuccess": "Alıcı başarıyla kaldırıldı",
"removeError": "Alıcı kaldırılamadı",
"sendingNotifications": "Bildirimler gönderiliyor...",
"notifySuccess": "Alıcılar başarıyla bildirildi",
"notifyError": "Alıcılara bildirim gönderilemedi"
},
"navigation": {
"dashboard": "Gösterge Paneli"
},
"common": {
"loading": "Yükleniyor, lütfen bekleyin...",
"cancel": "İptal",
"save": "Kaydet",
"delete": "Sil",
"close": "Kapat",
"download": "İndir",
"unexpectedError": "Beklenmeyen bir hata oluştu. Lütfen tekrar deneyin.",
"yes": "Evet",
"no": "Hayır",
"dashboard": "Gösterge Paneli"
},
"createShare": {
"title": "Paylaşım Oluştur",
"nameLabel": "Paylaşım Adı",
"expirationLabel": "Son Kullanma Tarihi",
"expirationPlaceholder": "MM/GG/YYYY SS:DD",
"maxViewsLabel": "Maksimum Görüntüleme",
"maxViewsPlaceholder": "Sınırsız için boş bırakın",
"passwordProtection": "Şifre Koruması",
"passwordLabel": "Şifre",
"create": "Paylaşım Oluştur",
"success": "Paylaşım başarıyla oluşturuldu",
"error": "Paylaşım oluşturulamadı"
},
"fileActions": {
"editFile": "Dosyayı Düzenle",
"nameLabel": "Ad",
"namePlaceholder": "Yeni ad girin",
"extension": "Uzantı",
"descriptionLabel": "Açıklama",
"descriptionPlaceholder": "Dosya açıklamasını girin",
"deleteFile": "Dosyayı Sil",
"deleteConfirmation": "\"{{fileName}}\" dosyasını silmek istediğinize emin misiniz?",
"deleteWarning": "Bu işlem geri alınamaz."
},
"filePreview": {
"loading": "Önizleme yükleniyor...",
"notAvailable": "Önizleme mevcut değil",
"downloadToView": "İçeriği görüntülemek için dosyayı indirin",
"audioNotSupported": "Tarayıcınız ses öğesini desteklemiyor",
"videoNotSupported": "Tarayıcınız video öğesini desteklemiyor",
"loadError": "Önizleme yüklenemedi",
"downloadError": "Dosya indirilemedi"
},
"generateShareLink": {
"generateTitle": "Paylaşım Bağlantısı Oluştur",
"updateTitle": "Paylaşım Bağlantısını Güncelle",
"generateDescription": "Dosyalarınızı paylaşmak için bir bağlantı oluşturun",
"updateDescription": "Bu paylaşım bağlantısı için takma ad güncelleyin",
"aliasPlaceholder": "Takma ad girin",
"linkReady": "Paylaşım bağlantınız hazır:",
"generateButton": "Bağlantıyı Oluştur",
"updateButton": "Bağlantıyı Güncelle",
"copyButton": "Bağlantıyı Kopyala",
"success": "Bağlantı başarıyla oluşturuldu",
"error": "Bağlantı oluşturulamadı",
"copied": "Bağlantı panoya kopyalandı"
},
"shareActions": {
"deleteTitle": "Paylaşımı Sil",
"deleteConfirmation": "Bu paylaşımı silmek istediğinize emin misiniz? Bu işlem geri alınamaz.",
"editTitle": "Paylaşımı Düzenle",
"nameLabel": "Paylaşım Adı",
"expirationLabel": "Son Kullanma Tarihi",
"expirationPlaceholder": "MM/GG/YYYY SS:DD",
"maxViewsLabel": "Maksimum Görüntüleme",
"maxViewsPlaceholder": "Sınırsız için boş bırakın",
"passwordProtection": "Şifre Korumalı",
"passwordLabel": "Şifre",
"passwordPlaceholder": "Şifreyi girin",
"newPasswordLabel": "Yeni Şifre (mevcut şifreyi korumak için boş bırakın)",
"newPasswordPlaceholder": "Yeni şifreyi girin",
"manageFilesTitle": "Dosyaları Yönet",
"manageRecipientsTitle": "Alıcıları Yönet",
"editSuccess": "Paylaşım başarıyla güncellendi",
"editError": "Paylaşım güncellenemedi"
},
"shareDetails": {
"title": "Paylaşım Detayları",
"subtitle": "Bu paylaşım hakkında ayrıntılı bilgi",
"basicInfo": "Temel Bilgiler",
"name": "Ad",
"untitled": "Adsız",
"views": "Görüntüleme",
"dates": "Tarihler",
"created": "Oluşturuldu",
"expires": "Sona Eriyor",
"never": "Asla",
"security": "Güvenlik",
"passwordProtected": "Şifre ile Korunuyor",
"publicAccess": "Genel Erişim",
"maxViews": "Maksimum Görüntüleme: {{count}}",
"files": "Dosyalar ({{count}})",
"recipients": "Alıcılar ({{count}})",
"notAvailable": "Mevcut Değil",
"invalidDate": "Geçersiz tarih",
"loadError": "Paylaşım detayları yüklenemedi"
},
"uploadFile": {
"title": "Dosya Yükle",
"selectFile": "Dosya seçmek için tıklayın",
"preview": "Önizleme",
"uploadProgress": "Yükleme İlerlemesi",
"upload": "Yükle",
"success": "Dosya başarıyla yüklendi",
"error": "Dosya yüklenemedi"
},
"filesTable": {
"ariaLabel": "Dosya Tablosu",
"columns": {
"name": "Ad",
"description": "Açıklama",
"size": "Boyut",
"createdAt": "Oluşturulma Tarihi",
"updatedAt": "Güncellenme Tarihi",
"actions": "İşlemler"
},
"actions": {
"menu": "Dosya İşlem Menüsü",
"preview": "Önizleme",
"edit": "Düzenle",
"download": "İndir",
"delete": "Sil"
}
},
"sharesTable": {
"ariaLabel": "Paylaşım Tablosu",
"never": "Asla",
"columns": {
"name": "Ad",
"createdAt": "Oluşturulma Tarihi",
"expiresAt": "Son Kullanma Tarihi",
"status": "Durum",
"security": "Güvenlik",
"files": "Dosyalar",
"recipients": "Alıcılar",
"actions": "İşlemler"
},
"status": {
"neverExpires": "Sona Ermez",
"active": "Aktif",
"expired": "Sona Erdi"
},
"security": {
"protected": "Korunuyor",
"public": "Genel"
},
"filesCount": "{{count}} dosya",
"recipientsCount": "{{count}} alıcı",
"actions": {
"menu": "Paylaşım İşlem Menüsü",
"edit": "Düzenle",
"manageFiles": "Dosyaları Yönet",
"manageRecipients": "Alıcıları Yönet",
"viewDetails": "Detayları Görüntüle",
"generateLink": "Bağlantı Oluştur",
"editLink": "Bağlantıyı Düzenle",
"copyLink": "Bağlantıyı Kopyala",
"notifyRecipients": "Alıcıları Bildir",
"delete": "Sil"
}
},
"footer": {
"poweredBy": "Tarafından destekleniyor:",
"kyanHomepage": "Kyantech Ana Sayfası"
},
"fileManager": {
"downloadError": "Dosya indirilemedi",
"updateSuccess": "Dosya başarıyla güncellendi",
"updateError": "Dosya güncellenemedi",
"deleteSuccess": "Dosya başarıyla silindi",
"deleteError": "Dosya silinemedi"
},
"shareManager": {
"deleteSuccess": "Paylaşım başarıyla silindi",
"deleteError": "Paylaşım silinemedi",
"updateSuccess": "Paylaşım başarıyla güncellendi",
"updateError": "Paylaşım güncellenemedi",
"filesUpdateSuccess": "Dosyalar başarıyla güncellendi",
"filesUpdateError": "Dosyalar güncellenemedi",
"recipientsUpdateSuccess": "Alıcılar başarıyla güncellendi",
"recipientsUpdateError": "Alıcılar güncellenemedi",
"linkGenerateSuccess": "Paylaşım bağlantısı başarıyla oluşturuldu",
"linkGenerateError": "Paylaşım bağlantısı oluşturulamadı",
"notifyLoading": "Bildirimler gönderiliyor...",
"notifySuccess": "Alıcılara başarıyla bildirildi",
"notifyError": "Alıcılara bildirim gönderilemedi"
},
"quickAccess": {
"files": {
"title": "Benim Dosyalarım",
"description": "Yüklenen dosyalara erişin ve yönetin"
},
"shares": {
"title": "Benim Paylaşımlarım",
"description": "Paylaşılan dosyaları görüntüleyin ve yönetin"
}
},
"recentFiles": {
"title": "Son Yüklemeler",
"viewAll": "Tümünü Görüntüle",
"uploadFile": "Dosya Yükle",
"noFiles": "Henüz dosya yüklenmedi"
},
"recentShares": {
"title": "Son Paylaşımlar",
"viewAll": "Tümünü Görüntüle",
"createShare": "Paylaşım Oluştur",
"noShares": "Henüz paylaşım oluşturulmadı",
"createFirst": "İlk paylaşımınızı oluşturun"
},
"storageUsage": {
"title": "Depolama Kullanımı",
"ariaLabel": "Depolama kullanım ilerleme çubuğu",
"used": "{{size}} kullanıldı",
"available": "{{size}} kullanılabilir"
},
"dashboard": {
"loadError": "Gösterge paneli verileri yüklenemedi",
"linkCopied": "Bağlantı panoya kopyalandı",
"pageTitle": "Gösterge Paneli",
"breadcrumb": "Gösterge Paneli"
},
"emptyState": {
"noFiles": "Henüz dosya yüklenmedi",
"uploadFile": "Dosya Yükle"
},
"files": {
"title": "Tüm Dosyalar",
"uploadFile": "Dosya Yükle",
"loadError": "Dosyalar yüklenemedi",
"pageTitle": "Benim Dosyalarım",
"breadcrumb": "Benim Dosyalarım"
},
"searchBar": {
"placeholder": "Dosya ara...",
"results": "Toplam {{total}} dosya içinde {{filtered}} dosya bulundu"
},
"forgotPassword": {
"emailLabel": "E-posta Adresi",
"emailPlaceholder": "E-posta adresinizi girin",
"sending": "Gönderiliyor...",
"submit": "Şifre Sıfırlama Talimatlarını Gönder",
"backToLogin": "Girişe Geri Dön",
"title": "Şifrenizi mi Unuttunuz?",
"description": "E-posta adresinizi girin, şifre sıfırlama talimatlarını göndereceğiz.",
"resetInstructions": "Şifre sıfırlama talimatları e-posta adresinize gönderildi",
"pageTitle": "Şifrenizi mi Unuttunuz?"
},
"home": {
"description": "WeTransfer'e açık kaynaklı alternatif. Takip veya kısıtlama olmadan dosyalarınızı güvenle paylaşın.",
"documentation": "Belgelendirme",
"starOnGithub": "GitHub'da Yıldız Verin",
"privacyMessage": "Gizlilik göz önünde bulundurularak tasarlanmıştır. Yüklemeden önceki dosyalar, yalnızca paylaşım bağlantısına sahip olanlar tarafından erişilebilir. Her zaman ücretsiz ve açık kaynaktır.",
"header": {
"fileSharing": "Dosya Paylaşımı",
"tagline": "Basit ve Ücretsiz"
},
"pageTitle": "Ana Sayfa"
},
"profile": {
"password": {
"title": "Şifreyi Değiştir",
"newPassword": "Yeni Şifre",
"confirmPassword": "Yeni Şifreyi Onayla",
"updateButton": "Şifreyi Güncelle"
},
"form": {
"title": "Profil Bilgileri",
"firstName": "Ad",
"lastName": "Soyad",
"username": "Kullanıcı Adı",
"email": "E-posta",
"updateButton": "Profili Güncelle"
},
"header": {
"title": "Profil",
"subtitle": "Kişisel bilgilerinizi ve şifrenizi yönetin"
},
"picture": {
"title": "Profil Resmi",
"description": "Profil resmini değiştirmek için kamera simgesine tıklayın",
"uploadPhoto": "Fotoğraf Yükle",
"removePhoto": "Fotoğrafı Kaldır"
},
"errors": {
"loadFailed": "Kullanıcı verileri yüklenemedi",
"updateFailed": "Profil güncellenemedi",
"passwordFailed": "Şifre güncellenemedi",
"imageFailed": "Profil resmi güncellenemedi",
"imageRemoveFailed": "Profil resmi kaldırılamadı"
},
"messages": {
"noChanges": "Kaydedilecek değişiklik yok",
"updateSuccess": "Profil başarıyla güncellendi",
"fillPasswords": "Lütfen her iki şifre alanını da doldurun",
"passwordSuccess": "Şifre başarıyla güncellendi",
"imageSuccess": "Profil resmi başarıyla güncellendi",
"imageRemoved": "Profil resmi başarıyla kaldırıldı"
},
"pageTitle": "Profil"
},
"resetPassword": {
"pageTitle": "Şifreyi Sıfırla",
"header": {
"title": "Şifreyi Sıfırla",
"description": "Aşağıya yeni şifrenizi girin"
},
"form": {
"newPassword": "Yeni Şifre",
"newPasswordPlaceholder": "Yeni şifrenizi girin",
"confirmPassword": "Yeni Şifreyi Onayla",
"confirmPasswordPlaceholder": "Yeni şifrenizi tekrar girin",
"resetting": "Şifre sıfırlanıyor...",
"submit": "Şifreyi Sıfırla",
"backToLogin": "Girişe Geri Dön"
},
"messages": {
"success": "Şifre başarıyla sıfırlandı"
},
"errors": {
"serverError": "Şifre sıfırlama başarısız. Lütfen tekrar deneyin.",
"invalidToken": "Geçersiz veya eksik sıfırlama belirteci"
}
},
"settings": {
"groups": {
"defaultDescription": "Yapılandırma seçenekleri",
"general": {
"title": "Genel",
"description": "Uygulamanın temel ayarları"
},
"email": {
"title": "E-posta",
"description": "E-posta sunucusu yapılandırması"
},
"security": {
"title": "Güvenlik",
"description": "Güvenlik ve kimlik doğrulama ayarları"
},
"storage": {
"title": "Depolama",
"description": "Dosya depolama yapılandırması"
}
},
"fields": {
"noDescription": "Açıklama mevcut değil",
"appLogo": {
"title": "Uygulama Logosu",
"description": "Uygulama logosu resmi"
},
"appName": {
"title": "Uygulama Adı",
"description": "Kullanıcılara gösterilen uygulama adı"
},
"appDescription": {
"title": "Uygulama Açıklaması",
"description": "Uygulama hakkında kısa açıklama"
},
"showHomePage": {
"title": "Ana Sayfayı Göster",
"description": "Kurulumdan sonra ana sayfayı göster"
},
"smtpEnabled": {
"title": "SMTP Etkin",
"description": "SMTP e-posta işlevini etkinleştir veya devre dışı bırak"
},
"smtpHost": {
"title": "SMTP Sunucusu",
"description": "SMTP sunucusunun adresi"
},
"smtpPort": {
"title": "SMTP Portu",
"description": "SMTP sunucu portu"
},
"smtpUser": {
"title": "SMTP Kullanıcısı",
"description": "SMTP kimlik doğrulaması için kullanıcı adı"
},
"smtpPass": {
"title": "SMTP Şifresi",
"description": "SMTP kimlik doğrulaması için şifre"
},
"smtpFromName": {
"title": "Gönderen Adı",
"description": "Gönderilen e-postalarda görüntülenecek isim"
},
"smtpFromEmail": {
"title": "Gönderen E-postası",
"description": "Gönderenin e-posta adresi"
},
"maxLoginAttempts": {
"title": "Maksimum Giriş Denemesi",
"description": "Engelleme öncesi maksimum giriş denemesi sayısı"
},
"loginBlockDuration": {
"title": "Giriş Engelleme Süresi",
"description": "Deneme sayısııldıktan sonra engelleme süresi (saniye cinsinden)"
},
"passwordMinLength": {
"title": "Minimum Şifre Uzunluğu",
"description": "Şifre için gereken minimum karakter sayısı"
},
"passwordResetTokenExpiration": {
"title": "Şifre Sıfırlama Belirtecinin Süresi",
"description": "Şifre sıfırlama belirtecinin geçerlilik süresi (saniye cinsinden)"
},
"maxFileSize": {
"title": "Maksimum Dosya Boyutu",
"description": "Yüklemeye izin verilen maksimum dosya boyutu (bayt cinsinden)"
},
"maxTotalStoragePerUser": {
"title": "Kullanıcı Başına Maksimum Depolama",
"description": "Kullanıcı başına toplam depolama sınırı (bayt cinsinden)"
}
},
"buttons": {
"save": "{{group}} Kaydet"
},
"errors": {
"loadFailed": "Ayarlar yüklenemedi",
"updateFailed": "Ayarlar güncellenemedi"
},
"messages": {
"noChanges": "Kaydedilecek değişiklik yok",
"updateSuccess": "{{group}} ayarları başarıyla güncellendi"
},
"title": "Ayarlar",
"breadcrumb": "Ayarlar",
"pageTitle": "Ayarlar"
},
"share": {
"errors": {
"invalidPassword": "Geçersiz şifre. Lütfen tekrar deneyin.",
"loadFailed": "Paylaşım yüklenemedi",
"downloadFailed": "Dosya indirilemedi"
},
"messages": {
"downloadStarted": "İndirme başladı"
},
"password": {
"title": "Şifre Korumalı Paylaşım",
"protected": "Bu paylaşım şifre ile korunuyor",
"incorrect": "Şifre yanlış. Lütfen tekrar deneyin.",
"label": "Şifre",
"placeholder": "Paylaşım şifresini girin",
"submit": "Gönder"
},
"details": {
"untitled": "Adsız",
"created": "Oluşturulma: {{date}}",
"expires": "Son Kullanma: {{date}}"
},
"notFound": {
"title": "Paylaşım Bulunamadı",
"description": "Bu paylaşım silinmiş veya süresi dolmuş olabilir."
},
"pageTitle": "Paylaşım"
},
"shares": {
"errors": {
"loadFailed": "Paylaşımlar yüklenemedi",
"notifyFailed": "Alıcılara bildirim gönderilemedi",
"smtpConfigFailed": "SMTP ayarları yüklenemedi"
},
"messages": {
"linkCopied": "Bağlantı panoya kopyalandı",
"recipientsNotified": "Alıcılar başarıyla bildirildi"
},
"empty": {
"message": "Henüz paylaşım oluşturulmadı",
"createButton": "Paylaşım Oluştur"
},
"header": {
"title": "Benim Paylaşımlarım",
"myShares": "Benim Paylaşımlarım"
},
"search": {
"title": "Tüm Paylaşımlar",
"createButton": "Paylaşım Oluştur",
"placeholder": "Paylaşım ara...",
"results": "Toplam {{total}} paylaşım arasında {{filtered}} paylaşım bulundu"
},
"pageTitle": "Paylaşımlar"
},
"users": {
"modes": {
"create": "Oluştur",
"edit": "Düzenle"
},
"errors": {
"loadFailed": "Kullanıcılar yüklenemedi",
"submitFailed": "Kullanıcı {{mode}} edilemedi",
"deleteFailed": "Kullanıcı silinemedi",
"statusUpdateFailed": "Kullanıcı durumu güncellenemedi"
},
"messages": {
"createSuccess": "Kullanıcı başarıyla oluşturuldu",
"updateSuccess": "Kullanıcı başarıyla güncellendi",
"deleteSuccess": "Kullanıcı başarıyla silindi",
"activateSuccess": "Kullanıcı başarıyla etkinleştirildi",
"deactivateSuccess": "Kullanıcı başarıyla devre dışı bırakıldı"
},
"actions": {
"edit": "Düzenle",
"activate": "Etkinleştir",
"deactivate": "Devre Dışı Bırak",
"delete": "Sil"
},
"delete": {
"title": "Kullanıcı Silmeyi Onayla",
"confirmation": "{{firstName}} {{lastName}} adlı kullanıcıyı silmek istediğinize emin misiniz? Bu işlem geri alınamaz.",
"confirm": "Kullanıcıyı Sil"
},
"form": {
"titleCreate": "Yeni Kullanıcı Ekle",
"titleEdit": "Kullanıcıyı Düzenle",
"firstName": "Ad",
"lastName": "Soyad",
"username": "Kullanıcı Adı",
"email": "E-posta",
"password": "Şifre",
"newPassword": "Yeni Şifre (Opsiyonel)",
"passwordPlaceholder": "Mevcut şifreyi korumak için boş bırakın",
"role": "Rol",
"roleUser": "Kullanıcı",
"roleAdmin": "Yönetici",
"create": "Oluştur",
"save": "Kaydet"
},
"status": {
"title": "Durum Değişikliğini Onayla",
"confirmation": "{{firstName}} {{lastName}} adlı kullanıcıyı {{action}} etmek istediğinize emin misiniz?",
"activate": "Etkinleştir",
"deactivate": "Devre Dışı Bırak",
"user": "Kullanıcı"
},
"header": {
"title": "Kullanıcı Yönetimi",
"addUser": "Kullanıcı Ekle",
"management": "Kullanıcı Yönetimi"
},
"table": {
"user": "Kullanıcı",
"email": "E-posta",
"status": "Durum",
"role": "Rol",
"actions": "İşlemler",
"active": "Etkin",
"inactive": "Devre Dışı",
"admin": "Yönetici",
"userr": "Kullanıcı"
}
},
"logo": {
"labels": {
"appLogo": "Uygulama Logosu"
},
"buttons": {
"upload": "Logoyu Yükle",
"remove": "Logoyu Kaldır"
},
"messages": {
"uploadSuccess": "Logo başarıyla yüklendi",
"removeSuccess": "Logo başarıyla kaldırıldı"
},
"errors": {
"uploadFailed": "Logo yüklenemedi",
"removeFailed": "Logo kaldırılamadı"
}
},
"navbar": {
"logoAlt": "Uygulama Logosu",
"profileMenu": "Profil Menüsü",
"profile": "Profil",
"settings": "Ayarlar",
"usersManagement": "Kullanıcı Yönetimi",
"logout": "Oturumu Kapat"
}
}

View File

@@ -0,0 +1,638 @@
{
"login": {
"welcome": "欢迎您",
"signInToContinue": "请登录以继续",
"emailLabel": "电子邮件地址",
"emailPlaceholder": "请输入您的电子邮件",
"passwordLabel": "密码",
"passwordPlaceholder": "请输入您的密码",
"signIn": "登录",
"signingIn": "正在登录...",
"forgotPassword": "忘记密码?",
"pageTitle": "登录"
},
"errors": {
"invalidCredentials": "电子邮件或密码错误",
"userNotFound": "未找到用户",
"accountLocked": "账户已锁定。请稍后再试",
"unexpectedError": "发生意外错误。请重试"
},
"validation": {
"invalidEmail": "无效的电子邮件地址",
"passwordMinLength": "密码至少需要6个字符",
"firstNameRequired": "名字为必填项",
"lastNameRequired": "姓氏为必填项",
"usernameLength": "用户名至少需要3个字符",
"usernameSpaces": "用户名不能包含空格",
"passwordLength": "密码至少需要8个字符",
"passwordsMatch": "密码不匹配",
"emailRequired": "电子邮件为必填项",
"passwordRequired": "密码为必填项"
},
"fileSelector": {
"availableFiles": "可用文件 ({{count}})",
"shareFiles": "共享文件 ({{count}})",
"searchPlaceholder": "搜索文件...",
"noMatchingFiles": "没有匹配的文件",
"noAvailableFiles": "没有可用的文件",
"noFilesInShare": "共享中没有文件",
"saveChanges": "保存更改"
},
"recipientSelector": {
"emailPlaceholder": "请输入收件人电子邮件",
"add": "添加",
"recipients": "收件人 ({{count}})",
"notifyAll": "通知所有人",
"noRecipients": "还没有添加收件人",
"addSuccess": "收件人添加成功",
"addError": "添加收件人失败",
"removeSuccess": "收件人删除成功",
"removeError": "删除收件人失败",
"sendingNotifications": "正在发送通知...",
"notifySuccess": "收件人通知成功",
"notifyError": "通知收件人失败"
},
"navigation": {
"dashboard": "仪表盘"
},
"common": {
"loading": "加载中,请稍候...",
"cancel": "取消",
"save": "保存",
"delete": "删除",
"close": "关闭",
"download": "下载",
"unexpectedError": "发生意外错误。请重试。",
"yes": "是",
"no": "否",
"dashboard": "仪表盘"
},
"createShare": {
"title": "创建共享",
"nameLabel": "共享名称",
"expirationLabel": "过期日期",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "最大查看次数",
"maxViewsPlaceholder": "留空表示无限",
"passwordProtection": "密码保护",
"passwordLabel": "密码",
"create": "创建共享",
"success": "共享创建成功",
"error": "创建共享失败"
},
"fileActions": {
"editFile": "编辑文件",
"nameLabel": "名称",
"namePlaceholder": "请输入新名称",
"extension": "扩展名",
"descriptionLabel": "描述",
"descriptionPlaceholder": "请输入文件描述",
"deleteFile": "删除文件",
"deleteConfirmation": "您确定要删除“{{fileName}}”吗?",
"deleteWarning": "此操作不可撤销。"
},
"filePreview": {
"loading": "正在加载预览...",
"notAvailable": "预览不可用",
"downloadToView": "下载文件以查看内容",
"audioNotSupported": "您的浏览器不支持音频元素",
"videoNotSupported": "您的浏览器不支持视频元素",
"loadError": "加载预览失败",
"downloadError": "下载文件失败"
},
"generateShareLink": {
"generateTitle": "生成共享链接",
"updateTitle": "更新共享链接",
"generateDescription": "生成用于共享文件的链接",
"updateDescription": "更新此共享链接的别名",
"aliasPlaceholder": "请输入别名",
"linkReady": "您的共享链接已准备好:",
"generateButton": "生成链接",
"updateButton": "更新链接",
"copyButton": "复制链接",
"success": "链接生成成功",
"error": "生成链接失败",
"copied": "链接已复制到剪贴板"
},
"shareActions": {
"deleteTitle": "删除共享",
"deleteConfirmation": "您确定要删除此共享吗?此操作不可撤销。",
"editTitle": "编辑共享",
"nameLabel": "共享名称",
"expirationLabel": "过期日期",
"expirationPlaceholder": "MM/DD/YYYY HH:MM",
"maxViewsLabel": "最大查看次数",
"maxViewsPlaceholder": "留空表示无限",
"passwordProtection": "密码保护",
"passwordLabel": "密码",
"passwordPlaceholder": "请输入密码",
"newPasswordLabel": "新密码(留空表示保持当前密码)",
"newPasswordPlaceholder": "请输入新密码",
"manageFilesTitle": "管理文件",
"manageRecipientsTitle": "管理收件人",
"editSuccess": "共享更新成功",
"editError": "更新共享失败"
},
"shareDetails": {
"title": "共享详情",
"subtitle": "关于此共享的详细信息",
"basicInfo": "基本信息",
"name": "名称",
"untitled": "未命名",
"views": "查看次数",
"dates": "日期",
"created": "创建于",
"expires": "过期于",
"never": "从不",
"security": "安全性",
"passwordProtected": "受密码保护",
"publicAccess": "公开访问",
"maxViews": "最大查看次数:{{count}}",
"files": "文件 ({{count}})",
"recipients": "收件人 ({{count}})",
"notAvailable": "不适用",
"invalidDate": "无效的日期",
"loadError": "加载共享详情失败"
},
"uploadFile": {
"title": "上传文件",
"selectFile": "点击选择文件",
"preview": "预览",
"uploadProgress": "上传进度",
"upload": "上传",
"success": "文件上传成功",
"error": "文件上传失败"
},
"filesTable": {
"ariaLabel": "文件表格",
"columns": {
"name": "名称",
"description": "描述",
"size": "大小",
"createdAt": "创建时间",
"updatedAt": "更新时间",
"actions": "操作"
},
"actions": {
"menu": "文件操作菜单",
"preview": "预览",
"edit": "编辑",
"download": "下载",
"delete": "删除"
}
},
"sharesTable": {
"ariaLabel": "共享表格",
"never": "从不",
"columns": {
"name": "名称",
"createdAt": "创建时间",
"expiresAt": "过期时间",
"status": "状态",
"security": "安全性",
"files": "文件",
"recipients": "收件人",
"actions": "操作"
},
"status": {
"neverExpires": "永不过期",
"active": "活跃",
"expired": "已过期"
},
"security": {
"protected": "受保护",
"public": "公开"
},
"filesCount": "{{count}} 个文件",
"recipientsCount": "{{count}} 个收件人",
"actions": {
"menu": "共享操作菜单",
"edit": "编辑",
"manageFiles": "管理文件",
"manageRecipients": "管理收件人",
"viewDetails": "查看详情",
"generateLink": "生成链接",
"editLink": "编辑链接",
"copyLink": "复制链接",
"notifyRecipients": "通知收件人",
"delete": "删除"
}
},
"footer": {
"poweredBy": "技术支持:",
"kyanHomepage": "Kyantech 主页"
},
"fileManager": {
"downloadError": "文件下载失败",
"updateSuccess": "文件更新成功",
"updateError": "文件更新失败",
"deleteSuccess": "文件删除成功",
"deleteError": "文件删除失败"
},
"shareManager": {
"deleteSuccess": "共享删除成功",
"deleteError": "共享删除失败",
"updateSuccess": "共享更新成功",
"updateError": "共享更新失败",
"filesUpdateSuccess": "文件更新成功",
"filesUpdateError": "文件更新失败",
"recipientsUpdateSuccess": "收件人更新成功",
"recipientsUpdateError": "收件人更新失败",
"linkGenerateSuccess": "共享链接生成成功",
"linkGenerateError": "共享链接生成失败",
"notifyLoading": "正在发送通知...",
"notifySuccess": "通知收件人成功",
"notifyError": "通知收件人失败"
},
"quickAccess": {
"files": {
"title": "我的文件",
"description": "访问和管理您上传的文件"
},
"shares": {
"title": "我的共享",
"description": "查看和管理您共享的文件"
}
},
"recentFiles": {
"title": "最近上传",
"viewAll": "查看全部",
"uploadFile": "上传文件",
"noFiles": "尚未上传文件"
},
"recentShares": {
"title": "最近共享",
"viewAll": "查看全部",
"createShare": "创建共享",
"noShares": "尚未创建共享",
"createFirst": "请创建您的第一个共享"
},
"storageUsage": {
"title": "存储使用情况",
"ariaLabel": "存储使用进度条",
"used": "已使用:{{size}}",
"available": "可用:{{size}}"
},
"dashboard": {
"loadError": "加载仪表盘数据失败",
"linkCopied": "链接已复制到剪贴板",
"pageTitle": "仪表盘",
"breadcrumb": "仪表盘"
},
"emptyState": {
"noFiles": "尚未上传任何文件",
"uploadFile": "上传文件"
},
"files": {
"title": "所有文件",
"uploadFile": "上传文件",
"loadError": "加载文件失败",
"pageTitle": "我的文件",
"breadcrumb": "我的文件"
},
"searchBar": {
"placeholder": "搜索文件...",
"results": "共{{total}}个文件,找到{{filtered}}个"
},
"forgotPassword": {
"emailLabel": "电子邮件地址",
"emailPlaceholder": "请输入您的电子邮件",
"sending": "正在发送...",
"submit": "发送密码重置指令",
"backToLogin": "返回登录",
"title": "忘记密码?",
"description": "请输入您的电子邮件,我们将发送密码重置指令给您。",
"resetInstructions": "密码重置指令已发送到您的电子邮件",
"pageTitle": "忘记密码?"
},
"home": {
"description": "WeTransfer的开源替代方案。安全分享文件无需跟踪或限制。",
"documentation": "文档",
"starOnGithub": "在GitHub上点赞",
"privacyMessage": "本应用注重隐私。在上传前,您的文件仅对拥有共享链接的人可见。永远免费且开源。",
"header": {
"fileSharing": "文件共享",
"tagline": "简单且免费"
},
"pageTitle": "首页"
},
"profile": {
"password": {
"title": "修改密码",
"newPassword": "新密码",
"confirmPassword": "确认新密码",
"updateButton": "更新密码"
},
"form": {
"title": "个人资料信息",
"firstName": "名字",
"lastName": "姓氏",
"username": "用户名",
"email": "电子邮件",
"updateButton": "更新资料"
},
"header": {
"title": "个人资料",
"subtitle": "管理您的个人信息和密码"
},
"picture": {
"title": "个人头像",
"description": "点击相机图标以更换头像",
"uploadPhoto": "上传照片",
"removePhoto": "移除照片"
},
"errors": {
"loadFailed": "加载用户数据失败",
"updateFailed": "更新个人资料失败",
"passwordFailed": "更新密码失败",
"imageFailed": "更新头像失败",
"imageRemoveFailed": "移除头像失败"
},
"messages": {
"noChanges": "没有可保存的更改",
"updateSuccess": "个人资料更新成功",
"fillPasswords": "请填写两个密码字段",
"passwordSuccess": "密码更新成功",
"imageSuccess": "头像更新成功",
"imageRemoved": "头像移除成功"
},
"pageTitle": "个人资料"
},
"resetPassword": {
"pageTitle": "重置密码",
"header": {
"title": "重置密码",
"description": "在下方输入您的新密码"
},
"form": {
"newPassword": "新密码",
"newPasswordPlaceholder": "请输入新密码",
"confirmPassword": "确认新密码",
"confirmPasswordPlaceholder": "请再次输入新密码",
"resetting": "正在重置密码...",
"submit": "重置密码",
"backToLogin": "返回登录"
},
"messages": {
"success": "密码重置成功"
},
"errors": {
"serverError": "密码重置失败,请重试。",
"invalidToken": "无效或缺失重置令牌"
}
},
"settings": {
"groups": {
"defaultDescription": "配置选项",
"general": {
"title": "通用",
"description": "基本的应用设置"
},
"email": {
"title": "电子邮件",
"description": "电子邮件服务器配置"
},
"security": {
"title": "安全性",
"description": "安全与认证设置"
},
"storage": {
"title": "存储",
"description": "文件存储配置"
}
},
"fields": {
"noDescription": "暂无描述",
"appLogo": {
"title": "应用Logo",
"description": "应用的Logo图片"
},
"appName": {
"title": "应用名称",
"description": "显示给用户的应用名称"
},
"appDescription": {
"title": "应用描述",
"description": "对应用的简短描述"
},
"showHomePage": {
"title": "显示首页",
"description": "安装后显示首页"
},
"smtpEnabled": {
"title": "启用SMTP",
"description": "启用或禁用SMTP邮件功能"
},
"smtpHost": {
"title": "SMTP服务器",
"description": "SMTP服务器地址"
},
"smtpPort": {
"title": "SMTP端口",
"description": "SMTP服务器端口"
},
"smtpUser": {
"title": "SMTP用户名",
"description": "用于SMTP认证的用户名"
},
"smtpPass": {
"title": "SMTP密码",
"description": "用于SMTP认证的密码"
},
"smtpFromName": {
"title": "发件人姓名",
"description": "发送邮件时显示的名称"
},
"smtpFromEmail": {
"title": "发件人电子邮件",
"description": "发件人的电子邮件地址"
},
"maxLoginAttempts": {
"title": "最大登录尝试次数",
"description": "达到限制前允许的最大登录尝试次数"
},
"loginBlockDuration": {
"title": "登录阻止时长",
"description": "超过尝试次数后的阻止时长(以秒为单位)"
},
"passwordMinLength": {
"title": "最小密码长度",
"description": "密码所需的最小字符数"
},
"passwordResetTokenExpiration": {
"title": "密码重置令牌有效期",
"description": "密码重置令牌的有效时长(以秒为单位)"
},
"maxFileSize": {
"title": "最大文件大小",
"description": "允许上传的最大文件大小(以字节为单位)"
},
"maxTotalStoragePerUser": {
"title": "每个用户的最大存储量",
"description": "每个用户的总存储限制(以字节为单位)"
}
},
"buttons": {
"save": "保存 {{group}}"
},
"errors": {
"loadFailed": "加载设置失败",
"updateFailed": "更新设置失败"
},
"messages": {
"noChanges": "没有需要保存的更改",
"updateSuccess": "{{group}}设置更新成功"
},
"title": "设置",
"breadcrumb": "设置",
"pageTitle": "设置"
},
"share": {
"errors": {
"invalidPassword": "无效的密码。请重试。",
"loadFailed": "加载共享失败",
"downloadFailed": "下载文件失败"
},
"messages": {
"downloadStarted": "下载已开始"
},
"password": {
"title": "密码保护的共享",
"protected": "此共享受密码保护",
"incorrect": "密码不正确。请重试。",
"label": "密码",
"placeholder": "请输入共享密码",
"submit": "提交"
},
"details": {
"untitled": "未命名",
"created": "创建于:{{date}}",
"expires": "过期于:{{date}}"
},
"notFound": {
"title": "未找到共享",
"description": "该共享可能已被删除或已过期。"
},
"pageTitle": "共享"
},
"shares": {
"errors": {
"loadFailed": "加载共享失败",
"notifyFailed": "通知收件人失败",
"smtpConfigFailed": "加载SMTP配置失败"
},
"messages": {
"linkCopied": "链接已复制到剪贴板",
"recipientsNotified": "收件人已成功通知"
},
"empty": {
"message": "尚未创建共享",
"createButton": "创建共享"
},
"header": {
"title": "我的共享",
"myShares": "我的共享"
},
"search": {
"title": "所有共享",
"createButton": "创建共享",
"placeholder": "搜索共享...",
"results": "在总共{{total}}个共享中找到了{{filtered}}个"
},
"pageTitle": "共享"
},
"users": {
"modes": {
"create": "创建",
"edit": "编辑"
},
"errors": {
"loadFailed": "加载用户失败",
"submitFailed": "用户{{mode}}失败",
"deleteFailed": "删除用户失败",
"statusUpdateFailed": "更新用户状态失败"
},
"messages": {
"createSuccess": "用户创建成功",
"updateSuccess": "用户更新成功",
"deleteSuccess": "用户删除成功",
"activateSuccess": "用户已成功激活",
"deactivateSuccess": "用户已成功停用"
},
"actions": {
"edit": "编辑",
"activate": "激活",
"deactivate": "停用",
"delete": "删除"
},
"delete": {
"title": "确认删除用户",
"confirmation": "您确定要删除{{firstName}} {{lastName}}吗?此操作不可撤销。",
"confirm": "删除用户"
},
"form": {
"titleCreate": "添加新用户",
"titleEdit": "编辑用户",
"firstName": "名字",
"lastName": "姓氏",
"username": "用户名",
"email": "电子邮件",
"password": "密码",
"newPassword": "新密码(可选)",
"passwordPlaceholder": "留空以保留当前密码",
"role": "角色",
"roleUser": "用户",
"roleAdmin": "管理员",
"create": "创建",
"save": "保存"
},
"status": {
"title": "确认状态更改",
"confirmation": "您确定要{{action}}{{firstName}} {{lastName}}吗?",
"activate": "激活",
"deactivate": "停用",
"user": "用户"
},
"header": {
"title": "用户管理",
"addUser": "添加用户",
"management": "用户管理"
},
"table": {
"user": "用户",
"email": "电子邮件",
"status": "状态",
"role": "角色",
"actions": "操作",
"active": "激活",
"inactive": "停用",
"admin": "管理员",
"userr": "用户"
}
},
"logo": {
"labels": {
"appLogo": "应用Logo"
},
"buttons": {
"upload": "上传Logo",
"remove": "删除Logo"
},
"messages": {
"uploadSuccess": "Logo上传成功",
"removeSuccess": "Logo删除成功"
},
"errors": {
"uploadFailed": "Logo上传失败",
"removeFailed": "Logo删除失败"
}
},
"navbar": {
"logoAlt": "应用Logo",
"profileMenu": "个人菜单",
"profile": "个人资料",
"settings": "设置",
"usersManagement": "用户管理",
"logout": "退出登录"
}
}

7
apps/app/next.config.ts Normal file
View File

@@ -0,0 +1,7 @@
import { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";
const nextConfig: NextConfig = {};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);

58
apps/app/package.json Normal file
View File

@@ -0,0 +1,58 @@
{
"name": "palmr-app-v2",
"version": "2.0.0",
"private": true,
"scripts": {
"dev": "next dev --turbopack",
"build": "next build",
"start": "next start",
"lint": "eslint \"src/**/*.+(ts|tsx)\"",
"lint:fix": "eslint \"src/**/*.+(ts|tsx)\" --fix",
"format": "prettier . --write",
"format:check": "prettier . --check"
},
"dependencies": {
"@hookform/resolvers": "^5.0.1",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.6",
"@radix-ui/react-label": "^2.1.2",
"@radix-ui/react-slot": "^1.1.2",
"@tabler/icons-react": "^3.31.0",
"axios": "^1.8.4",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"framer-motion": "^12.6.3",
"lucide-react": "^0.487.0",
"next": "15.2.4",
"next-intl": "^4.0.2",
"next-themes": "^0.4.6",
"nookies": "^2.5.2",
"react": "^19.1.0",
"react-country-flag": "^3.1.0",
"react-dom": "^19.1.0",
"react-hook-form": "^7.55.0",
"tailwind-merge": "^3.1.0",
"tw-animate-css": "^1.2.5",
"zod": "^3.24.2",
"zustand": "^5.0.3"
},
"devDependencies": {
"@eslint/eslintrc": "3.3.1",
"@eslint/js": "9.23.0",
"@ianvs/prettier-plugin-sort-imports": "4.4.1",
"@tailwindcss/postcss": "4.1.2",
"@types/node": "22.14.0",
"@types/react": "19.1.0",
"@types/react-dom": "19.1.1",
"@typescript-eslint/eslint-plugin": "8.29.0",
"@typescript-eslint/parser": "8.29.0",
"eslint": "9.23.0",
"eslint-config-next": "15.2.4",
"eslint-config-prettier": "9.1.0",
"eslint-plugin-prettier": "5.2.6",
"prettier": "3.5.3",
"prettier-plugin-sort-json": "4.1.1",
"tailwindcss": "4.1.2",
"typescript": "5.8.2"
}
}

4902
apps/app/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,5 @@
const config = {
plugins: ["@tailwindcss/postcss"],
};
export default config;

1
apps/app/public/file.svg Normal file
View File

@@ -0,0 +1 @@
<svg fill="none" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><path d="M14.5 13.5V5.41a1 1 0 0 0-.3-.7L9.8.29A1 1 0 0 0 9.08 0H1.5v13.5A2.5 2.5 0 0 0 4 16h8a2.5 2.5 0 0 0 2.5-2.5m-1.5 0v-7H8v-5H3v12a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1M9.5 5V2.12L12.38 5zM5.13 5h-.62v1.25h2.12V5zm-.62 3h7.12v1.25H4.5zm.62 3h-.62v1.25h7.12V11z" clip-rule="evenodd" fill="#666" fill-rule="evenodd"/></svg>

After

Width:  |  Height:  |  Size: 391 B

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><g clip-path="url(#a)"><path fill-rule="evenodd" clip-rule="evenodd" d="M10.27 14.1a6.5 6.5 0 0 0 3.67-3.45q-1.24.21-2.7.34-.31 1.83-.97 3.1M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16m.48-1.52a7 7 0 0 1-.96 0H7.5a4 4 0 0 1-.84-1.32q-.38-.89-.63-2.08a40 40 0 0 0 3.92 0q-.25 1.2-.63 2.08a4 4 0 0 1-.84 1.31zm2.94-4.76q1.66-.15 2.95-.43a7 7 0 0 0 0-2.58q-1.3-.27-2.95-.43a18 18 0 0 1 0 3.44m-1.27-3.54a17 17 0 0 1 0 3.64 39 39 0 0 1-4.3 0 17 17 0 0 1 0-3.64 39 39 0 0 1 4.3 0m1.1-1.17q1.45.13 2.69.34a6.5 6.5 0 0 0-3.67-3.44q.65 1.26.98 3.1M8.48 1.5l.01.02q.41.37.84 1.31.38.89.63 2.08a40 40 0 0 0-3.92 0q.25-1.2.63-2.08a4 4 0 0 1 .85-1.32 7 7 0 0 1 .96 0m-2.75.4a6.5 6.5 0 0 0-3.67 3.44 29 29 0 0 1 2.7-.34q.31-1.83.97-3.1M4.58 6.28q-1.66.16-2.95.43a7 7 0 0 0 0 2.58q1.3.27 2.95.43a18 18 0 0 1 0-3.44m.17 4.71q-1.45-.12-2.69-.34a6.5 6.5 0 0 0 3.67 3.44q-.65-1.27-.98-3.1" fill="#666"/></g><defs><clipPath id="a"><path fill="#fff" d="M0 0h16v16H0z"/></clipPath></defs></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

1
apps/app/public/next.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 394 80"><path fill="#000" d="M262 0h68.5v12.7h-27.2v66.6h-13.6V12.7H262V0ZM149 0v12.7H94v20.4h44.3v12.6H94v21h55v12.6H80.5V0h68.7zm34.3 0h-17.8l63.8 79.4h17.9l-32-39.7 32-39.6h-17.9l-23 28.6-23-28.6zm18.3 56.7-9-11-27.1 33.7h17.8l18.3-22.7z"/><path fill="#000" d="M81 79.3 17 0H0v79.3h13.6V17l50.2 62.3H81Zm252.6-.4c-1 0-1.8-.4-2.5-1s-1.1-1.6-1.1-2.6.3-1.8 1-2.5 1.6-1 2.6-1 1.8.3 2.5 1a3.4 3.4 0 0 1 .6 4.3 3.7 3.7 0 0 1-3 1.8zm23.2-33.5h6v23.3c0 2.1-.4 4-1.3 5.5a9.1 9.1 0 0 1-3.8 3.5c-1.6.8-3.5 1.3-5.7 1.3-2 0-3.7-.4-5.3-1s-2.8-1.8-3.7-3.2c-.9-1.3-1.4-3-1.4-5h6c.1.8.3 1.6.7 2.2s1 1.2 1.6 1.5c.7.4 1.5.5 2.4.5 1 0 1.8-.2 2.4-.6a4 4 0 0 0 1.6-1.8c.3-.8.5-1.8.5-3V45.5zm30.9 9.1a4.4 4.4 0 0 0-2-3.3 7.5 7.5 0 0 0-4.3-1.1c-1.3 0-2.4.2-3.3.5-.9.4-1.6 1-2 1.6a3.5 3.5 0 0 0-.3 4c.3.5.7.9 1.3 1.2l1.8 1 2 .5 3.2.8c1.3.3 2.5.7 3.7 1.2a13 13 0 0 1 3.2 1.8 8.1 8.1 0 0 1 3 6.5c0 2-.5 3.7-1.5 5.1a10 10 0 0 1-4.4 3.5c-1.8.8-4.1 1.2-6.8 1.2-2.6 0-4.9-.4-6.8-1.2-2-.8-3.4-2-4.5-3.5a10 10 0 0 1-1.7-5.6h6a5 5 0 0 0 3.5 4.6c1 .4 2.2.6 3.4.6 1.3 0 2.5-.2 3.5-.6 1-.4 1.8-1 2.4-1.7a4 4 0 0 0 .8-2.4c0-.9-.2-1.6-.7-2.2a11 11 0 0 0-2.1-1.4l-3.2-1-3.8-1c-2.8-.7-5-1.7-6.6-3.2a7.2 7.2 0 0 1-2.4-5.7 8 8 0 0 1 1.7-5 10 10 0 0 1 4.3-3.5c2-.8 4-1.2 6.4-1.2 2.3 0 4.4.4 6.2 1.2 1.8.8 3.2 2 4.3 3.4 1 1.4 1.5 3 1.5 5h-5.8z"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1155 1000"><path d="m577.3 0 577.4 1000H0z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 128 B

View File

@@ -0,0 +1 @@
<svg fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path fill-rule="evenodd" clip-rule="evenodd" d="M1.5 2.5h13v10a1 1 0 0 1-1 1h-11a1 1 0 0 1-1-1zM0 1h16v11.5a2.5 2.5 0 0 1-2.5 2.5h-11A2.5 2.5 0 0 1 0 12.5zm3.75 4.5a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5M7 4.75a.75.75 0 1 1-1.5 0 .75.75 0 0 1 1.5 0m1.75.75a.75.75 0 1 0 0-1.5.75.75 0 0 0 0 1.5" fill="#666"/></svg>

After

Width:  |  Height:  |  Size: 385 B

View File

@@ -0,0 +1,75 @@
import Link from "next/link";
import { IconBrandGithubFilled } from "@tabler/icons-react";
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
import { Button } from "@/components/ui/button";
import { siteConfig } from "@/config/site";
import { HomeContentProps } from "../types";
import { BackgroundLights } from "../../../components/ui/background-lights";
import { HomeHeader } from "./home-header";
const fadeInAnimation = {
animate: { opacity: 1 },
initial: { opacity: 0 },
transition: { duration: 0.5 }
};
const fadeInUpAnimation = {
animate: { opacity: 1, y: 0 },
initial: { opacity: 0, y: 20 },
transition: { duration: 0.5 }
};
function ActionButtons({ t }: { t: (key: string) => string }) {
return (
<div className="flex gap-3">
<Button asChild variant="ghost">
<Link href={siteConfig.links.docs} target="_blank" rel="noopener noreferrer">
{t("home.documentation")}
</Link>
</Button>
<Button asChild variant="outline">
<Link href={siteConfig.links.github} target="_blank" rel="noopener noreferrer">
<IconBrandGithubFilled className="size-5" />
{t("home.starOnGithub")}
</Link>
</Button>
</div>
);
}
export function HomeContent({ isLoading }: HomeContentProps) {
const t = useTranslations();
if (isLoading) {
return null;
}
return (
<div className="container mx-auto max-w-7xl px-6 flex-grow">
<BackgroundLights />
<section className="relative flex flex-col items-center justify-center gap-6 m-auto h-full">
<HomeHeader title="🌴 Palmr." />
<motion.div
{...fadeInAnimation}
className="w-full text-lg lg:text-xl text-default-600 mt-4 text-center whitespace-normal"
transition={{ delay: 0.6, ...fadeInAnimation.transition }}
>
{t("home.description")}
</motion.div>
<motion.div
{...fadeInUpAnimation}
className="flex flex-col items-center gap-6 mt-8"
transition={{ delay: 0.8, ...fadeInUpAnimation.transition }}
>
<ActionButtons t={t} />
<p className="text-sm opacity-70 max-w-md text-center">
{t("home.privacyMessage")}
</p>
</motion.div>
</section>
</div>
);
}

View File

@@ -0,0 +1,56 @@
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
import { HomeHeaderProps } from "../types";
const fadeInUpAnimation = {
animate: { opacity: 1, y: 0 },
initial: { opacity: 0, y: 20 },
transition: { duration: 0.5 }
};
const titleAnimation = {
animate: { scale: 1 },
initial: { scale: 0.9 },
transition: { duration: 0.3 }
};
const slideInAnimation = (delay: number, direction: -1 | 1) => ({
animate: { opacity: 1, x: 0 },
initial: { opacity: 0, x: 20 * direction },
transition: { delay, duration: 0.5 }
});
export function HomeHeader({ title }: HomeHeaderProps) {
const t = useTranslations();
return (
<motion.div
{...fadeInUpAnimation}
className="inline-block max-w-xl text-center justify-center"
>
<div className="flex flex-col gap-8">
<motion.span
{...titleAnimation}
className="text-4xl lg:text-6xl font-extrabold tracking-tight"
>
{title}
</motion.span>
<div className="flex flex-col gap-2">
<motion.span
{...slideInAnimation(0.2, -1)}
className="text-4xl lg:text-5xl font-semibold tracking-tight text-primary"
>
{t("home.header.fileSharing")}
</motion.span>
<motion.span
{...slideInAnimation(0.4, 1)}
className="text-[2.3rem] lg:text-5xl leading-9 font-semibold tracking-tight"
>
{t("home.header.tagline")}
</motion.span>
</div>
</div>
</motion.div>
);
}

View File

@@ -0,0 +1,92 @@
"use client";
import { useEffect } from "react";
import { useState } from "react";
import Link from "next/link";
import { IconHeart, IconMenu2 } from "@tabler/icons-react";
import { LanguageSwitcher } from "@/components/general/language-switcher";
import { ModeToggle } from "@/components/mode-toggle";
import { Button } from "@/components/ui/button";
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { siteConfig } from "@/config/site";
import { useAppInfo } from "@/contexts/app-info-context";
import { cn } from "@/lib/utils";
export function Navbar() {
const { appName, appLogo, refreshAppInfo } = useAppInfo();
const [isMenuOpen, setIsMenuOpen] = useState(false);
useEffect(() => {
refreshAppInfo();
}, [refreshAppInfo]);
return (
<header className="sticky top-0 z-40 w-full border-b border-border/50 bg-background/70 backdrop-blur-sm px-6">
<div className="container flex h-16 max-w-screen-xl items-center mx-auto">
<div className="flex flex-1 items-center justify-between">
<div className="flex items-center gap-3">
<Link href="/" className="flex items-center gap-2">
{appLogo && <img alt="App Logo" className="h-8 w-8 object-contain" src={appLogo} />}
<p className="font-bold text-2xl">{appName}</p>
</Link>
<nav className="hidden lg:flex ml-2 gap-4">
{siteConfig.navItems.map((item) => (
<Link
key={item.href}
href={item.href}
className={cn(
"text-sm font-medium transition-colors hover:text-foreground/80",
"data-[active=true]:text-primary data-[active=true]:font-medium"
)}
>
{item.label}
</Link>
))}
</nav>
</div>
<div className="hidden md:flex items-center gap-2">
<LanguageSwitcher />
<ModeToggle />
<Button asChild variant="ghost" className="text-sm font-normal">
<Link href={siteConfig.links.sponsor} target="_blank" rel="noopener noreferrer">
<IconHeart className="h-4 w-4 text-destructive" />
Sponsor
</Link>
</Button>
</div>
<div className="flex items-center gap-2 sm:hidden">
<LanguageSwitcher />
<ModeToggle />
<Sheet open={isMenuOpen} onOpenChange={setIsMenuOpen}>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="h-9 w-9 p-0">
<IconMenu2 className="h-5 w-5" />
<span className="sr-only">Toggle menu</span>
</Button>
</SheetTrigger>
<SheetContent side="right">
<div className="grid gap-6 pt-6">
<div className="flex flex-col gap-4">
{siteConfig.navMenuItems.map((item, index) => (
<Link
key={`${item}-${index}`}
href={item.href}
className="text-foreground text-lg font-medium"
onClick={() => setIsMenuOpen(false)}
>
{item.label}
</Link>
))}
</div>
</div>
</SheetContent>
</Sheet>
</div>
</div>
</div>
</header>
);
}

View File

@@ -0,0 +1,52 @@
"use client";
import { useEffect } from "react";
import { useRouter } from "next/navigation";
import { create } from 'zustand';
import { getAllConfigs } from "@/http/endpoints";
interface Config {
key: string;
value: string;
}
interface HomeStore {
isLoading: boolean;
checkHomePageAccess: () => Promise<boolean>;
}
const useHomeStore = create<HomeStore>((set) => ({
isLoading: true,
checkHomePageAccess: async () => {
try {
const response = await getAllConfigs();
const showHomePage = response.data.configs.find(
(config: Config) => config.key === "showHomePage"
)?.value === "true";
set({ isLoading: false });
return showHomePage;
} catch (error) {
console.error("Failed to check homepage access:", error);
set({ isLoading: false });
return false;
}
}
}));
export function useHome() {
const router = useRouter();
const { isLoading, checkHomePageAccess } = useHomeStore();
useEffect(() => {
checkHomePageAccess().then(hasAccess => {
if (!hasAccess) {
router.push("/login");
}
});
}, [router, checkHomePageAccess]);
return {
isLoading,
};
}

View File

@@ -0,0 +1,18 @@
import { Metadata } from 'next'
import { getTranslations } from 'next-intl/server'
export async function generateMetadata(): Promise<Metadata> {
const t = await getTranslations()
return {
title: t('home.pageTitle'),
}
}
export default function HomeLayout({
children,
}: {
children: React.ReactNode
}) {
return <>{children}</>
}

View File

@@ -0,0 +1,23 @@
"use client";
import { LoadingScreen } from "@/components/layout/loading-screen";
import { DefaultFooter } from "@/components/ui/default-footer";
import { HomeContent } from "./components/home-content";
import { Navbar } from "./components/navbar";
import { useHome } from "./hooks/use-home";
export default function HomePage() {
const { isLoading } = useHome();
if (isLoading) {
return <LoadingScreen />;
}
return (
<div className="relative flex flex-col h-screen">
<Navbar />
<HomeContent isLoading={isLoading} />
<DefaultFooter />
</div>
);
}

View File

@@ -0,0 +1,7 @@
export interface HomeContentProps {
isLoading: boolean;
}
export interface HomeHeaderProps {
title: string;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

View File

@@ -0,0 +1,122 @@
@import "tailwindcss";
@import "tw-animate-css";
@custom-variant dark (&:is(.dark *));
@theme inline {
--color-background: var(--background);
--color-foreground: var(--foreground);
--font-sans: var(--font-geist-sans);
--font-mono: var(--font-geist-mono);
--color-sidebar-ring: var(--sidebar-ring);
--color-sidebar-border: var(--sidebar-border);
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
--color-sidebar-accent: var(--sidebar-accent);
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
--color-sidebar-primary: var(--sidebar-primary);
--color-sidebar-foreground: var(--sidebar-foreground);
--color-sidebar: var(--sidebar);
--color-chart-5: var(--chart-5);
--color-chart-4: var(--chart-4);
--color-chart-3: var(--chart-3);
--color-chart-2: var(--chart-2);
--color-chart-1: var(--chart-1);
--color-ring: var(--ring);
--color-input: var(--input);
--color-border: var(--border);
--color-destructive: var(--destructive);
--color-accent-foreground: var(--accent-foreground);
--color-accent: var(--accent);
--color-muted-foreground: var(--muted-foreground);
--color-muted: var(--muted);
--color-secondary-foreground: var(--secondary-foreground);
--color-secondary: var(--secondary);
--color-primary-foreground: var(--primary-foreground);
--color-primary: var(--primary);
--color-popover-foreground: var(--popover-foreground);
--color-popover: var(--popover);
--color-card-foreground: var(--card-foreground);
--color-card: var(--card);
--radius-sm: calc(var(--radius) - 4px);
--radius-md: calc(var(--radius) - 2px);
--radius-lg: var(--radius);
--radius-xl: calc(var(--radius) + 4px);
}
:root {
--radius: 0.75rem;
--background: oklch(1 0 0);
--foreground: oklch(0.141 0.005 285.823);
--card: oklch(1 0 0);
--card-foreground: oklch(0.141 0.005 285.823);
--popover: oklch(1 0 0);
--popover-foreground: oklch(0.141 0.005 285.823);
--primary: oklch(0.723 0.219 149.579);
--primary-foreground: oklch(0.982 0.018 155.826);
--secondary: oklch(0.967 0.001 286.375);
--secondary-foreground: oklch(0.21 0.006 285.885);
--muted: oklch(0.967 0.001 286.375);
--muted-foreground: oklch(0.552 0.016 285.938);
--accent: oklch(0.967 0.001 286.375);
--accent-foreground: oklch(0.21 0.006 285.885);
--destructive: oklch(0.577 0.245 27.325);
--border: oklch(0.92 0.004 286.32);
--input: oklch(0.92 0.004 286.32);
--ring: oklch(0.723 0.219 149.579);
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
--sidebar: oklch(0.985 0 0);
--sidebar-foreground: oklch(0.141 0.005 285.823);
--sidebar-primary: oklch(0.723 0.219 149.579);
--sidebar-primary-foreground: oklch(0.982 0.018 155.826);
--sidebar-accent: oklch(0.967 0.001 286.375);
--sidebar-accent-foreground: oklch(0.21 0.006 285.885);
--sidebar-border: oklch(0.92 0.004 286.32);
--sidebar-ring: oklch(0.723 0.219 149.579);
}
.dark {
--background: oklch(0.141 0.005 285.823);
--foreground: oklch(0.985 0 0);
--card: oklch(0.21 0.006 285.885);
--card-foreground: oklch(0.985 0 0);
--popover: oklch(0.21 0.006 285.885);
--popover-foreground: oklch(0.985 0 0);
--primary: oklch(0.696 0.17 162.48);
--primary-foreground: oklch(0.393 0.095 152.535);
--secondary: oklch(0.274 0.006 286.033);
--secondary-foreground: oklch(0.985 0 0);
--muted: oklch(0.274 0.006 286.033);
--muted-foreground: oklch(0.705 0.015 286.067);
--accent: oklch(0.274 0.006 286.033);
--accent-foreground: oklch(0.985 0 0);
--destructive: oklch(0.704 0.191 22.216);
--border: oklch(1 0 0 / 10%);
--input: oklch(1 0 0 / 15%);
--ring: oklch(0.527 0.154 150.069);
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
--sidebar: oklch(0.21 0.006 285.885);
--sidebar-foreground: oklch(0.985 0 0);
--sidebar-primary: oklch(0.696 0.17 162.48);
--sidebar-primary-foreground: oklch(0.393 0.095 152.535);
--sidebar-accent: oklch(0.274 0.006 286.033);
--sidebar-accent-foreground: oklch(0.985 0 0);
--sidebar-border: oklch(1 0 0 / 10%);
--sidebar-ring: oklch(0.527 0.154 150.069);
}
@layer base {
* {
@apply border-border outline-ring/50;
}
body {
@apply bg-background text-foreground;
}
}

View File

@@ -0,0 +1,52 @@
import type { Metadata } from "next";
import { Geist, Geist_Mono } from "next/font/google";
import { NextIntlClientProvider } from "next-intl";
import { getLocale } from "next-intl/server";
import "./globals.css";
import { useAppInfo } from "@/contexts/app-info-context";
import { ThemeProvider } from "../providers/theme-provider";
import { AuthProvider } from "@/contexts/auth-context";
const geistSans = Geist({
variable: "--font-geist-sans",
subsets: ["latin"],
});
const geistMono = Geist_Mono({
variable: "--font-geist-mono",
subsets: ["latin"],
});
// !TODO: CHANGE METADATA BASED ON API RESPONSE
export const metadata: Metadata = {
title: "Create Next App",
description: "Generated by create next app",
};
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const locale = await getLocale();
if (typeof window !== 'undefined') {
useAppInfo.getState().refreshAppInfo();
}
return (
<html lang={locale} suppressHydrationWarning>
<body className={`${geistSans.variable} ${geistMono.variable} antialiased`}>
<NextIntlClientProvider>
<ThemeProvider attribute="class" defaultTheme="system" enableSystem disableTransitionOnChange>
<AuthProvider>
{children}
</AuthProvider>
</ThemeProvider>
</NextIntlClientProvider>
</body>
</html>
);
}

View File

@@ -0,0 +1,112 @@
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage } from "@/components/ui/form";
import Link from "next/link";
import { useTranslations } from "next-intl";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { createLoginSchema, type LoginFormValues } from "../schemas/schema";
import { PasswordVisibilityToggle } from "./password-visibility-toggle";
interface LoginFormProps {
error?: string;
isVisible: boolean;
onToggleVisibility: () => void;
onSubmit: (data: LoginFormValues) => Promise<void>;
}
export function LoginForm({ error, isVisible, onToggleVisibility, onSubmit }: LoginFormProps) {
const t = useTranslations();
const loginSchema = createLoginSchema(t);
const form = useForm<LoginFormValues>({
resolver: zodResolver(loginSchema),
defaultValues: {
email: "",
password: "",
},
});
const isSubmitting = form.formState.isSubmitting;
const renderErrorMessage = () => (
error && (
<p className="text-destructive text-sm text-center bg-destructive/10 p-2 rounded-md">
{error.replace('errors.', '')}
</p>
)
);
const renderEmailField = () => (
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>{t("login.emailLabel")}</FormLabel>
<FormControl className="-mb-1">
<Input
{...field}
type="email"
placeholder={t("login.emailPlaceholder")}
disabled={isSubmitting}
className="bg-transparent backdrop-blur-md"
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
const renderPasswordField = () => (
<FormField
control={form.control}
name="password"
render={({ field }) => (
<FormItem>
<FormLabel>{t("login.passwordLabel")}</FormLabel>
<FormControl>
<div className="relative">
<Input
{...field}
type={isVisible ? "text" : "password"}
placeholder={t("login.passwordPlaceholder")}
disabled={isSubmitting}
className="bg-transparent backdrop-blur-md pr-10"
/>
<PasswordVisibilityToggle
isVisible={isVisible}
onToggle={onToggleVisibility}
/>
</div>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
);
return (
<>
{renderErrorMessage()}
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="flex flex-col gap-4">
{renderEmailField()}
{renderPasswordField()}
<Button className="w-full mt-4 cursor-pointer" variant="default" size="lg" type="submit">
{isSubmitting ? t("login.signingIn") : t("login.signIn")}
</Button>
</form>
</Form>
<div className="flex w-full items-center justify-center px-1 mt-2">
<Link
className="text-muted-foreground hover:text-primary text-sm"
href="/forgot-password"
>
{t("login.forgotPassword")}
</Link>
</div>
</>
);
}

View File

@@ -0,0 +1,26 @@
import { useAppInfo } from "@/contexts/app-info-context";
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
import { useEffect } from "react";
export function LoginHeader() {
const t = useTranslations();
const { appName, refreshAppInfo } = useAppInfo();
useEffect(() => {
refreshAppInfo();
}, [refreshAppInfo]);
return (
<motion.div
animate={{ opacity: 1 }}
className="flex flex-col gap-1 flex-1 items-center justify-center text-center text-default-500 mb-4"
initial={{ opacity: 0 }}
transition={{ delay: 0.2, duration: 0.5 }}
>
<h1 className="text-2xl font-semibold tracking-tight text-center">{t("login.welcome")} {appName}</h1>
<p className="text-default-500 text-sm">{t("login.signInToContinue")}</p>
</motion.div>
);
}

View File

@@ -0,0 +1,24 @@
import { Button } from "@/components/ui/button";
import { IconEye, IconEyeClosed } from "@tabler/icons-react";
interface PasswordVisibilityToggleProps {
isVisible: boolean;
onToggle: () => void;
}
export function PasswordVisibilityToggle({ isVisible, onToggle }: PasswordVisibilityToggleProps) {
return (
<Button
type="button"
variant="link"
onClick={onToggle}
className="absolute right-0 top-1/2 -translate-y-1/2 cursor-pointer"
>
{isVisible ? (
<IconEye className="h-5 w-5 text-muted-foreground" />
) : (
<IconEyeClosed className="h-5 w-5 text-muted-foreground" />
)}
</Button>
);
}

View File

@@ -0,0 +1,8 @@
export const StaticBackgroundLights = () => {
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
<div className="absolute -top-[20%] -left-[20%] w-[140%] h-[140%] bg-[radial-gradient(circle,rgba(34,197,94,0.08)_0%,transparent_70%)] dark:opacity-70 opacity-30" />
<div className="absolute -bottom-[20%] -right-[20%] w-[140%] h-[140%] bg-[radial-gradient(circle,rgba(34,197,94,0.08)_0%,transparent_70%)] dark:opacity-70 opacity-30" />
</div>
);
};

View File

@@ -0,0 +1,77 @@
"use client"
import { useAuth } from "@/contexts/auth-context";
import { login, getCurrentUser } from "@/http/endpoints";
import { useRouter } from "next/navigation";
import { useState, useEffect } from "react";
import axios from "axios";
import { useTranslations } from "next-intl";
import { LoginFormValues } from "../schemas/schema";
export function useLogin() {
const router = useRouter();
const t = useTranslations();
const { isAuthenticated, setUser, setIsAdmin, setIsAuthenticated } = useAuth();
const [isVisible, setIsVisible] = useState(false);
const [error, setError] = useState<string | undefined>();
const [isInitialized, setIsInitialized] = useState(false);
useEffect(() => {
const checkAuth = async () => {
try {
const userResponse = await getCurrentUser();
if (!userResponse?.data?.user) {
throw new Error("No user data");
}
const { isAdmin, ...userData } = userResponse.data.user;
setUser(userData);
setIsAdmin(isAdmin);
setIsAuthenticated(true);
router.push("/dashboard");
} catch (err) {
setUser(null);
setIsAdmin(false);
setIsAuthenticated(false);
} finally {
setIsInitialized(true);
}
};
checkAuth();
}, [router, setUser, setIsAdmin, setIsAuthenticated]);
const toggleVisibility = () => setIsVisible(!isVisible);
const onSubmit = async (data: LoginFormValues) => {
setError(undefined);
try {
await login(data);
const userResponse = await getCurrentUser();
const { isAdmin, ...userData } = userResponse.data.user;
setUser(userData);
setIsAdmin(isAdmin);
setIsAuthenticated(true);
router.replace("/dashboard");
} catch (err) {
if (axios.isAxiosError(err) && err.response?.data?.error) {
setError(t(`errors.${err.response.data.error}`));
} else {
setError(t("errors.unexpectedError"));
}
setIsAuthenticated(false);
setUser(null);
setIsAdmin(false);
}
};
return {
isAuthenticated: !isInitialized ? null : isAuthenticated,
error,
isVisible,
toggleVisibility,
onSubmit,
};
}

View File

@@ -0,0 +1,18 @@
import { Metadata } from 'next'
import { getTranslations } from 'next-intl/server'
interface LayoutProps {
children: React.ReactNode
}
export async function generateMetadata(): Promise<Metadata> {
const translate = await getTranslations()
return {
title: translate('login.pageTitle'),
}
}
export default function LoginLayout({ children }: LayoutProps) {
return <>{children}</>
}

View File

@@ -0,0 +1,47 @@
"use client"
import { LoginForm } from "./components/login-form";
import { LoginHeader } from "./components/login-header";
import { StaticBackgroundLights } from "./components/static-background-lights";
import { useLogin } from "./hooks/use-login";
import { LoadingScreen } from "@/components/layout/loading-screen";
import { DefaultFooter } from "@/components/ui/default-footer";
import { motion } from "framer-motion";
import { LanguageSwitcher } from "@/components/general/language-switcher";
export default function LoginPage() {
const login = useLogin();
if (login.isAuthenticated === null) {
return <LoadingScreen />;
}
return (
<div className="relative flex flex-col h-screen">
<div className="fixed top-4 right-4 z-50">
<LanguageSwitcher />
</div>
<div className="container mx-auto max-w-7xl px-6 flex-grow">
<StaticBackgroundLights />
<div className="relative flex h-full w-full items-center justify-center">
<motion.div
animate={{ opacity: 1, y: 0 }}
className="flex w-full max-w-sm flex-col gap-4 rounded-lg bg-background/80 backdrop-blur-md px-8 pb-10 pt-6 shadow-lg"
initial={{ opacity: 0, y: 20 }}
transition={{ duration: 0.5 }}
>
<LoginHeader />
<LoginForm
error={login.error}
isVisible={login.isVisible}
onSubmit={login.onSubmit}
onToggleVisibility={login.toggleVisibility}
/>
</motion.div>
</div>
</div>
<DefaultFooter />
</div>
);
}

View File

@@ -0,0 +1,17 @@
import * as z from "zod";
import { useTranslations } from "next-intl";
type TFunction = ReturnType<typeof useTranslations>;
export const createLoginSchema = (t: TFunction) =>
z.object({
email: z
.string()
.min(1, t("validation.emailRequired"))
.email(t("validation.invalidEmail")),
password: z
.string()
.min(1, t("validation.passwordRequired"))
});
export type LoginFormValues = z.infer<ReturnType<typeof createLoginSchema>>;

View File

@@ -0,0 +1,10 @@
import { LoginFormData } from "../hooks/use-login";
import { UseFormReturn } from "react-hook-form";
export interface LoginFormProps {
form: UseFormReturn<LoginFormData>;
error: string | null;
isVisible: boolean;
onToggleVisibility: () => void;
onSubmit: (data: LoginFormData) => Promise<void>;
}

View File

@@ -0,0 +1,82 @@
import { useRouter } from "next/navigation";
import { IconLanguage } from "@tabler/icons-react";
import { useLocale } from "next-intl";
import { setCookie } from "nookies";
import ReactCountryFlag from "react-country-flag";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
const languages = {
"en-US": "English",
"pt-BR": "Português",
"fr-FR": "Français",
"es-ES": "Español",
"de-DE": "Deutsch",
"tr-TR": "Türkçe (Turkish)",
"ru-RU": "Русский (Russian)",
"hi-IN": "हिन्दी (Hindi)",
"ar-SA": "العربية (Arabic)",
"zh-CN": "中文 (Chinese)",
"ja-JP": "日本語 (Japanese)",
"ko-KR": "한국어 (Korean)",
};
const COOKIE_LANG_KEY = "NEXT_LOCALE";
const COOKIE_MAX_AGE = 365 * 24 * 60 * 60;
export function LanguageSwitcher() {
const locale = useLocale();
const router = useRouter();
const changeLanguage = (fullLocale: string) => {
setCookie(null, COOKIE_LANG_KEY, fullLocale, {
maxAge: COOKIE_MAX_AGE,
path: "/",
sameSite: "lax",
secure: process.env.NODE_ENV === "production",
});
router.refresh();
};
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon" className="h-9 w-9 p-0">
<IconLanguage className="h-5 w-5" />
<span className="sr-only">Change language</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
{Object.entries(languages).map(([code, name]) => {
const isCurrentLocale = locale === code.split("-")[0];
return (
<DropdownMenuItem
key={code}
onClick={() => changeLanguage(code)}
className={isCurrentLocale ? "bg-accent" : ""}
>
<ReactCountryFlag
svg
countryCode={code.split("-")[1]}
style={{
marginRight: "8px",
width: "1em",
height: "1em",
}}
/>
{name}
</DropdownMenuItem>
);
})}
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -0,0 +1,27 @@
import { motion } from "framer-motion";
import { useTranslations } from "next-intl";
import { BackgroundLights } from "@/components/ui/background-lights";
export function LoadingScreen() {
const t = useTranslations();
return (
<div className="fixed inset-0 bg-background">
<BackgroundLights />
<div className="relative flex flex-col items-center justify-center h-full">
<motion.div
animate={{ scale: [1, 1.1, 1] }}
className="flex flex-col items-center gap-4"
transition={{
duration: 1.5,
repeat: Infinity,
ease: "easeInOut",
}}
>
<span className="text-xl font-semibold text-primary">{t("common.loading")}</span>
</motion.div>
</div>
</div>
);
}

View File

@@ -0,0 +1,35 @@
// !!TODO: ADD TRANSLATION SUPPORT FOR THESE BUTTONS
"use client";
import * as React from "react";
import { IconMoon, IconSun } from "@tabler/icons-react";
import { useTheme } from "next-themes";
import { Button } from "@/components/ui/button";
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
export function ModeToggle() {
const { setTheme } = useTheme();
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon">
<IconSun className="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<IconMoon className="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onClick={() => setTheme("light")}>Light</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("dark")}>Dark</DropdownMenuItem>
<DropdownMenuItem onClick={() => setTheme("system")}>System</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
);
}

View File

@@ -0,0 +1,33 @@
import { motion } from "framer-motion";
export function BackgroundLights() {
return (
<div className="absolute inset-0 -z-10 overflow-hidden">
<motion.div
animate={{
scale: [1, 1.1, 1],
opacity: [0.3, 0.5, 0.3],
}}
className="absolute -top-[20%] -left-[20%] w-[140%] h-[140%] bg-[radial-gradient(circle,rgba(34,197,94,0.15)_0%,transparent_70%)] dark:opacity-100 opacity-50"
transition={{
duration: 5,
repeat: Infinity,
ease: "easeInOut",
}}
/>
<motion.div
animate={{
scale: [1, 1.1, 1],
opacity: [0.3, 0.5, 0.3],
}}
className="absolute -bottom-[20%] -right-[20%] w-[140%] h-[140%] bg-[radial-gradient(circle,rgba(34,197,94,0.15)_0%,transparent_70%)] dark:opacity-100 opacity-50"
transition={{
duration: 5,
repeat: Infinity,
ease: "easeInOut",
delay: 2.5,
}}
/>
</div>
);
}

View File

@@ -0,0 +1,59 @@
import * as React from "react"
import { Slot } from "@radix-ui/react-slot"
import { cva, type VariantProps } from "class-variance-authority"
import { cn } from "@/lib/utils"
const buttonVariants = cva(
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
{
variants: {
variant: {
default:
"bg-primary text-primary-foreground shadow-xs hover:bg-primary/90",
destructive:
"bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
outline:
"border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
secondary:
"bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
ghost:
"hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
default: "h-9 px-4 py-2 has-[>svg]:px-3",
sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
icon: "size-9",
},
},
defaultVariants: {
variant: "default",
size: "default",
},
}
)
function Button({
className,
variant,
size,
asChild = false,
...props
}: React.ComponentProps<"button"> &
VariantProps<typeof buttonVariants> & {
asChild?: boolean
}) {
const Comp = asChild ? Slot : "button"
return (
<Comp
data-slot="button"
className={cn(buttonVariants({ variant, size, className }))}
{...props}
/>
)
}
export { Button, buttonVariants }

View File

@@ -0,0 +1,25 @@
import Link from "next/link";
import { useTranslations } from "next-intl";
import { version } from "../../../package.json";
export function DefaultFooter() {
const t = useTranslations();
return (
<footer className="w-full flex items-center justify-center py-3 h-16">
<div className="flex flex-col items-center">
<Link
target="_blank"
className="flex items-center gap-1 text-current"
href="https://kyantech.com.br"
title={t("footer.kyanHomepage")}
>
<span className="text-default-600 text-xs sm:text-sm">{t("footer.poweredBy")}</span>
<p className="text-green-700 text-xs sm:text-sm">Kyantech Solutions</p>
</Link>
<span className="text-default-500 text-[11px] mt-1">v{version}-beta</span>
</div>
</footer>
);
}

View File

@@ -0,0 +1,257 @@
"use client"
import * as React from "react"
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function DropdownMenu({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Root>) {
return <DropdownMenuPrimitive.Root data-slot="dropdown-menu" {...props} />
}
function DropdownMenuPortal({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>) {
return (
<DropdownMenuPrimitive.Portal data-slot="dropdown-menu-portal" {...props} />
)
}
function DropdownMenuTrigger({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Trigger>) {
return (
<DropdownMenuPrimitive.Trigger
data-slot="dropdown-menu-trigger"
{...props}
/>
)
}
function DropdownMenuContent({
className,
sideOffset = 4,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Content>) {
return (
<DropdownMenuPrimitive.Portal>
<DropdownMenuPrimitive.Content
data-slot="dropdown-menu-content"
sideOffset={sideOffset}
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-md border p-1 shadow-md",
className
)}
{...props}
/>
</DropdownMenuPrimitive.Portal>
)
}
function DropdownMenuGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Group>) {
return (
<DropdownMenuPrimitive.Group data-slot="dropdown-menu-group" {...props} />
)
}
function DropdownMenuItem({
className,
inset,
variant = "default",
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Item> & {
inset?: boolean
variant?: "default" | "destructive"
}) {
return (
<DropdownMenuPrimitive.Item
data-slot="dropdown-menu-item"
data-inset={inset}
data-variant={variant}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
/>
)
}
function DropdownMenuCheckboxItem({
className,
children,
checked,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.CheckboxItem>) {
return (
<DropdownMenuPrimitive.CheckboxItem
data-slot="dropdown-menu-checkbox-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
checked={checked}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CheckIcon className="size-4" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.CheckboxItem>
)
}
function DropdownMenuRadioGroup({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioGroup>) {
return (
<DropdownMenuPrimitive.RadioGroup
data-slot="dropdown-menu-radio-group"
{...props}
/>
)
}
function DropdownMenuRadioItem({
className,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.RadioItem>) {
return (
<DropdownMenuPrimitive.RadioItem
data-slot="dropdown-menu-radio-item"
className={cn(
"focus:bg-accent focus:text-accent-foreground relative flex cursor-default items-center gap-2 rounded-sm py-1.5 pr-2 pl-8 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
className
)}
{...props}
>
<span className="pointer-events-none absolute left-2 flex size-3.5 items-center justify-center">
<DropdownMenuPrimitive.ItemIndicator>
<CircleIcon className="size-2 fill-current" />
</DropdownMenuPrimitive.ItemIndicator>
</span>
{children}
</DropdownMenuPrimitive.RadioItem>
)
}
function DropdownMenuLabel({
className,
inset,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Label> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.Label
data-slot="dropdown-menu-label"
data-inset={inset}
className={cn(
"px-2 py-1.5 text-sm font-medium data-[inset]:pl-8",
className
)}
{...props}
/>
)
}
function DropdownMenuSeparator({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Separator>) {
return (
<DropdownMenuPrimitive.Separator
data-slot="dropdown-menu-separator"
className={cn("bg-border -mx-1 my-1 h-px", className)}
{...props}
/>
)
}
function DropdownMenuShortcut({
className,
...props
}: React.ComponentProps<"span">) {
return (
<span
data-slot="dropdown-menu-shortcut"
className={cn(
"text-muted-foreground ml-auto text-xs tracking-widest",
className
)}
{...props}
/>
)
}
function DropdownMenuSub({
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.Sub>) {
return <DropdownMenuPrimitive.Sub data-slot="dropdown-menu-sub" {...props} />
}
function DropdownMenuSubTrigger({
className,
inset,
children,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubTrigger> & {
inset?: boolean
}) {
return (
<DropdownMenuPrimitive.SubTrigger
data-slot="dropdown-menu-sub-trigger"
data-inset={inset}
className={cn(
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground flex cursor-default items-center rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[inset]:pl-8",
className
)}
{...props}
>
{children}
<ChevronRightIcon className="ml-auto size-4" />
</DropdownMenuPrimitive.SubTrigger>
)
}
function DropdownMenuSubContent({
className,
...props
}: React.ComponentProps<typeof DropdownMenuPrimitive.SubContent>) {
return (
<DropdownMenuPrimitive.SubContent
data-slot="dropdown-menu-sub-content"
className={cn(
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden rounded-md border p-1 shadow-lg",
className
)}
{...props}
/>
)
}
export {
DropdownMenu,
DropdownMenuPortal,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuLabel,
DropdownMenuItem,
DropdownMenuCheckboxItem,
DropdownMenuRadioGroup,
DropdownMenuRadioItem,
DropdownMenuSeparator,
DropdownMenuShortcut,
DropdownMenuSub,
DropdownMenuSubTrigger,
DropdownMenuSubContent,
}

View File

@@ -0,0 +1,167 @@
"use client"
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { Slot } from "@radix-ui/react-slot"
import {
Controller,
FormProvider,
useFormContext,
useFormState,
type ControllerProps,
type FieldPath,
type FieldValues,
} from "react-hook-form"
import { cn } from "@/lib/utils"
import { Label } from "@/components/ui/label"
const Form = FormProvider
type FormFieldContextValue<
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
> = {
name: TName
}
const FormFieldContext = React.createContext<FormFieldContextValue>(
{} as FormFieldContextValue
)
const FormField = <
TFieldValues extends FieldValues = FieldValues,
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
>({
...props
}: ControllerProps<TFieldValues, TName>) => {
return (
<FormFieldContext.Provider value={{ name: props.name }}>
<Controller {...props} />
</FormFieldContext.Provider>
)
}
const useFormField = () => {
const fieldContext = React.useContext(FormFieldContext)
const itemContext = React.useContext(FormItemContext)
const { getFieldState } = useFormContext()
const formState = useFormState({ name: fieldContext.name })
const fieldState = getFieldState(fieldContext.name, formState)
if (!fieldContext) {
throw new Error("useFormField should be used within <FormField>")
}
const { id } = itemContext
return {
id,
name: fieldContext.name,
formItemId: `${id}-form-item`,
formDescriptionId: `${id}-form-item-description`,
formMessageId: `${id}-form-item-message`,
...fieldState,
}
}
type FormItemContextValue = {
id: string
}
const FormItemContext = React.createContext<FormItemContextValue>(
{} as FormItemContextValue
)
function FormItem({ className, ...props }: React.ComponentProps<"div">) {
const id = React.useId()
return (
<FormItemContext.Provider value={{ id }}>
<div
data-slot="form-item"
className={cn("grid gap-2", className)}
{...props}
/>
</FormItemContext.Provider>
)
}
function FormLabel({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
const { error, formItemId } = useFormField()
return (
<Label
data-slot="form-label"
data-error={!!error}
className={cn("data-[error=true]:text-destructive", className)}
htmlFor={formItemId}
{...props}
/>
)
}
function FormControl({ ...props }: React.ComponentProps<typeof Slot>) {
const { error, formItemId, formDescriptionId, formMessageId } = useFormField()
return (
<Slot
data-slot="form-control"
id={formItemId}
aria-describedby={
!error
? `${formDescriptionId}`
: `${formDescriptionId} ${formMessageId}`
}
aria-invalid={!!error}
{...props}
/>
)
}
function FormDescription({ className, ...props }: React.ComponentProps<"p">) {
const { formDescriptionId } = useFormField()
return (
<p
data-slot="form-description"
id={formDescriptionId}
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
function FormMessage({ className, ...props }: React.ComponentProps<"p">) {
const { error, formMessageId } = useFormField()
const body = error ? String(error?.message ?? "") : props.children
if (!body) {
return null
}
return (
<p
data-slot="form-message"
id={formMessageId}
className={cn("text-destructive text-xs", className)}
{...props}
>
{body}
</p>
)
}
export {
useFormField,
Form,
FormItem,
FormLabel,
FormControl,
FormDescription,
FormMessage,
FormField,
}

View File

@@ -0,0 +1,21 @@
import * as React from "react"
import { cn } from "@/lib/utils"
function Input({ className, type, ...props }: React.ComponentProps<"input">) {
return (
<input
type={type}
data-slot="input"
className={cn(
"file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm",
"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className
)}
{...props}
/>
)
}
export { Input }

View File

@@ -0,0 +1,24 @@
"use client"
import * as React from "react"
import * as LabelPrimitive from "@radix-ui/react-label"
import { cn } from "@/lib/utils"
function Label({
className,
...props
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
return (
<LabelPrimitive.Root
data-slot="label"
className={cn(
"flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50",
className
)}
{...props}
/>
)
}
export { Label }

View File

@@ -0,0 +1,139 @@
"use client"
import * as React from "react"
import * as SheetPrimitive from "@radix-ui/react-dialog"
import { XIcon } from "lucide-react"
import { cn } from "@/lib/utils"
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
return <SheetPrimitive.Root data-slot="sheet" {...props} />
}
function SheetTrigger({
...props
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
}
function SheetClose({
...props
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
}
function SheetPortal({
...props
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
}
function SheetOverlay({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
return (
<SheetPrimitive.Overlay
data-slot="sheet-overlay"
className={cn(
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50",
className
)}
{...props}
/>
)
}
function SheetContent({
className,
children,
side = "right",
...props
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
side?: "top" | "right" | "bottom" | "left"
}) {
return (
<SheetPortal>
<SheetOverlay />
<SheetPrimitive.Content
data-slot="sheet-content"
className={cn(
"bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
side === "right" &&
"data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm",
side === "left" &&
"data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm",
side === "top" &&
"data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b",
side === "bottom" &&
"data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t",
className
)}
{...props}
>
{children}
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
<XIcon className="size-4" />
<span className="sr-only">Close</span>
</SheetPrimitive.Close>
</SheetPrimitive.Content>
</SheetPortal>
)
}
function SheetHeader({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-header"
className={cn("flex flex-col gap-1.5 p-4", className)}
{...props}
/>
)
}
function SheetFooter({ className, ...props }: React.ComponentProps<"div">) {
return (
<div
data-slot="sheet-footer"
className={cn("mt-auto flex flex-col gap-2 p-4", className)}
{...props}
/>
)
}
function SheetTitle({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
return (
<SheetPrimitive.Title
data-slot="sheet-title"
className={cn("text-foreground font-semibold", className)}
{...props}
/>
)
}
function SheetDescription({
className,
...props
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
return (
<SheetPrimitive.Description
data-slot="sheet-description"
className={cn("text-muted-foreground text-sm", className)}
{...props}
/>
)
}
export {
Sheet,
SheetTrigger,
SheetClose,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
}

View File

@@ -0,0 +1,11 @@
import axios from "axios";
const axiosInstance = axios.create({
baseURL: process.env.NEXT_PUBLIC_API_URL,
headers: {
"Content-Type": "application/json",
},
withCredentials: true,
});
export default axiosInstance;

View File

@@ -0,0 +1,29 @@
export type SiteConfig = typeof siteConfig;
export const siteConfig = {
navItems: [
{
label: "Login",
href: "/login",
},
{
label: "Docs",
href: "https://palmr-docs.kyantech.com.br",
},
],
navMenuItems: [
{
label: "Login",
href: "/login",
},
{
label: "Docs",
href: "https://palmr-docs.kyantech.com.br",
},
],
links: {
github: "https://github.com/kyantech/Palmr",
docs: "https://palmr-docs.kyantech.com.br",
sponsor: "https://github.com/sponsors/kyantech",
},
};

View File

@@ -0,0 +1,63 @@
import { create } from 'zustand'
import { getAppInfo } from "@/http/endpoints";
interface AppInfoStore {
appName: string;
appLogo: string;
setAppName: (name: string) => void;
setAppLogo: (logo: string) => void;
refreshAppInfo: () => Promise<void>;
}
const updateFavicon = (logo: string) => {
const link = document.querySelector<HTMLLinkElement>("link[rel*='icon']") || document.createElement("link");
link.type = "image/x-icon";
link.rel = "shortcut icon";
link.href = logo || "/favicon.ico";
document.head.appendChild(link);
};
const updateTitle = (name: string) => {
document.title = name;
};
export const useAppInfo = create<AppInfoStore>((set) => {
if (typeof window !== 'undefined') {
getAppInfo().then((response) => {
set({
appName: response.data.appName,
appLogo: response.data.appLogo,
});
updateTitle(response.data.appName);
updateFavicon(response.data.appLogo);
}).catch((error) => {
console.error("Failed to fetch app info:", error);
});
}
return {
appName: "",
appLogo: "",
setAppName: (name: string) => {
set({ appName: name });
updateTitle(name);
},
setAppLogo: (logo: string) => {
set({ appLogo: logo });
updateFavicon(logo);
},
refreshAppInfo: async () => {
try {
const response = await getAppInfo();
set({
appName: response.data.appName,
appLogo: response.data.appLogo,
});
updateTitle(response.data.appName);
updateFavicon(response.data.appLogo);
} catch (error) {
console.error("Failed to fetch app info:", error);
}
},
};
});

View File

@@ -0,0 +1,75 @@
"use client"
import { getCurrentUser } from "@/http/endpoints";
import type { GetCurrentUser200User } from "@/http/models";
import { createContext, useContext, useEffect, useState } from "react";
type AuthUser = Omit<GetCurrentUser200User, "isAdmin">;
type AuthContextType = {
user: AuthUser | null;
setUser: (user: AuthUser | null) => void;
isAuthenticated: boolean | null;
setIsAuthenticated: (value: boolean) => void;
isAdmin: boolean | null;
setIsAdmin: (value: boolean) => void;
logout: () => void;
};
const AuthContext = createContext<AuthContextType>({
user: null,
setUser: () => {},
isAuthenticated: null,
setIsAuthenticated: () => {},
isAdmin: null,
setIsAdmin: () => {},
logout: () => {},
});
export function AuthProvider({ children }: { children: React.ReactNode }) {
const [isAuthenticated, setIsAuthenticated] = useState<boolean | null>(null);
const [user, setUser] = useState<AuthUser | null>(null);
const [isAdmin, setIsAdmin] = useState<boolean | null>(null);
const logout = () => {
setUser(null);
setIsAdmin(false);
setIsAuthenticated(false);
};
useEffect(() => {
const checkAuth = async () => {
try {
const response = await getCurrentUser();
const { isAdmin, ...userData } = response.data.user;
setUser(userData);
setIsAdmin(isAdmin);
setIsAuthenticated(true);
} catch (err) {
console.error(err);
logout();
}
};
checkAuth();
}, []);
return (
<AuthContext.Provider
value={{
user,
setUser,
isAuthenticated,
setIsAuthenticated,
isAdmin,
setIsAdmin,
logout,
}}
>
{children}
</AuthContext.Provider>
);
}
export const useAuth = () => useContext(AuthContext);

View File

@@ -0,0 +1,81 @@
import type {
GetAppInfoResult,
UploadLogoResult,
RemoveLogoResult,
CheckHealthResult,
GetDiskSpaceResult,
CheckUploadAllowedResult,
UploadLogoBody,
CheckUploadAllowedParams,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
/**
* Get application base information
* @summary Get application base information
*/
export const getAppInfo = <TData = GetAppInfoResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/app/info`, options);
};
/**
* Upload a new app logo (admin only)
* @summary Upload app logo
*/
export const uploadLogo = <TData = UploadLogoResult>(
uploadLogoBody: UploadLogoBody,
options?: AxiosRequestConfig
): Promise<TData> => {
const formData = new FormData();
if (uploadLogoBody.file !== undefined) {
formData.append("file", uploadLogoBody.file as Blob);
}
return axiosInstance.post(`/app/logo`, formData, {
...options,
headers: {
...options?.headers,
"Content-Type": "multipart/form-data",
},
});
};
/**
* Remove the current app logo (admin only)
* @summary Remove app logo
*/
export const removeLogo = <TData = RemoveLogoResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.delete(`/app/logo`, options);
};
/**
* Returns the health status of the API
* @summary Check API Health
*/
export const checkHealth = <TData = CheckHealthResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/health`, options);
};
/**
* Get server disk space information
* @summary Get server disk space information
*/
export const getDiskSpace = <TData = GetDiskSpaceResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/storage/disk-space`, options);
};
/**
* Check if file upload is allowed based on available space (fileSize in bytes)
* @summary Check if file upload is allowed
*/
export const checkUploadAllowed = <TData = CheckUploadAllowedResult>(
params: CheckUploadAllowedParams,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.get(`/storage/check-upload`, {
...options,
params: { ...params, ...options?.params },
});
};

View File

@@ -0,0 +1,20 @@
import type {
GetAppInfo200,
UploadLogo200,
UploadLogoBody,
RemoveLogo200,
CheckHealth200,
GetDiskSpace200,
CheckUploadAllowed200,
CheckUploadAllowedParams,
} from "../../models";
import type { AxiosResponse } from "axios";
export type GetAppInfoResult = AxiosResponse<GetAppInfo200>;
export type UploadLogoResult = AxiosResponse<UploadLogo200>;
export type RemoveLogoResult = AxiosResponse<RemoveLogo200>;
export type CheckHealthResult = AxiosResponse<CheckHealth200>;
export type GetDiskSpaceResult = AxiosResponse<GetDiskSpace200>;
export type CheckUploadAllowedResult = AxiosResponse<CheckUploadAllowed200>;
export type { UploadLogoBody, CheckUploadAllowedParams };

View File

@@ -0,0 +1,38 @@
import type {
LoginResult,
LogoutResult,
RequestPasswordResetResult,
ResetPasswordResult,
GetCurrentUserResult,
LoginBody,
RequestPasswordResetBody,
ResetPasswordBody,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
export const login = <TData = LoginResult>(loginBody: LoginBody, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.post(`/auth/login`, loginBody, options);
};
export const logout = <TData = LogoutResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.post(`/auth/logout`, undefined, options);
};
export const requestPasswordReset = <TData = RequestPasswordResetResult>(
requestPasswordResetBody: RequestPasswordResetBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/auth/forgot-password`, requestPasswordResetBody, options);
};
export const resetPassword = <TData = ResetPasswordResult>(
resetPasswordBody: ResetPasswordBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/auth/reset-password`, resetPasswordBody, options);
};
export const getCurrentUser = <TData = GetCurrentUserResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/auth/me`, options);
};

View File

@@ -0,0 +1,19 @@
import type {
Login200,
LoginBody,
Logout200,
RequestPasswordReset200,
RequestPasswordResetBody,
ResetPassword200,
ResetPasswordBody,
GetCurrentUser200,
} from "../../models";
import type { AxiosResponse } from "axios";
export type LoginResult = AxiosResponse<Login200>;
export type LogoutResult = AxiosResponse<Logout200>;
export type RequestPasswordResetResult = AxiosResponse<RequestPasswordReset200>;
export type ResetPasswordResult = AxiosResponse<ResetPassword200>;
export type GetCurrentUserResult = AxiosResponse<GetCurrentUser200>;
export type { LoginBody, RequestPasswordResetBody, ResetPasswordBody };

View File

@@ -0,0 +1,40 @@
import type {
UpdateConfigResult,
GetAllConfigsResult,
BulkUpdateConfigsResult,
UpdateConfigBody,
BulkUpdateConfigsBodyItem,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
/**
* Update a configuration value (admin only)
* @summary Update a configuration value
*/
export const updateConfig = <TData = UpdateConfigResult>(
key: string,
updateConfigBody: UpdateConfigBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/app/configs/${key}`, updateConfigBody, options);
};
/**
* List all configurations (admin only)
* @summary List all configurations
*/
export const getAllConfigs = <TData = GetAllConfigsResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/app/configs`, options);
};
/**
* Bulk update configuration values (admin only)
* @summary Bulk update configuration values
*/
export const bulkUpdateConfigs = <TData = BulkUpdateConfigsResult>(
bulkUpdateConfigsBodyItem: BulkUpdateConfigsBodyItem[],
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/app/configs`, bulkUpdateConfigsBodyItem, options);
};

View File

@@ -0,0 +1,14 @@
import type {
UpdateConfig200,
UpdateConfigBody,
GetAllConfigs200,
BulkUpdateConfigs200,
BulkUpdateConfigsBodyItem,
} from "../../models";
import type { AxiosResponse } from "axios";
export type UpdateConfigResult = AxiosResponse<UpdateConfig200>;
export type GetAllConfigsResult = AxiosResponse<GetAllConfigs200>;
export type BulkUpdateConfigsResult = AxiosResponse<BulkUpdateConfigs200>;
export type { UpdateConfigBody, BulkUpdateConfigsBodyItem };

View File

@@ -0,0 +1,77 @@
import type {
GetPresignedUrlResult,
RegisterFileResult,
ListFilesResult,
GetDownloadUrlResult,
DeleteFileResult,
UpdateFileResult,
GetPresignedUrlParams,
RegisterFileBody,
UpdateFileBody,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
/**
* Generates a pre-signed URL for direct upload to MinIO
* @summary Get Presigned URL
*/
export const getPresignedUrl = <TData = GetPresignedUrlResult>(
params: GetPresignedUrlParams,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.get(`/files/presigned-url`, {
...options,
params: { ...params, ...options?.params },
});
};
/**
* Registers file metadata in the database
* @summary Register File Metadata
*/
export const registerFile = <TData = RegisterFileResult>(
registerFileBody: RegisterFileBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/files`, registerFileBody, options);
};
/**
* Lists user files
* @summary List Files
*/
export const listFiles = <TData = ListFilesResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/files`, options);
};
/**
* Generates a pre-signed URL for downloading a private file
* @summary Get Download URL
*/
export const getDownloadUrl = <TData = GetDownloadUrlResult>(
objectName: string,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.get(`/files/${objectName}/download`, options);
};
/**
* Deletes a user file
* @summary Delete File
*/
export const deleteFile = <TData = DeleteFileResult>(id: string, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.delete(`/files/${id}`, options);
};
/**
* Updates file metadata in the database
* @summary Update File Metadata
*/
export const updateFile = <TData = UpdateFileResult>(
id: string,
updateFileBody: UpdateFileBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/files/${id}`, updateFileBody, options);
};

View File

@@ -0,0 +1,21 @@
import type {
GetPresignedUrl200,
GetPresignedUrlParams,
RegisterFile201,
RegisterFileBody,
ListFiles200,
GetDownloadUrl200,
DeleteFile200,
UpdateFile200,
UpdateFileBody,
} from "../../models";
import type { AxiosResponse } from "axios";
export type GetPresignedUrlResult = AxiosResponse<GetPresignedUrl200>;
export type RegisterFileResult = AxiosResponse<RegisterFile201>;
export type ListFilesResult = AxiosResponse<ListFiles200>;
export type GetDownloadUrlResult = AxiosResponse<GetDownloadUrl200>;
export type DeleteFileResult = AxiosResponse<DeleteFile200>;
export type UpdateFileResult = AxiosResponse<UpdateFile200>;
export type { GetPresignedUrlParams, RegisterFileBody, UpdateFileBody };

View File

@@ -0,0 +1,6 @@
export * from "./auth";
export * from "./users";
export * from "./files";
export * from "./shares";
export * from "./config";
export * from "./app";

View File

@@ -0,0 +1,180 @@
import type {
CreateShareResult,
UpdateShareResult,
ListUserSharesResult,
GetShareResult,
DeleteShareResult,
UpdateSharePasswordResult,
AddFilesResult,
RemoveFilesResult,
AddRecipientsResult,
RemoveRecipientsResult,
CreateShareAliasResult,
GetShareByAliasResult,
NotifyRecipientsResult,
CreateShareBody,
UpdateShareBody,
GetShareParams,
UpdateSharePasswordBody,
AddFilesBody,
RemoveFilesBody,
AddRecipientsBody,
RemoveRecipientsBody,
CreateShareAliasBody,
GetShareByAliasParams,
NotifyRecipientsBody,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
/**
* Create a new share
* @summary Create a new share
*/
export const createShare = <TData = CreateShareResult>(
createShareBody: CreateShareBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/shares`, createShareBody, options);
};
/**
* Update a share
* @summary Update a share
*/
export const updateShare = <TData = UpdateShareResult>(
updateShareBody: UpdateShareBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.put(`/shares`, updateShareBody, options);
};
/**
* List all shares created by the authenticated user
* @summary List all shares created by the authenticated user
*/
export const listUserShares = <TData = ListUserSharesResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/shares/me`, options);
};
/**
* Get a share by ID
* @summary Get a share by ID
*/
export const getShare = <TData = GetShareResult>(
shareId: string,
params?: GetShareParams,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.get(`/shares/${shareId}`, {
...options,
params: { ...params, ...options?.params },
});
};
/**
* Delete a share
* @summary Delete a share
*/
export const deleteShare = <TData = DeleteShareResult>(id: string, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.delete(`/shares/${id}`, options);
};
/**
* @summary Update share password
*/
export const updateSharePassword = <TData = UpdateSharePasswordResult>(
shareId: string,
updateSharePasswordBody: UpdateSharePasswordBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/shares/${shareId}/password`, updateSharePasswordBody, options);
};
/**
* @summary Add files to share
*/
export const addFiles = <TData = AddFilesResult>(
shareId: string,
addFilesBody: AddFilesBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/shares/${shareId}/files`, addFilesBody, options);
};
/**
* @summary Remove files from share
*/
export const removeFiles = <TData = RemoveFilesResult>(
shareId: string,
removeFilesBody: RemoveFilesBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.delete(`/shares/${shareId}/files`, {
data: removeFilesBody,
...options,
});
};
/**
* @summary Add recipients to a share
*/
export const addRecipients = <TData = AddRecipientsResult>(
shareId: string,
addRecipientsBody: AddRecipientsBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/shares/${shareId}/recipients`, addRecipientsBody, options);
};
/**
* Remove recipients from a share
* @summary Remove recipients from a share
*/
export const removeRecipients = <TData = RemoveRecipientsResult>(
shareId: string,
removeRecipientsBody: RemoveRecipientsBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.delete(`/shares/${shareId}/recipients`, {
data: removeRecipientsBody,
...options,
});
};
/**
* @summary Create or update share alias
*/
export const createShareAlias = <TData = CreateShareAliasResult>(
shareId: string,
createShareAliasBody: CreateShareAliasBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/shares/${shareId}/alias`, createShareAliasBody, options);
};
/**
* @summary Get share by alias
*/
export const getShareByAlias = <TData = GetShareByAliasResult>(
alias: string,
params?: GetShareByAliasParams,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.get(`/shares/alias/${alias}`, {
...options,
params: { ...params, ...options?.params },
});
};
/**
* Send email notification with share link to all recipients
* @summary Send email notification to share recipients
*/
export const notifyRecipients = <TData = NotifyRecipientsResult>(
shareId: string,
notifyRecipientsBody: NotifyRecipientsBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/shares/${shareId}/notify`, notifyRecipientsBody, options);
};

View File

@@ -0,0 +1,55 @@
import type {
CreateShare201,
CreateShareBody,
UpdateShare200,
UpdateShareBody,
ListUserShares200,
GetShare200,
GetShareParams,
DeleteShare200,
UpdateSharePassword200,
UpdateSharePasswordBody,
AddFiles200,
AddFilesBody,
RemoveFiles200,
RemoveFilesBody,
AddRecipients200,
AddRecipientsBody,
RemoveRecipients200,
RemoveRecipientsBody,
CreateShareAlias200,
CreateShareAliasBody,
GetShareByAlias200,
GetShareByAliasParams,
NotifyRecipients200,
NotifyRecipientsBody,
} from "../../models";
import type { AxiosResponse } from "axios";
export type CreateShareResult = AxiosResponse<CreateShare201>;
export type UpdateShareResult = AxiosResponse<UpdateShare200>;
export type ListUserSharesResult = AxiosResponse<ListUserShares200>;
export type GetShareResult = AxiosResponse<GetShare200>;
export type DeleteShareResult = AxiosResponse<DeleteShare200>;
export type UpdateSharePasswordResult = AxiosResponse<UpdateSharePassword200>;
export type AddFilesResult = AxiosResponse<AddFiles200>;
export type RemoveFilesResult = AxiosResponse<RemoveFiles200>;
export type AddRecipientsResult = AxiosResponse<AddRecipients200>;
export type RemoveRecipientsResult = AxiosResponse<RemoveRecipients200>;
export type CreateShareAliasResult = AxiosResponse<CreateShareAlias200>;
export type GetShareByAliasResult = AxiosResponse<GetShareByAlias200>;
export type NotifyRecipientsResult = AxiosResponse<NotifyRecipients200>;
export type {
CreateShareBody,
UpdateShareBody,
GetShareParams,
UpdateSharePasswordBody,
AddFilesBody,
RemoveFilesBody,
AddRecipientsBody,
RemoveRecipientsBody,
CreateShareAliasBody,
GetShareByAliasParams,
NotifyRecipientsBody,
};

View File

@@ -0,0 +1,126 @@
import type {
RegisterUserResult,
ListUsersResult,
UpdateUserResult,
GetUserByIdResult,
DeleteUserResult,
ActivateUserResult,
DeactivateUserResult,
UpdateUserImageResult,
UploadAvatarResult,
RemoveAvatarResult,
RegisterUserBody,
UpdateUserBody,
UpdateUserImageBody,
UploadAvatarBody,
} from "./types";
import axiosInstance from "@/config/axios";
import type { AxiosRequestConfig } from "axios";
/**
* Register a new user (admin only)
* @summary Register New User
*/
export const registerUser = <TData = RegisterUserResult>(
registerUserBody: RegisterUserBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.post(`/auth/register`, registerUserBody, options);
};
/**
* List all users (admin only)
* @summary List All Users
*/
export const listUsers = <TData = ListUsersResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/users`, options);
};
/**
* Update user data (admin only)
* @summary Update User Data
*/
export const updateUser = <TData = UpdateUserResult>(
updateUserBody: UpdateUserBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.put(`/users`, updateUserBody, options);
};
/**
* Get a user by ID (admin only)
* @summary Get User by ID
*/
export const getUserById = <TData = GetUserByIdResult>(id: string, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.get(`/users/${id}`, options);
};
/**
* Delete a user (admin only)
* @summary Delete User
*/
export const deleteUser = <TData = DeleteUserResult>(id: string, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.delete(`/users/${id}`, options);
};
/**
* Activate a user (admin only)
* @summary Activate User
*/
export const activateUser = <TData = ActivateUserResult>(id: string, options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.patch(`/users/${id}/activate`, undefined, options);
};
/**
* Deactivate a user (admin only)
* @summary Deactivate User
*/
export const deactivateUser = <TData = DeactivateUserResult>(
id: string,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/users/${id}/deactivate`, undefined, options);
};
/**
* Update user profile image (admin only)
* @summary Update User Image
*/
export const updateUserImage = <TData = UpdateUserImageResult>(
id: string,
updateUserImageBody: UpdateUserImageBody,
options?: AxiosRequestConfig
): Promise<TData> => {
return axiosInstance.patch(`/users/${id}/image`, updateUserImageBody, options);
};
/**
* Upload and update user profile image
* @summary Upload user avatar
*/
export const uploadAvatar = <TData = UploadAvatarResult>(
uploadAvatarBody: UploadAvatarBody,
options?: AxiosRequestConfig
): Promise<TData> => {
const formData = new FormData();
if (uploadAvatarBody.file !== undefined) {
formData.append("file", uploadAvatarBody.file as Blob);
}
return axiosInstance.post(`/users/avatar`, formData, {
...options,
headers: {
...options?.headers,
"Content-Type": "multipart/form-data",
},
});
};
/**
* Remove user profile image
* @summary Remove user avatar
*/
export const removeAvatar = <TData = RemoveAvatarResult>(options?: AxiosRequestConfig): Promise<TData> => {
return axiosInstance.delete(`/users/avatar`, options);
};

View File

@@ -0,0 +1,30 @@
import type {
RegisterUser201,
RegisterUserBody,
ListUsers200Item,
UpdateUser200,
UpdateUserBody,
GetUserById200,
DeleteUser200,
ActivateUser200,
DeactivateUser200,
UpdateUserImage200,
UpdateUserImageBody,
UploadAvatar200,
UploadAvatarBody,
RemoveAvatar200,
} from "../../models";
import type { AxiosResponse } from "axios";
export type RegisterUserResult = AxiosResponse<RegisterUser201>;
export type ListUsersResult = AxiosResponse<ListUsers200Item[]>;
export type UpdateUserResult = AxiosResponse<UpdateUser200>;
export type GetUserByIdResult = AxiosResponse<GetUserById200>;
export type DeleteUserResult = AxiosResponse<DeleteUser200>;
export type ActivateUserResult = AxiosResponse<ActivateUser200>;
export type DeactivateUserResult = AxiosResponse<DeactivateUser200>;
export type UpdateUserImageResult = AxiosResponse<UpdateUserImage200>;
export type UploadAvatarResult = AxiosResponse<UploadAvatar200>;
export type RemoveAvatarResult = AxiosResponse<RemoveAvatar200>;
export type { RegisterUserBody, UpdateUserBody, UpdateUserImageBody, UploadAvatarBody };

View File

@@ -0,0 +1,33 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type ActivateUser200 = {
/** User ID */
id: string;
/** User first name */
firstName: string;
/** User last name */
lastName: string;
/** User username */
username: string;
/** User email */
email: string;
/**
* User profile image URL
* @nullable
*/
image: string | null;
/** User is admin */
isAdmin: boolean;
/** User is active */
isActive: boolean;
/** User creation date */
createdAt: string;
/** User last update date */
updatedAt: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type ActivateUser400 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type ActivateUser401 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type ActivateUser403 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
import type { AddFiles200Share } from "./addFiles200Share";
export type AddFiles200 = {
share: AddFiles200Share;
};

View File

@@ -0,0 +1,44 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
import type { AddFiles200ShareAlias } from "./addFiles200ShareAlias";
import type { AddFiles200ShareFilesItem } from "./addFiles200ShareFilesItem";
import type { AddFiles200ShareRecipientsItem } from "./addFiles200ShareRecipientsItem";
import type { AddFiles200ShareSecurity } from "./addFiles200ShareSecurity";
export type AddFiles200Share = {
/** The share ID */
id: string;
/**
* The share name
* @nullable
*/
name: string | null;
/**
* The share description
* @nullable
*/
description: string | null;
/**
* The share expiration date
* @nullable
*/
expiration: string | null;
/** The number of views */
views: number;
/** The share creation date */
createdAt: string;
/** The share update date */
updatedAt: string;
/** The creator ID */
creatorId: string;
security: AddFiles200ShareSecurity;
files: AddFiles200ShareFilesItem[];
recipients: AddFiles200ShareRecipientsItem[];
/** @nullable */
alias: AddFiles200ShareAlias;
};

View File

@@ -0,0 +1,18 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
/**
* @nullable
*/
export type AddFiles200ShareAlias = {
id: string;
alias: string;
shareId: string;
createdAt: string;
updatedAt: string;
} | null;

View File

@@ -0,0 +1,31 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles200ShareFilesItem = {
/** The file ID */
id: string;
/** The file name */
name: string;
/**
* The file description
* @nullable
*/
description: string | null;
/** The file extension */
extension: string;
/** The file size */
size: string;
/** The file object name */
objectName: string;
/** The user ID */
userId: string;
/** The file creation date */
createdAt: string;
/** The file update date */
updatedAt: string;
};

View File

@@ -0,0 +1,18 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles200ShareRecipientsItem = {
/** The recipient ID */
id: string;
/** The recipient email */
email: string;
/** The recipient creation date */
createdAt: string;
/** The recipient update date */
updatedAt: string;
};

View File

@@ -0,0 +1,17 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles200ShareSecurity = {
/**
* The maximum number of views
* @nullable
*/
maxViews: number | null;
/** Whether the share has a password */
hasPassword: boolean;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles400 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles401 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFiles404 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddFilesBody = {
files: string[];
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
import type { AddRecipients200Share } from "./addRecipients200Share";
export type AddRecipients200 = {
share: AddRecipients200Share;
};

View File

@@ -0,0 +1,44 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
import type { AddRecipients200ShareAlias } from "./addRecipients200ShareAlias";
import type { AddRecipients200ShareFilesItem } from "./addRecipients200ShareFilesItem";
import type { AddRecipients200ShareRecipientsItem } from "./addRecipients200ShareRecipientsItem";
import type { AddRecipients200ShareSecurity } from "./addRecipients200ShareSecurity";
export type AddRecipients200Share = {
/** The share ID */
id: string;
/**
* The share name
* @nullable
*/
name: string | null;
/**
* The share description
* @nullable
*/
description: string | null;
/**
* The share expiration date
* @nullable
*/
expiration: string | null;
/** The number of views */
views: number;
/** The share creation date */
createdAt: string;
/** The share update date */
updatedAt: string;
/** The creator ID */
creatorId: string;
security: AddRecipients200ShareSecurity;
files: AddRecipients200ShareFilesItem[];
recipients: AddRecipients200ShareRecipientsItem[];
/** @nullable */
alias: AddRecipients200ShareAlias;
};

View File

@@ -0,0 +1,18 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
/**
* @nullable
*/
export type AddRecipients200ShareAlias = {
id: string;
alias: string;
shareId: string;
createdAt: string;
updatedAt: string;
} | null;

View File

@@ -0,0 +1,31 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients200ShareFilesItem = {
/** The file ID */
id: string;
/** The file name */
name: string;
/**
* The file description
* @nullable
*/
description: string | null;
/** The file extension */
extension: string;
/** The file size */
size: string;
/** The file object name */
objectName: string;
/** The user ID */
userId: string;
/** The file creation date */
createdAt: string;
/** The file update date */
updatedAt: string;
};

View File

@@ -0,0 +1,18 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients200ShareRecipientsItem = {
/** The recipient ID */
id: string;
/** The recipient email */
email: string;
/** The recipient creation date */
createdAt: string;
/** The recipient update date */
updatedAt: string;
};

View File

@@ -0,0 +1,17 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients200ShareSecurity = {
/**
* The maximum number of views
* @nullable
*/
maxViews: number | null;
/** Whether the share has a password */
hasPassword: boolean;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients400 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients401 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipients404 = {
/** Error message */
error: string;
};

View File

@@ -0,0 +1,11 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type AddRecipientsBody = {
emails: string[];
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
import type { BulkUpdateConfigs200ConfigsItem } from "./bulkUpdateConfigs200ConfigsItem";
export type BulkUpdateConfigs200 = {
configs: BulkUpdateConfigs200ConfigsItem[];
};

View File

@@ -0,0 +1,20 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type BulkUpdateConfigs200ConfigsItem = {
/** The config key */
key: string;
/** The config value */
value: string;
/** The config type */
type: string;
/** The config group */
group: string;
/** The config update date */
updatedAt: string;
};

View File

@@ -0,0 +1,12 @@
/**
* Generated by orval v7.5.0 🍺
* Do not edit manually.
* 🌴 Palmr. API
* API documentation for Palmr file sharing system
* OpenAPI spec version: 1.0.0
*/
export type BulkUpdateConfigs400 = {
/** Error message */
error: string;
};

Some files were not shown because too many files have changed in this diff Show More