Files
xSaherelmWorkspace/Documents/Resources/XResourceIDS/Generator/xFrameworkResourceManager.html
T

1303 lines
50 KiB
HTML

<!doctype html>
<html lang="fa" dir="rtl">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>مدیریت منابع زبانی xFramework</title>
<style>
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: "Segoe UI", Tahoma, sans-serif;
background: linear-gradient(135deg, #1e1e2f 0%, #2a2a3e 100%);
color: #eee;
min-height: 100vh;
padding: 20px;
}
header {
text-align: center;
padding: 30px 20px;
background: rgba(255, 255, 255, 0.05);
border-radius: 16px;
margin-bottom: 30px;
backdrop-filter: blur(10px);
}
header h1 {
font-size: 2.2em;
margin-bottom: 10px;
color: #7ec8ff;
}
header p {
opacity: 0.8;
}
header .meta {
margin-top: 12px;
font-size: 0.85em;
opacity: 0.6;
}
.container {
max-width: 1500px;
margin: 0 auto;
}
.section {
background: rgba(255, 255, 255, 0.04);
border-radius: 16px;
padding: 24px;
margin-bottom: 24px;
border: 1px solid rgba(255, 255, 255, 0.08);
}
.section h2 {
margin-bottom: 20px;
color: #7ec8ff;
border-bottom: 2px solid rgba(126, 200, 255, 0.3);
padding-bottom: 10px;
}
/* Source Selection */
.source-tabs {
display: flex;
gap: 8px;
margin-bottom: 20px;
background: rgba(0, 0, 0, 0.2);
padding: 6px;
border-radius: 10px;
}
.source-tab {
flex: 1;
padding: 12px 16px;
background: rgba(255, 255, 255, 0.05);
border-radius: 8px;
cursor: pointer;
text-align: center;
font-weight: 600;
transition: all 0.2s;
border: 1px solid transparent;
font-size: 14px;
}
.source-tab:hover {
background: rgba(255, 255, 255, 0.1);
}
.source-tab.active {
background: rgba(126, 200, 255, 0.15);
border-color: rgba(126, 200, 255, 0.4);
color: #7ec8ff;
}
.source-content {
display: none;
}
.source-content.active {
display: block;
}
/* Upload */
.upload-section {
background: rgba(0, 0, 0, 0.2);
border: 2px dashed rgba(126, 200, 255, 0.3);
border-radius: 12px;
padding: 24px;
text-align: center;
transition: all 0.3s;
}
.upload-section:hover {
border-color: rgba(126, 200, 255, 0.6);
background: rgba(0, 0, 0, 0.3);
}
.upload-btn {
display: inline-block;
padding: 10px 24px;
background: #7ec8ff;
color: #1e1e2f;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
transition: all 0.2s;
}
.upload-btn:hover {
background: #5ab0f0;
transform: translateY(-2px);
}
.upload-status {
margin-top: 12px;
font-size: 13px;
min-height: 18px;
}
.upload-status.success {
color: #4caf50;
}
.upload-status.error {
color: #f44336;
}
/* Language Management */
.lang-list {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-bottom: 16px;
}
.lang-chip {
background: rgba(126, 200, 255, 0.1);
border: 1px solid rgba(126, 200, 255, 0.3);
padding: 8px 16px;
border-radius: 20px;
font-size: 13px;
display: flex;
align-items: center;
gap: 8px;
}
.lang-chip .remove-lang {
cursor: pointer;
color: #f44336;
font-weight: bold;
margin-right: 4px;
}
.add-lang-form {
display: flex;
gap: 8px;
flex-wrap: wrap;
margin-top: 12px;
padding: 12px;
background: rgba(0, 0, 0, 0.2);
border-radius: 8px;
}
.add-lang-form input,
.add-lang-form select {
padding: 8px 12px;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 6px;
color: #fff;
font-size: 13px;
flex: 1;
min-width: 120px;
}
/* Identifier Editor Layout */
.editor-layout {
display: grid;
grid-template-columns: 350px 1fr;
gap: 20px;
}
@media (max-width: 900px) {
.editor-layout {
grid-template-columns: 1fr;
}
}
/* Identifier List */
.id-list-container {
max-height: 500px;
overflow-y: auto;
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.id-list-container::-webkit-scrollbar {
width: 8px;
}
.id-list-container::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
border-radius: 4px;
}
.id-list-container::-webkit-scrollbar-thumb {
background: rgba(126, 200, 255, 0.4);
border-radius: 4px;
}
.id-item {
padding: 10px 14px;
border-bottom: 1px solid rgba(255, 255, 255, 0.05);
cursor: pointer;
transition: background 0.2s;
display: flex;
justify-content: space-between;
align-items: center;
font-size: 13px;
font-family: monospace;
}
.id-item:hover {
background: rgba(126, 200, 255, 0.1);
}
.id-item.active {
background: rgba(126, 200, 255, 0.2);
border-right: 3px solid #7ec8ff;
}
.id-item .warning-badge {
background: #ff9800;
color: #000;
font-size: 10px;
padding: 2px 6px;
border-radius: 4px;
font-weight: bold;
}
/* Edit Form */
.edit-form {
background: rgba(0, 0, 0, 0.2);
border-radius: 10px;
padding: 20px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.edit-row {
margin-bottom: 16px;
}
.edit-row label {
display: block;
margin-bottom: 6px;
color: #a8d0ff;
font-size: 13px;
font-weight: 600;
}
.edit-row input,
.edit-row textarea {
width: 100%;
padding: 10px 12px;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 6px;
color: #fff;
font-size: 14px;
font-family: "Segoe UI", Tahoma, sans-serif;
}
.edit-row input:focus,
.edit-row textarea:focus {
outline: none;
border-color: #7ec8ff;
background: rgba(255, 255, 255, 0.12);
}
.edit-row textarea {
min-height: 80px;
resize: vertical;
}
/* JSON Output */
.json-output {
background: #0d1117;
border-radius: 8px;
padding: 14px;
max-height: 380px;
overflow: auto;
font-family: "Consolas", monospace;
font-size: 11px;
color: #c9d1d9;
border: 1px solid rgba(255, 255, 255, 0.1);
direction: ltr;
text-align: left;
white-space: pre;
}
.json-output::-webkit-scrollbar {
width: 8px;
height: 8px;
}
.json-output::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.2);
}
.json-output::-webkit-scrollbar-thumb {
background: rgba(126, 200, 255, 0.4);
border-radius: 4px;
}
.tabs {
display: flex;
gap: 4px;
margin-bottom: 12px;
}
.tab {
padding: 8px 16px;
background: rgba(255, 255, 255, 0.05);
border-radius: 6px 6px 0 0;
cursor: pointer;
border: 1px solid transparent;
font-size: 13px;
font-weight: 500;
}
.tab.active {
background: rgba(126, 200, 255, 0.15);
border-color: rgba(126, 200, 255, 0.3);
color: #7ec8ff;
}
/* Action Buttons */
.action-buttons {
display: flex;
gap: 10px;
flex-wrap: wrap;
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.btn {
padding: 10px 20px;
border: none;
border-radius: 8px;
cursor: pointer;
font-weight: 600;
font-size: 13px;
transition: all 0.2s;
}
.btn-primary {
background: #7ec8ff;
color: #1e1e2f;
}
.btn-primary:hover {
background: #5ab0f0;
}
.btn-success {
background: #4caf50;
color: #fff;
}
.btn-success:hover {
background: #3d9140;
}
.btn-warning {
background: #ff9800;
color: #fff;
}
.btn-warning:hover {
background: #e08600;
}
.btn-info {
background: #2196f3;
color: #fff;
}
.btn-info:hover {
background: #1976d2;
}
.btn-danger {
background: #f44336;
color: #fff;
}
.btn-danger:hover {
background: #d32f2f;
}
.search-box {
width: 100%;
padding: 10px 14px;
background: rgba(255, 255, 255, 0.08);
border: 1px solid rgba(255, 255, 255, 0.15);
border-radius: 8px;
color: #fff;
font-size: 14px;
margin-bottom: 12px;
}
.search-box:focus {
outline: none;
border-color: #7ec8ff;
}
</style>
</head>
<body>
<header>
<h1>🌐 مدیریت منابع زبانی xFramework</h1>
<p>
مدیریت، ویرایش و اعتبارسنجی فایل‌های ترجمه برای برنامه‌های کاربردی مبتنی
بر xFramework
</p>
<div class="meta">
توسعه‌دهنده: هادی خزاعی اصل | شرکت: فن آوران ساحر علم | تاریخ: ۱ شهریور
۱۴۰۵
</div>
</header>
<div class="container">
<!-- Source Section -->
<div class="section">
<h2>📂 منبع داده‌ها</h2>
<div class="source-tabs">
<div class="source-tab active" onclick="switchSource('default')">
📚 منابع پیش‌فرض سیستم
</div>
<div class="source-tab" onclick="switchSource('upload')">
📁 بارگذاری فایل JSON
</div>
</div>
<div id="source-default" class="source-content active">
<p style="opacity: 0.7; font-size: 14px; padding: 10px">
✅ در حال حاضر از منابع پیش‌فرض xFramework استفاده می‌شود. می‌توانید
مستقیماً ویرایش را شروع کنید.
</p>
</div>
<div id="source-upload" class="source-content">
<div class="upload-section">
<label for="jsonFileInput" class="upload-btn"
>📁 انتخاب فایل JSON منابع</label
>
<input
type="file"
id="jsonFileInput"
accept=".json"
style="display: none"
onchange="handleFileUpload(event)"
/>
<div id="uploadStatus" class="upload-status"></div>
</div>
</div>
</div>
<!-- Language Management Section -->
<div class="section">
<h2>🌍 مدیریت زبان‌ها</h2>
<div class="lang-list" id="langList"></div>
<div class="add-lang-form">
<input
type="text"
id="newLangName"
placeholder="نام زبان (مثال: arabic)"
/>
<input
type="text"
id="newLangLocale"
placeholder="لوکال (مثال: ar-SA)"
/>
<input
type="text"
id="newLangCode"
placeholder="کد زبان (مثال: ar)"
/>
<select id="newLangDir">
<option value="rtl">RTL</option>
<option value="ltr">LTR</option>
</select>
<button class="btn btn-primary" onclick="addNewLanguage()">
➕ افزودن زبان
</button>
</div>
</div>
<!-- Identifier Editor Section -->
<div class="section">
<h2>✏️ ویرایش شناسه‌ها و ترجمه‌ها</h2>
<div class="editor-layout">
<!-- Left: Identifier List -->
<div>
<input
type="text"
class="search-box"
id="idSearch"
placeholder="🔍 جستجوی شناسه..."
oninput="renderIdList()"
/>
<div class="id-list-container" id="idListContainer"></div>
<button
class="btn btn-info"
style="width: 100%; margin-top: 12px"
onclick="addNewIdentifier()"
>
➕ ایجاد شناسه جدید
</button>
</div>
<!-- Right: Edit Form -->
<div class="edit-form" id="editForm">
<p style="opacity: 0.5; text-align: center; padding: 40px">
یک شناسه را از لیست سمت راست انتخاب کنید تا ترجمه‌های آن را ویرایش
کنید.
</p>
</div>
</div>
</div>
<!-- JSON Output & Actions -->
<div class="section">
<h2>📄 خروجی JSON</h2>
<div class="tabs">
<div class="tab active" onclick="switchJsonTab('full')" id="tab-full">
📄 Full JSON
</div>
</div>
<pre class="json-output" id="jsonOutput"></pre>
<div class="action-buttons">
<button class="btn btn-success" onclick="downloadJSON()">
⬇️ دانلود JSON
</button>
<button class="btn btn-warning" onclick="copyJSON()">
📋 کپی JSON
</button>
<button class="btn btn-danger" onclick="resetToDefault()">
🔄 بازنشانی به پیش‌فرض
</button>
</div>
</div>
</div>
<script>
// ============ Default Data ============
const DEFAULT_RESOURCES = [
{
name: "persian",
locale: "fa-IR",
language: "fa",
direction: "rtl",
resources: [
{ id: "app_name", value: "ساحر علم" },
{ id: "company", value: "فن آوران ساحر علم" },
{ id: "id", value: "شناسه" },
{ id: "file_name", value: "نام فایل" },
{ id: "error", value: "خطا" },
{ id: "required", value: "الزامی است." },
{ id: "loading", value: "بارگزاری" },
{ id: "username", value: "نام کاربری" },
{ id: "password", value: "کلمه عبور" },
{ id: "first_name", value: "نام" },
{ id: "last_name", value: "نام خانوادگی" },
{ id: "verified", value: "تایید شده" },
{ id: "unverified", value: "تایید نشده" },
{ id: "thumbnail", value: "پیش نمایش" },
{ id: "language", value: "زبان" },
{ id: "take_screenshot", value: "تصویر برداری ازمحیط" },
{ id: "enable_capture_mode", value: "فعالسازی حالت تصویر برداری" },
{
id: "disable_capture_mode",
value: "غیرفعالسازی حالت تصویر برداری",
},
{ id: "be", value: "باشد" },
{ id: "not_to_be", value: "نباشد" },
{ id: "enabled", value: "فعال" },
{ id: "disabled", value: "غیر فعال" },
{ id: "banned", value: "مسدود" },
{ id: "un_banned", value: "غیر مسدود" },
{ id: "audio", value: "صوت" },
{ id: "video", value: "فیلم" },
{ id: "cover_image", value: "تصویر" },
{ id: "image", value: "تصویر" },
{ id: "avatar", value: "شکلک" },
{ id: "unknown", value: "ناشناس" },
{ id: "location", value: "موقعیت جغرافیای" },
{ id: "are_you_sure", value: "اطمینان دارید ؟" },
{ id: "success_msg", value: "عملیات با موفقیت انجام شد" },
{
id: "locked_msg",
value:
"برای ترک این صفحه باید فعالیت جاری را لغو کرده و یا به اتمام برسانید",
},
{ id: "empty_content", value: "خالی است" },
{ id: "no_item", value: "محتوایی ثبت نشده است" },
{ id: "drag_drop_here", value: "محل رها کردن فایل" },
{ id: "map_dialog_title", value: "نمایش موقعیت مکانی" },
{ id: "map_dialog_select_title", value: "انتخاب موقعیت جغرافیایی" },
{ id: "color_picker_dialog_title", value: "انتخاب رنگ" },
{ id: "dismiss", value: "رد کردن" },
{ id: "accept", value: "می پذیرم" },
{ id: "ok", value: "بسیار خب" },
{ id: "save", value: "ذخیره" },
{ id: "cancel", value: "لغو" },
{ id: "retry", value: "سعی مجدد" },
{ id: "edit", value: "ویرایش" },
{ id: "reset", value: "باز نشاندن" },
{ id: "change", value: "تغییر" },
{ id: "start", value: "آغاز" },
{ id: "yes", value: "بله" },
{ id: "no", value: "خیر" },
{ id: "verify", value: "تایید کردن" },
{ id: "confirm", value: "تاییدیه" },
{ id: "crop", value: "برش" },
{ id: "clear", value: "پاک کردن" },
{ id: "set", value: "تنظیم" },
{ id: "select", value: "انتخاب" },
{ id: "send", value: "ارسال" },
{ id: "show", value: "نمایش دادن" },
{ id: "hide", value: "پنهان کردن" },
{ id: "search", value: "جستجو" },
{ id: "delete", value: "حذف" },
{ id: "clone", value: "نمونه گیری" },
{ id: "select_all", value: "انتخاب همه" },
{ id: "select_file", value: "انتخاب فایل(ها)" },
{ id: "select_all_group", value: "انتخاب همه موارد فیلتر شده" },
{ id: "deselect_all", value: "لغو همه انتخاب ها" },
{
id: "deselect_all_group",
value: "لغو انتخاب همه موارد فیلتر شده",
},
{ id: "inverse_selection", value: "انتخاب معکوس" },
{ id: "selected_location", value: "انتخاب محل" },
{ id: "preset_colors", value: "رنگ های پیش فرض" },
{ id: "copy_to_clipboard", value: "ثبت در حافظه موقت" },
{ id: "color", value: "رنگ" },
{ id: "colors", value: "رنگها" },
{ id: "upload", value: "بارگزاری" },
{ id: "import", value: "وارد کردن" },
{ id: "continue", value: "ادامه" },
{ id: "finish", value: "پایان" },
{ id: "enable", value: "فعال" },
{ id: "disable", value: "غیر فعال" },
{ id: "all", value: "همه" },
{ id: "new", value: "جدید" },
{ id: "add", value: "افزودن" },
{ id: "update", value: "بروز رسانی" },
{ id: "details", value: "جزئیات" },
{ id: "translation", value: "ترجمه" },
{ id: "download", value: "دریافت" },
{ id: "list", value: "فهرست" },
{ id: "options", value: "انتخاب ها" },
{ id: "descriptions", value: "توضیحات" },
{ id: "type", value: "نوع" },
{ id: "media", value: "رسانه" },
{ id: "medias", value: "رسانه ها" },
{ id: "summary", value: "خلاصه" },
{ id: "go", value: "رفتن" },
{ id: "input", value: "ورود" },
{ id: "preview", value: "پیش نمایش" },
{ id: "close", value: "بستن" },
{ id: "undo", value: "لغو کردن" },
{ id: "redo", value: "انجام دوباره" },
{ id: "refresh", value: "بازیابی" },
{ id: "submit", value: "ثبت" },
{ id: "first", value: "نخستین" },
{ id: "last", value: "آخرین" },
{ id: "previous", value: "قبلی" },
{ id: "next", value: "بعدی" },
{ id: "back", value: "بازگشت" },
{ id: "x_markdown_preview", value: "پیش نمایش" },
{ id: "x_markdown_image", value: "تصویر" },
{ id: "x_markdown_link", value: "پیوند" },
{ id: "x_markdown_ol", value: "فهرست ترتیبی" },
{ id: "x_markdown_ul", value: "فهرست بدون ترتیب" },
{ id: "x_markdown_quote", value: "نقل قول" },
{ id: "x_markdown_code", value: "کد منبع" },
{ id: "x_markdown_heading", value: "عنوان" },
{ id: "x_markdown_italic", value: "ایتالیک" },
{ id: "x_markdown_bold", value: "پر رنگ" },
{ id: "x_markdown_guide", value: "راهنمای نگارش" },
{ id: "theme", value: "پوسته" },
{ id: "theme_mode", value: "حالت نمایشی" },
{ id: "theme_dark", value: "تیره" },
{ id: "theme_light", value: "روشن" },
{ id: "theme_name", value: "نام پوسته" },
{ id: "theme_name_description", value: "نام پوسته را وارد کنید" },
{ id: "theme_clone_title", value: "نمونه گیری از پوسته" },
{ id: "input_color_title", value: "تعیین رنگ" },
{ id: "input_color_description", value: "مقدار رنگ را وارد کنید" },
{ id: "ide_mode", value: "نوع کد" },
{ id: "ide_format", value: "حالت دهی کد" },
{ id: "print", value: "چاپ" },
{ id: "export_png", value: "خروجی PNG" },
{ id: "export_svg", value: "خروجی SVG" },
{ id: "export_csv", value: "خروجی CSV" },
{ id: "zoom_in", value: "بزرگنمایی" },
{ id: "zoom_out", value: "کوچک نمایی" },
{ id: "zoom_selection", value: "بزرگنمایی ناحیه" },
{ id: "x_axis", value: "محور افقی" },
{ id: "y_axis", value: "محور عمودی" },
{ id: "xy_axis", value: "محورهای عمودی و افقی" },
{ id: "pan", value: "حرکت آزاد" },
{ id: "full_screen", value: "حالت تمام صفحه" },
{ id: "ex_100", value: "داده نا معتبر" },
{ id: "ex_101", value: "تاریخ نامعتبر" },
{ id: "ex_102", value: "درخواست اشتباه" },
{ id: "ex_103", value: "ورودی نامعتبر" },
{ id: "ex_104", value: "پیام نامعتبر" },
{ id: "ex_105", value: "نشانه نامعتبر" },
{ id: "ex_106", value: "کد اععتبارسنجی نامعتبر" },
{ id: "ex_107", value: "پست الکترونیک نامعتبر" },
{ id: "ex_108", value: "شماره تلفن همراه نامعتبر" },
{ id: "ex_109", value: "کلمه عبور نامعتبر" },
{ id: "ex_110", value: "آدرس اینترنتی نامعتبر" },
{ id: "ex_111", value: "دستگاه نامعتبر" },
{ id: "ex_112", value: "تصویر پروفایل نامعتبر" },
{ id: "ex_113", value: "فایل نامعتبر" },
{ id: "ex_114", value: "نام کاربری نامعتبر" },
{ id: "ex_200", value: "یافت نشد" },
{ id: "ex_201", value: "عدم تایید جواز" },
{ id: "ex_202", value: "سطح دسترسی نامعتبر" },
{ id: "ex_203", value: "غیر قابل نمایش" },
{ id: "ex_300", value: "حساب کاربری قفل شده است" },
{ id: "ex_301", value: "خطا در ورود" },
{ id: "ex_302", value: "کاربر قبلا ثبت نام کرده است" },
{ id: "ex_303", value: "کاربر غیرفعال است" },
{ id: "ex_304", value: "دستگاه شما قفل شده است تا : (0)" },
{
id: "ex_305",
value: "امکان درخواست کد اعتبارسنجی وجود ندارد تا : (0)",
},
{ id: "ex_306", value: "کلمه عبورها یکسان هستند" },
{ id: "ex_307", value: "شماره های تلفن یکسان هستند" },
{ id: "ex_308", value: "آدرس های پست الکترونیک یکسان هستند" },
{ id: "ex_309", value: "شماره تلفن قبلا ثبت شده است" },
{ id: "ex_310", value: "پست الکترونیک قبلا ثبت شده است" },
{ id: "ex_311", value: "تلفن همراه تایید نشده است" },
{ id: "ex_312", value: "پست الکترونیک تایید نشده است" },
{ id: "ex_313", value: "مطلب ممنوعه" },
{ id: "ex_314", value: "کاربر ممنوعه" },
{ id: "ex_400", value: "خطای نا شناخته" },
{ id: "ex_401", value: "مورد تکراری" },
{ id: "ex_402", value: "شکست عملیات" },
{ id: "ex_403", value: "تاریخ مصرف منقضی شده است" },
{ id: "ex_404", value: "غیر قابل اسفاده" },
{ id: "ex_405", value: "تعداد برچسب ها بیش از جد مجاز است" },
{ id: "ex_406", value: "اتمام مهلت زمانی" },
{ id: "ex_500", value: "پرونده خالی است" },
{ id: "ex_501", value: "اندازه بیش از حد مجاز" },
{ id: "ex_502", value: "گونه نامعتبر فایل" },
{ id: "ex_503", value: "تعداد رسانه ها بیش از حد مجاز است" },
{ id: "ex_600", value: "پیکربندی اشتباه" },
{ id: "ex_601", value: "خطا در پیکربندی سامانه ذخیره سازی" },
{ id: "ex_602", value: "خطا در پیکربندی سامانه ذخیره سازی" },
{ id: "ex_900", value: "تعداد فایل ها بیش از حد مجاز است" },
{ id: "ex_901", value: "مجموع اندازه فایل ها کمتر از حد مجاز است" },
{ id: "ex_902", value: "مجموع اندازه فایل ها بیش از حد مجاز است" },
{ id: "ex_903", value: "شرایط و ضوابط باید پذیرفته شوند" },
{ id: "ex_904", value: "عدم پشتیبانی از سیستم موقعیت یاب" },
{
id: "ex_905",
value: "مجوز دسترسی به موقعیت خود را صادر نکرده اید",
},
{
id: "ex_906",
value: "دسترسی به موقعیت جغرافیایی امکان پذیر نیست",
},
{ id: "ex_907", value: "عدم پشتیبانی از سیستم ذخیره سازی" },
{
id: "ex_908",
value: "برای دسترسی به محتوا باید از سامانه خارج شوید",
},
{ id: "ex_909", value: "زبان انتخاب شده نامعتبر است" },
{ id: "ex_910", value: "داده نامعتبر برای انتخاب کاربر" },
],
},
{
name: "english",
locale: "en-US",
language: "en",
direction: "ltr",
resources: [
{ id: "app_name", value: "SaherElm" },
{ id: "company", value: "SaherElm IT Center" },
{ id: "id", value: "ID" },
{ id: "file_name", value: "File Name" },
{ id: "error", value: "Error" },
{ id: "required", value: "required" },
{ id: "loading", value: "loading" },
{ id: "username", value: "Username" },
{ id: "password", value: "Password" },
{ id: "first_name", value: "Firstname" },
{ id: "last_name", value: "Lastname" },
{ id: "verified", value: "Verified" },
{ id: "unverified", value: "Unverified" },
{ id: "thumbnail", value: "Thumbnail" },
{ id: "language", value: "Language" },
{ id: "take_screenshot", value: "Take Screenshot" },
{ id: "enable_capture_mode", value: "Enable Capture Mode" },
{ id: "disable_capture_mode", value: "Disable Capture Mode" },
{ id: "be", value: "Be" },
{ id: "not_to_be", value: "Not to be" },
{ id: "enabled", value: "Enabled" },
{ id: "disabled", value: "Disabled" },
{ id: "banned", value: "Banned" },
{ id: "un_banned", value: "UnBanned" },
{ id: "audio", value: "Audio" },
{ id: "video", value: "Video" },
{ id: "cover_image", value: "Cover Image" },
{ id: "image", value: "Image" },
{ id: "avatar", value: "Avatar" },
{ id: "unknown", value: "Unknown" },
{ id: "location", value: "Location" },
{ id: "are_you_sure", value: "Are You Sure ?" },
{ id: "success_msg", value: "Operation done Successfully ..." },
{
id: "locked_msg",
value: "You have to finish/cancel current proccess for leaving",
},
{ id: "empty_content", value: "Empty" },
{ id: "no_item", value: "there is no Content" },
{ id: "drag_drop_here", value: "Drop File Here" },
{ id: "map_dialog_title", value: "Show Location" },
{ id: "map_dialog_select_title", value: "Select Location" },
{ id: "color_picker_dialog_title", value: "Select Color" },
{ id: "dismiss", value: "dismiss" },
{ id: "accept", value: "Accept" },
{ id: "ok", value: "Ok" },
{ id: "save", value: "Save" },
{ id: "cancel", value: "Cancel" },
{ id: "retry", value: "Retry" },
{ id: "edit", value: "Edit" },
{ id: "reset", value: "Reset" },
{ id: "change", value: "Change" },
{ id: "start", value: "Start" },
{ id: "yes", value: "Yes" },
{ id: "no", value: "No" },
{ id: "verify", value: "Verify" },
{ id: "confirm", value: "Confirm" },
{ id: "crop", value: "Crop" },
{ id: "clear", value: "Clear" },
{ id: "set", value: "Set" },
{ id: "select", value: "Select" },
{ id: "send", value: "Send" },
{ id: "show", value: "Show" },
{ id: "hide", value: "Hide" },
{ id: "search", value: "Search" },
{ id: "delete", value: "Delete" },
{ id: "clone", value: "Clone" },
{ id: "select_all", value: "Select All" },
{ id: "select_file", value: "Select File(s)" },
{ id: "select_all_group", value: "Select All Filtered Items" },
{ id: "deselect_all", value: "Deselect All" },
{ id: "deselect_all_group", value: "Deselect All Filtered Items" },
{ id: "inverse_selection", value: "Inverse Selection" },
{ id: "selected_location", value: "Selected Location" },
{ id: "preset_colors", value: "Preset Colors" },
{ id: "copy_to_clipboard", value: "Copy to Clipboard" },
{ id: "color", value: "Color" },
{ id: "colors", value: "Colors" },
{ id: "upload", value: "Upload" },
{ id: "import", value: "Import" },
{ id: "continue", value: "Continue" },
{ id: "finish", value: "Finish" },
{ id: "enable", value: "Enable" },
{ id: "disable", value: "Disable" },
{ id: "all", value: "All" },
{ id: "new", value: "New" },
{ id: "add", value: "Add" },
{ id: "update", value: "Update" },
{ id: "details", value: "Details" },
{ id: "translation", value: "Translation" },
{ id: "download", value: "Download" },
{ id: "list", value: "List" },
{ id: "options", value: "Options" },
{ id: "descriptions", value: "Description" },
{ id: "type", value: "Type" },
{ id: "media", value: "Media" },
{ id: "medias", value: "Medias" },
{ id: "summary", value: "Summary" },
{ id: "go", value: "Go" },
{ id: "input", value: "Input" },
{ id: "preview", value: "Preview" },
{ id: "close", value: "Close" },
{ id: "undo", value: "Undo" },
{ id: "redo", value: "Redo" },
{ id: "refresh", value: "Refresh" },
{ id: "submit", value: "Submit" },
{ id: "first", value: "First" },
{ id: "last", value: "Last" },
{ id: "previous", value: "Previous" },
{ id: "next", value: "Next" },
{ id: "back", value: "Back" },
{ id: "x_markdown_preview", value: "Preview" },
{ id: "x_markdown_image", value: "Image" },
{ id: "x_markdown_link", value: "Link" },
{ id: "x_markdown_ol", value: "Ordered List" },
{ id: "x_markdown_ul", value: "Unordered List" },
{ id: "x_markdown_quote", value: "Quote" },
{ id: "x_markdown_code", value: "Code" },
{ id: "x_markdown_heading", value: "Heading" },
{ id: "x_markdown_italic", value: "Italic" },
{ id: "x_markdown_bold", value: "Bold" },
{ id: "x_markdown_guide", value: "Markdown Guide" },
{ id: "theme", value: "Theme" },
{ id: "theme_mode", value: "Theme Mode" },
{ id: "theme_dark", value: "Dark" },
{ id: "theme_light", value: "Light" },
{ id: "theme_name", value: "Theme Name" },
{ id: "theme_name_description", value: "Enter Theme name" },
{ id: "theme_clone_title", value: "Theme Cloning" },
{ id: "input_color_title", value: "Color Value" },
{ id: "input_color_description", value: "input color value" },
{ id: "ide_mode", value: "Code Style" },
{ id: "ide_format", value: "Code Formatting" },
{ id: "print", value: "Print" },
{ id: "export_png", value: "Export PNG" },
{ id: "export_svg", value: "Export SVG" },
{ id: "export_csv", value: "Export CSV" },
{ id: "zoom_in", value: "Zoom In" },
{ id: "zoom_out", value: "Zoom Out" },
{ id: "zoom_selection", value: "Zoom Selection" },
{ id: "x_axis", value: "X Axis" },
{ id: "y_axis", value: "Y Axis" },
{ id: "xy_axis", value: "XY Axis" },
{ id: "pan", value: "Pan" },
{ id: "full_screen", value: "Full Screen" },
{ id: "ex_100", value: "Invalid Data ..." },
{ id: "ex_101", value: "Invalid Date ..." },
{ id: "ex_102", value: "Bad Request ..." },
{ id: "ex_103", value: "Invalid Args ..." },
{ id: "ex_104", value: "Invalid Message ..." },
{ id: "ex_105", value: "Invalid Token ..." },
{ id: "ex_106", value: "Invalid Verification Code ..." },
{ id: "ex_107", value: "Invalid Email Address ..." },
{ id: "ex_108", value: "Invalid Mobile Number ..." },
{ id: "ex_109", value: "Invalid Password ..." },
{ id: "ex_110", value: "Invalid URL ..." },
{ id: "ex_111", value: "Invalid Device ..." },
{ id: "ex_112", value: "Invalid Profile Image ..." },
{ id: "ex_113", value: "Invalid File ..." },
{ id: "ex_114", value: "Invalid Username ..." },
{ id: "ex_200", value: "Not Found ..." },
{ id: "ex_201", value: "Not Allowed ..." },
{ id: "ex_202", value: "Not Authorized ..." },
{ id: "ex_203", value: "Not Visible ..." },
{ id: "ex_300", value: "Account Locked out ..." },
{ id: "ex_301", value: "Login Failed ..." },
{ id: "ex_302", value: "User Registered Before ..." },
{ id: "ex_303", value: "User Disabled ..." },
{ id: "ex_304", value: "Device Banned Until:(0)" },
{
id: "ex_305",
value: "You can not Request Verification code Until:(0)",
},
{ id: "ex_306", value: "Passwords Same ..." },
{ id: "ex_307", value: "Mobiles Same ..." },
{ id: "ex_308", value: "Emails Same ..." },
{ id: "ex_309", value: "Mobile In Used ..." },
{ id: "ex_310", value: "Email In Used ..." },
{ id: "ex_311", value: "Mobile Not Confirmed ..." },
{ id: "ex_312", value: "Email Not Confirmed ..." },
{ id: "ex_313", value: "Post Banned ..." },
{ id: "ex_314", value: "User Banned ..." },
{ id: "ex_400", value: "Unknown Error ..." },
{ id: "ex_401", value: "Duplicate ..." },
{ id: "ex_402", value: "Action Failed ..." },
{ id: "ex_403", value: "Expired Date ..." },
{ id: "ex_404", value: "Unavailable ..." },
{ id: "ex_405", value: "Max Allowed Tag Exceeded ..." },
{ id: "ex_406", value: "Timeout ..." },
{ id: "ex_500", value: "Empty File ..." },
{ id: "ex_501", value: "max File size exceeded ..." },
{ id: "ex_502", value: "Unsupported File Type ..." },
{ id: "ex_503", value: "Max Allowed Media Exceeded ..." },
{ id: "ex_600", value: "Invalid Configuration ..." },
{
id: "ex_601",
value: "Storage Service Initiallization Failed ...",
},
{
id: "ex_602",
value: "Message Service Initialization Failed ...",
},
{ id: "ex_900", value: "Max Allowed Files Exceeded ..." },
{ id: "ex_901", value: "Min Files Size Exceeded ..." },
{ id: "ex_902", value: "Max Files Size Exceeded ..." },
{ id: "ex_903", value: "Must Accept Terms And Conditions ..." },
{
id: "ex_904",
value: "Browser does not support Location Services ...",
},
{
id: "ex_905",
value: "You have rejected access to your Location ...",
},
{ id: "ex_906", value: "Unable to determine your Location ..." },
{
id: "ex_907",
value: "Browser does not support Storage Services ...",
},
{ id: "ex_908", value: "Must Logout to access content ..." },
{ id: "ex_909", value: "Invalid Locale ..." },
{ id: "ex_910", value: "Invalid User Selector ..." },
],
},
];
// ============ State ============
let resourcesData = JSON.parse(JSON.stringify(DEFAULT_RESOURCES));
let selectedId = null;
let jsonTab = "full";
// ============ Initialization ============
function init() {
renderLanguages();
renderIdList();
renderJson();
}
// ============ Language Management ============
function renderLanguages() {
const container = document.getElementById("langList");
container.innerHTML = "";
resourcesData.forEach((lang, index) => {
const chip = document.createElement("div");
chip.className = "lang-chip";
chip.innerHTML = `
<strong>${lang.name}</strong> (${lang.locale})
${resourcesData.length > 1 ? `<span class="remove-lang" onclick="removeLanguage(${index})" title="حذف زبان">✕</span>` : ""}
`;
container.appendChild(chip);
});
}
function addNewLanguage() {
const name = document.getElementById("newLangName").value.trim();
const locale = document.getElementById("newLangLocale").value.trim();
const code = document.getElementById("newLangCode").value.trim();
const dir = document.getElementById("newLangDir").value;
if (!name || !locale || !code) {
alert("لطفاً تمام فیلدهای زبان جدید را پر کنید.");
return;
}
if (resourcesData.find((l) => l.name === name)) {
alert("زبانی با این نام از قبل وجود دارد.");
return;
}
// Create empty resources for all existing IDs
const allIds = getAllIdentifiers();
const newResources = allIds.map((id) => ({ id, value: "" }));
resourcesData.push({
name,
locale,
language: code,
direction: dir,
resources: newResources,
});
document.getElementById("newLangName").value = "";
document.getElementById("newLangLocale").value = "";
document.getElementById("newLangCode").value = "";
renderLanguages();
renderIdList();
renderJson();
alert(`زبان ${name} با موفقیت اضافه شد.`);
}
function removeLanguage(index) {
if (
confirm(`آیا از حذف زبان ${resourcesData[index].name} اطمینان دارید؟`)
) {
resourcesData.splice(index, 1);
renderLanguages();
renderIdList();
renderJson();
if (selectedId) selectIdentifier(selectedId);
}
}
// ============ Identifier Management ============
function getAllIdentifiers() {
const ids = new Set();
resourcesData.forEach((lang) => {
lang.resources.forEach((res) => ids.add(res.id));
});
return Array.from(ids).sort();
}
function renderIdList() {
const container = document.getElementById("idListContainer");
const search = document.getElementById("idSearch").value.toLowerCase();
container.innerHTML = "";
const allIds = getAllIdentifiers();
const filteredIds = allIds.filter((id) =>
id.toLowerCase().includes(search),
);
filteredIds.forEach((id) => {
const item = document.createElement("div");
item.className = `id-item ${selectedId === id ? "active" : ""}`;
// Check for missing or empty translations
let hasMissing = false;
resourcesData.forEach((lang) => {
const res = lang.resources.find((r) => r.id === id);
if (!res || !res.value.trim()) {
hasMissing = true;
}
});
item.innerHTML = `
<span>${id}</span>
${hasMissing ? '<span class="warning-badge" title="فاقد ترجمه در یک یا چند زبان">⚠️</span>' : ""}
`;
item.onclick = () => selectIdentifier(id);
container.appendChild(item);
});
}
function selectIdentifier(id) {
selectedId = id;
renderIdList(); // to update active state
const formContainer = document.getElementById("editForm");
formContainer.innerHTML = `<h3 style="margin-bottom: 16px; color: #7ec8ff;">ویرایش شناسه: <span style="font-family: monospace; color: #fff;">${id}</span></h3>`;
resourcesData.forEach((lang, langIndex) => {
const res = lang.resources.find((r) => r.id === id);
const currentValue = res ? res.value : "";
const row = document.createElement("div");
row.className = "edit-row";
row.innerHTML = `
<label>${lang.name} (${lang.locale}) ${!res ? '<span style="color:#f44336">(جدید - فاقد مقدار)</span>' : ""}</label>
<textarea
data-lang-index="${langIndex}"
data-res-id="${id}"
oninput="updateTranslation(this)"
placeholder="ترجمه را وارد کنید..."
>${currentValue}</textarea>
`;
formContainer.appendChild(row);
});
const addBtn = document.createElement("button");
addBtn.className = "btn btn-primary";
addBtn.style.width = "100%";
addBtn.style.marginTop = "12px";
addBtn.textContent = "💾 ذخیره تغییرات و به‌روزرسانی JSON";
addBtn.onclick = () => {
renderJson();
renderIdList(); // update warning badges
alert("تغییرات با موفقیت ذخیره شد.");
};
formContainer.appendChild(addBtn);
}
function updateTranslation(textarea) {
const langIndex = parseInt(textarea.dataset.langIndex);
const id = textarea.dataset.resId;
const newValue = textarea.value;
const lang = resourcesData[langIndex];
const resIndex = lang.resources.findIndex((r) => r.id === id);
if (resIndex !== -1) {
lang.resources[resIndex].value = newValue;
} else {
lang.resources.push({ id, value: newValue });
}
}
function addNewIdentifier() {
const newId = prompt("شناسه جدید را وارد کنید (مثال: my_new_key):");
if (!newId || !newId.trim()) return;
const trimmedId = newId.trim();
if (getAllIdentifiers().includes(trimmedId)) {
alert("این شناسه از قبل وجود دارد.");
return;
}
// Add to all languages with empty value
resourcesData.forEach((lang) => {
lang.resources.push({ id: trimmedId, value: "" });
});
renderIdList();
renderJson();
selectIdentifier(trimmedId);
}
// ============ JSON & Actions ============
function switchJsonTab(tab) {
jsonTab = tab;
document
.querySelectorAll(".tab")
.forEach((t) => t.classList.remove("active"));
document.getElementById(`tab-${tab}`).classList.add("active");
renderJson();
}
function renderJson() {
const output = document.getElementById("jsonOutput");
if (jsonTab === "full") {
output.textContent = JSON.stringify(resourcesData, null, 2);
}
}
function downloadJSON() {
const blob = new Blob([JSON.stringify(resourcesData, null, 2)], {
type: "application/json",
});
const url = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = url;
a.download = "x-framework-translations.json";
a.click();
URL.revokeObjectURL(url);
}
function copyJSON() {
navigator.clipboard
.writeText(JSON.stringify(resourcesData, null, 2))
.then(() => alert("✅ JSON در کلیپ‌بورد کپی شد."))
.catch(() => alert("❌ خطا در کپی کردن."));
}
function resetToDefault() {
if (
confirm(
"آیا اطمینان دارید؟ تمام تغییرات شما از بین خواهد رفت و به حالت پیش‌فرض بازمی‌گردد.",
)
) {
resourcesData = JSON.parse(JSON.stringify(DEFAULT_RESOURCES));
selectedId = null;
document.getElementById("editForm").innerHTML =
'<p style="opacity: 0.5; text-align: center; padding: 40px;">یک شناسه را از لیست سمت راست انتخاب کنید تا ترجمه‌های آن را ویرایش کنید.</p>';
renderLanguages();
renderIdList();
renderJson();
}
}
// ============ File Upload ============
function handleFileUpload(event) {
const file = event.target.files[0];
if (!file) return;
const reader = new FileReader();
reader.onload = function (e) {
try {
const parsed = JSON.parse(e.target.result);
if (!Array.isArray(parsed)) {
throw new Error("فایل JSON باید یک آرایه از اشیاء زبان باشد.");
}
// Basic validation
parsed.forEach((lang) => {
if (
!lang.name ||
!lang.locale ||
!Array.isArray(lang.resources)
) {
throw new Error(
"ساختار هر زبان باید شامل name، locale و resources باشد.",
);
}
});
resourcesData = parsed;
selectedId = null;
document.getElementById("editForm").innerHTML =
'<p style="opacity: 0.5; text-align: center; padding: 40px;">یک شناسه را از لیست سمت راست انتخاب کنید تا ترجمه‌های آن را ویرایش کنید.</p>';
document.getElementById("uploadStatus").className =
"upload-status success";
document.getElementById("uploadStatus").textContent =
`✅ فایل با موفقیت بارگذاری شد. (${resourcesData.length} زبان)`;
renderLanguages();
renderIdList();
renderJson();
} catch (err) {
document.getElementById("uploadStatus").className =
"upload-status error";
document.getElementById("uploadStatus").textContent =
`❌ خطا: ${err.message}`;
}
};
reader.readAsText(file);
}
function switchSource(source) {
document
.querySelectorAll(".source-tab")
.forEach((t) => t.classList.remove("active"));
event.target.classList.add("active");
document
.querySelectorAll(".source-content")
.forEach((c) => c.classList.remove("active"));
document.getElementById(`source-${source}`).classList.add("active");
}
// Start
init();
</script>
</body>
</html>