313 lines
12 KiB
TypeScript
313 lines
12 KiB
TypeScript
/**
|
|
* Add Arabic (ar) to nameLocalized, descriptionLocalized, metaTitleLocalized, metaDescriptionLocalized
|
|
* in prisma/tools.json. Does not change slug, id, category, or any other non-localized fields.
|
|
*
|
|
* Run from backend: npx ts-node scripts/add-arabic-to-tools-json.ts
|
|
* Or: node scripts/add-arabic-to-tools-json.js (if compiled)
|
|
*
|
|
* Usage: npx ts-node scripts/add-arabic-to-tools-json.ts [path/to/tools.json]
|
|
* Default path: prisma/tools.json (relative to backend dir)
|
|
*/
|
|
|
|
import * as fs from 'fs';
|
|
import * as path from 'path';
|
|
|
|
const TOOLS_JSON = process.argv[2] || path.join(__dirname, '../prisma/tools.json');
|
|
|
|
/** English -> Arabic replacements for tool names and descriptions (order matters: longer first) */
|
|
const EN_AR: Record<string, string> = {
|
|
'Filezzy': 'Filezzy',
|
|
' | Filezzy': ' | Filezzy',
|
|
' - Filezzy': ' - Filezzy',
|
|
'Batch Add Page Numbers': 'إضافة أرقام الصفحات للمجموعات',
|
|
'Batch Add Password': 'إضافة كلمة مرور للمجموعات',
|
|
'Batch Add Stamp': 'إضافة ختم للمجموعات',
|
|
'Batch Add Watermark': 'إضافة علامة مائية للمجموعات',
|
|
'Batch Compress': 'ضغط مجموعة',
|
|
'Batch Convert to PDF': 'تحويل مجموعة إلى PDF',
|
|
'Batch Merge': 'دمج مجموعة',
|
|
'Batch Add Page Numbers to PDF': 'إضافة أرقام الصفحات لملفات PDF المجمعة',
|
|
'Add page numbers to multiple PDFs': 'إضافة أرقام الصفحات لعدة ملفات PDF',
|
|
'Password-protect multiple PDFs': 'حماية عدة ملفات PDF بكلمة مرور',
|
|
'Add the same stamp image to multiple PDFs': 'إضافة نفس صورة الختم لعدة ملفات PDF',
|
|
'Add the same watermark to multiple PDFs': 'إضافة نفس العلامة المائية لعدة ملفات PDF',
|
|
'Compress multiple PDFs': 'ضغط عدة ملفات PDF',
|
|
'Convert multiple files to PDF': 'تحويل عدة ملفات إلى PDF',
|
|
'Merge multiple PDFs': 'دمج عدة ملفات PDF',
|
|
'Batch': 'مجموعة',
|
|
'Add': 'إضافة',
|
|
'Compress': 'ضغط',
|
|
'Merge': 'دمج',
|
|
'Split': 'تقسيم',
|
|
'Convert': 'تحويل',
|
|
'PDF': 'PDF',
|
|
'Image': 'صورة',
|
|
'Word': 'Word',
|
|
'Excel': 'Excel',
|
|
'Watermark': 'علامة مائية',
|
|
'Stamp': 'ختم',
|
|
'Password': 'كلمة مرور',
|
|
'Page Numbers': 'أرقام الصفحات',
|
|
'Remove': 'إزالة',
|
|
'Extract': 'استخراج',
|
|
'Protect': 'حماية',
|
|
'Unlock': 'فتح',
|
|
'Rotate': 'تدوير',
|
|
'Crop': 'قص',
|
|
'Resize': 'تغيير الحجم',
|
|
'Format': 'تنسيق',
|
|
'Multiple': 'متعدد',
|
|
'files': 'ملفات',
|
|
'file': 'ملف',
|
|
'Free': 'مجاني',
|
|
'tool': 'أداة',
|
|
'tools': 'أدوات',
|
|
' at once': ' دفعة واحدة',
|
|
' at once.': ' دفعة واحدة.',
|
|
' once.': ' مرة واحدة.',
|
|
'One setting for all files.': 'إعداد واحد لجميع الملفات.',
|
|
'Same password for all.': 'نفس كلمة المرور للجميع.',
|
|
'Same format for all.': 'نفس التنسيق للجميع.',
|
|
'| Filezzy': ' | Filezzy',
|
|
' - Multiple Files': ' - ملفات متعددة',
|
|
'Multiple Files': 'ملفات متعددة',
|
|
' to PDF': ' إلى PDF',
|
|
' to Word': ' إلى Word',
|
|
' to Excel': ' إلى Excel',
|
|
' to Image': ' إلى صورة',
|
|
' to Images': ' إلى صور',
|
|
' to HTML': ' إلى HTML',
|
|
' to EPUB': ' إلى EPUB',
|
|
' from PDF': ' من PDF',
|
|
' from Image': ' من صورة',
|
|
' from Word': ' من Word',
|
|
' from Excel': ' من Excel',
|
|
' from HTML': ' من HTML',
|
|
' from Markdown': ' من Markdown',
|
|
' from JSON': ' من JSON',
|
|
' from CSV': ' من CSV',
|
|
' from XML': ' من XML',
|
|
' from Text': ' من نص',
|
|
' from URL': ' من رابط',
|
|
' from URL.': ' من رابط.',
|
|
' from Images': ' من صور',
|
|
' from PDFs': ' من ملفات PDF',
|
|
' from files': ' من ملفات',
|
|
' from file': ' من ملف',
|
|
' to JPG': ' إلى JPG',
|
|
' to PNG': ' إلى PNG',
|
|
' to WebP': ' إلى WebP',
|
|
' to GIF': ' إلى GIF',
|
|
' to SVG': ' إلى SVG',
|
|
' to TIFF': ' إلى TIFF',
|
|
' to BMP': ' إلى BMP',
|
|
' to HEIC': ' إلى HEIC',
|
|
' to AVIF': ' إلى AVIF',
|
|
' to PDF/A': ' إلى PDF/A',
|
|
' to PDF/X': ' إلى PDF/X',
|
|
' to DOCX': ' إلى DOCX',
|
|
' to DOC': ' إلى DOC',
|
|
' to ODT': ' إلى ODT',
|
|
' to RTF': ' إلى RTF',
|
|
' to TXT': ' إلى TXT',
|
|
' to Markdown': ' إلى Markdown',
|
|
' to CSV': ' إلى CSV',
|
|
' to JSON': ' إلى JSON',
|
|
' to XML': ' إلى XML',
|
|
' to PowerPoint': ' إلى PowerPoint',
|
|
' to PPTX': ' إلى PPTX',
|
|
' to Presentation': ' إلى عرض تقديمي',
|
|
' to Ebook': ' إلى كتاب إلكتروني',
|
|
' to EPUB or AZW3': ' إلى EPUB أو AZW3',
|
|
' to Archive': ' إلى أرشيف',
|
|
' to ZIP': ' إلى ZIP',
|
|
' to Searchable': ' إلى قابل للبحث',
|
|
' to Searchable PDF': ' إلى PDF قابل للبحث',
|
|
'Searchable PDF': 'PDF قابل للبحث',
|
|
'OCR': 'OCR',
|
|
'Compress PDF': 'ضغط PDF',
|
|
'Merge PDF': 'دمج PDF',
|
|
'Split PDF': 'تقسيم PDF',
|
|
'Add Watermark': 'إضافة علامة مائية',
|
|
'Add Stamp': 'إضافة ختم',
|
|
'Add Password': 'إضافة كلمة مرور',
|
|
'Remove Password': 'إزالة كلمة مرور',
|
|
'Unlock PDF': 'فتح PDF',
|
|
'Rotate PDF': 'تدوير PDF',
|
|
'Crop PDF': 'قص PDF',
|
|
'Compress Image': 'ضغط صورة',
|
|
'Resize Image': 'تغيير حجم الصورة',
|
|
'Convert Image': 'تحويل صورة',
|
|
'Remove Background': 'إزالة الخلفية',
|
|
'Crop Image': 'قص الصورة',
|
|
'Rotate Image': 'تدوير الصورة',
|
|
'Grayscale': 'تدرج رمادي',
|
|
'QR Code': 'رمز QR',
|
|
'Barcode': 'الباركود',
|
|
'Hash': 'تجزئة',
|
|
'Encode': 'ترميز',
|
|
'Decode': 'فك الترميز',
|
|
'Base64': 'Base64',
|
|
'JSON': 'JSON',
|
|
'XML': 'XML',
|
|
'CSV': 'CSV',
|
|
'Markdown': 'Markdown',
|
|
'HTML': 'HTML',
|
|
'Regex': 'التعبير النمطي',
|
|
'Password Generator': 'مولد كلمات المرور',
|
|
'Lorem Ipsum': 'نص تجريبي',
|
|
'Blank removal': 'إزالة الفراغات',
|
|
'Pipeline': 'سير العمل',
|
|
'Workflow': 'سير العمل',
|
|
'Scan to Searchable': 'المسح إلى PDF قابل للبحث',
|
|
'Invoice': 'فاتورة',
|
|
'Archive': 'أرشفة',
|
|
'E-sign': 'التوقيع الإلكتروني',
|
|
'Sign': 'توقيع',
|
|
'Digital Sign': 'توقيع رقمي',
|
|
'Verify': 'التحقق',
|
|
'Validate': 'التحقق من الصحة',
|
|
'Form': 'نموذج',
|
|
'Fill': 'ملء',
|
|
'Flatten': 'تسوية',
|
|
'Optimize': 'تحسين',
|
|
'Repair': 'إصلاح',
|
|
'Sanitize': 'تنظيف',
|
|
'Redact': 'إخفاء',
|
|
'Auto Redact': 'إخفاء تلقائي',
|
|
'Compare': 'مقارنة',
|
|
'Organize': 'تنظيم',
|
|
'Reorder': 'إعادة ترتيب',
|
|
'Extract Pages': 'استخراج الصفحات',
|
|
'Extract Text': 'استخراج النص',
|
|
'Extract Images': 'استخراج الصور',
|
|
'Get Info': 'الحصول على المعلومات',
|
|
'Info': 'معلومات',
|
|
'Metadata': 'البيانات الوصفية',
|
|
'Attachments': 'المرفقات',
|
|
'List Attachments': 'قائمة المرفقات',
|
|
'Embed': 'تضمين',
|
|
'Overlay': 'تراكب',
|
|
'Blank': 'فارغ',
|
|
'Blanks': 'فراغات',
|
|
'Remove Blanks': 'إزالة الصفحات الفارغة',
|
|
'Sections': 'أقسام',
|
|
'Split by Sections': 'تقسيم حسب الأقسام',
|
|
'Chapters': 'فصول',
|
|
'Split by Chapters': 'تقسيم حسب الفصول',
|
|
'Size': 'حجم',
|
|
'Split by Size': 'تقسيم حسب الحجم',
|
|
'Single Page': 'صفحة واحدة',
|
|
'Page': 'صفحة',
|
|
'Pages': 'صفحات',
|
|
'Presentation': 'عرض تقديمي',
|
|
'PowerPoint': 'PowerPoint',
|
|
'Ebook': 'كتاب إلكتروني',
|
|
'EPUB': 'EPUB',
|
|
'AZW3': 'AZW3',
|
|
'Table': 'جدول',
|
|
'Tables': 'جداول',
|
|
'Text': 'نص',
|
|
'Image to PDF': 'صورة إلى PDF',
|
|
'Images to PDF': 'صور إلى PDF',
|
|
'HTML to PDF': 'HTML إلى PDF',
|
|
'Markdown to PDF': 'Markdown إلى PDF',
|
|
'Word to PDF': 'Word إلى PDF',
|
|
'Excel to PDF': 'Excel إلى PDF',
|
|
'PPT to PDF': 'PPT إلى PDF',
|
|
'PDF to Word': 'PDF إلى Word',
|
|
'PDF to Excel': 'PDF إلى Excel',
|
|
'PDF to Images': 'PDF إلى صور',
|
|
'PDF to HTML': 'PDF إلى HTML',
|
|
'PDF to Text': 'PDF إلى نص',
|
|
'PDF to CSV': 'PDF إلى CSV',
|
|
'PDF to EPUB': 'PDF إلى EPUB',
|
|
'PDF to PowerPoint': 'PDF إلى PowerPoint',
|
|
'PDF/A': 'PDF/A',
|
|
'PDF/X': 'PDF/X',
|
|
'Archival': 'أرشفة',
|
|
'Long-term preservation': 'الحفظ طويل الأمد',
|
|
'Free batch': 'مجموعة مجانية',
|
|
'Free tool': 'أداة مجانية',
|
|
'Free online': 'مجاني على الإنترنت',
|
|
' at once!': ' دفعة واحدة!',
|
|
'protection': 'حماية',
|
|
' numbering': ' الترقيم',
|
|
' encryption': ' التشفير',
|
|
' stamping': ' الختم',
|
|
' protection': ' الحماية',
|
|
' protection to ': ' الحماية لـ ',
|
|
' numbering tool': ' أداة ترقيم',
|
|
' encryption tool': ' أداة تشفير',
|
|
' stamping tool': ' أداة ختم',
|
|
' protection.': ' الحماية.',
|
|
' to ': ' إلى ',
|
|
'!': '!',
|
|
'.': '.',
|
|
};
|
|
|
|
// Placeholder must not contain any substring that our EN_AR might replace (e.g. "file")
|
|
const FILEZZY_PLACEHOLDER = '\u200B\u200B\u200B'; // Unicode zero-width spaces (invisible, won't match dict)
|
|
|
|
function translateToArabic(text: string): string {
|
|
if (!text || typeof text !== 'string') return text;
|
|
// Protect "Filezzy" from partial replacement (e.g. "file" -> "ملف" breaking "Filezzy")
|
|
let out = text.replace(/\bFilezzy\b/gi, FILEZZY_PLACEHOLDER);
|
|
// Sort by key length descending so longer phrases are replaced first
|
|
const entries = Object.entries(EN_AR).sort((a, b) => b[0].length - a[0].length);
|
|
for (const [en, ar] of entries) {
|
|
if (en === 'Filezzy' || en === ' | Filezzy' || en === ' - Filezzy') continue; // already protected
|
|
const re = new RegExp(escapeRegex(en), 'gi');
|
|
out = out.replace(re, ar);
|
|
}
|
|
out = out.split(FILEZZY_PLACEHOLDER).join('Filezzy');
|
|
return out.trim() || text;
|
|
}
|
|
|
|
function escapeRegex(s: string): string {
|
|
return s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
}
|
|
|
|
type Localized = Record<string, string> | null | undefined;
|
|
|
|
function ensureAr(obj: Localized, sourceKey: 'en' | 'fr', fallback: string): Record<string, string> {
|
|
const o = obj && typeof obj === 'object' ? { ...obj } : {};
|
|
const source = o[sourceKey] ?? o.en ?? o.fr ?? fallback;
|
|
o.ar = translateToArabic(String(source));
|
|
return o as Record<string, string>;
|
|
}
|
|
|
|
function main() {
|
|
const dataPath = path.resolve(process.cwd(), TOOLS_JSON);
|
|
if (!fs.existsSync(dataPath)) {
|
|
console.error('File not found:', dataPath);
|
|
process.exit(1);
|
|
}
|
|
|
|
const raw = fs.readFileSync(dataPath, 'utf-8');
|
|
const tools: Record<string, unknown>[] = JSON.parse(raw);
|
|
if (!Array.isArray(tools)) {
|
|
console.error('tools.json must be an array');
|
|
process.exit(1);
|
|
}
|
|
|
|
let updated = 0;
|
|
for (const tool of tools) {
|
|
const name = (tool.name as string) || '';
|
|
const desc = (tool.description as string) || '';
|
|
const metaTitle = (tool.metaTitle as string) || name;
|
|
const metaDesc = (tool.metaDescription as string) || desc;
|
|
|
|
tool.nameLocalized = ensureAr(tool.nameLocalized as Localized, 'en', name);
|
|
tool.descriptionLocalized = ensureAr(tool.descriptionLocalized as Localized, 'en', desc);
|
|
tool.metaTitleLocalized = ensureAr(tool.metaTitleLocalized as Localized, 'en', metaTitle);
|
|
tool.metaDescriptionLocalized = ensureAr(tool.metaDescriptionLocalized as Localized, 'en', metaDesc);
|
|
updated++;
|
|
}
|
|
|
|
fs.writeFileSync(dataPath, JSON.stringify(tools, null, 2), 'utf-8');
|
|
console.log(`Added Arabic (ar) to ${updated} tools in ${dataPath}`);
|
|
}
|
|
|
|
main();
|