mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-14 11:39:32 +02:00
chore: add i18n to meta script
This commit is contained in:
920
.idea/workspace.xml
generated
920
.idea/workspace.xml
generated
File diff suppressed because it is too large
Load Diff
260
scripts/add-i18n-to-meta.js
Normal file
260
scripts/add-i18n-to-meta.js
Normal file
@@ -0,0 +1,260 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const TYPE_MAPPING = { 'image-generic': 'image', png: 'image' };
|
||||
// Helper function to convert kebab-case to camelCase
|
||||
function toCamelCase(str) {
|
||||
return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
||||
}
|
||||
|
||||
// Helper function to parse meta.ts file and extract required fields
|
||||
function parseMeta(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Extract category from defineTool first parameter
|
||||
const categoryMatch = content.match(/defineTool\s*\(\s*['"]([^'"]+)['"]/);
|
||||
if (!categoryMatch) {
|
||||
throw new Error(`Could not find category in ${filePath}`);
|
||||
}
|
||||
const category = categoryMatch[1];
|
||||
|
||||
// Extract name, description, shortDescription, and longDescription
|
||||
const nameMatch = content.match(/name\s*:\s*['"`]([^'"`]+)['"`]/);
|
||||
const descMatch = content.match(/description\s*:\s*['"`]([\s\S]*?)['"`]/);
|
||||
const shortMatch = content.match(
|
||||
/shortDescription\s*:\s*['"`]([^'"`]+)['"`]/
|
||||
);
|
||||
const longMatch = content.match(/longDescription\s*:\s*['"`]([\s\S]*?)['"`]/);
|
||||
|
||||
if (!nameMatch || !descMatch || !shortMatch) {
|
||||
console.warn(`⚠️ Missing required fields in ${filePath}`);
|
||||
console.warn(
|
||||
` name: ${!!nameMatch}, description: ${!!descMatch}, shortDescription: ${!!shortMatch}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
category,
|
||||
name: nameMatch[1],
|
||||
description: descMatch[1].replace(/\s+/g, ' ').trim(),
|
||||
shortDescription: shortMatch[1],
|
||||
longDescription: longMatch ? longMatch[1].replace(/\s+/g, ' ').trim() : null
|
||||
};
|
||||
}
|
||||
|
||||
// Helper function to check if meta.ts already has i18n field
|
||||
function hasI18nField(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
return content.includes('i18n:');
|
||||
}
|
||||
|
||||
// Helper function to add i18n field to meta.ts
|
||||
function addI18nToMeta(filePath, category, toolName, hasLongDescription) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Build i18n object
|
||||
let i18nObject = ` i18n: {
|
||||
name: '${category}:${toolName}.title',
|
||||
description: '${category}:${toolName}.description',
|
||||
shortDescription: '${category}:${toolName}.shortDescription'`;
|
||||
|
||||
if (hasLongDescription) {
|
||||
i18nObject += `,
|
||||
longDescription: '${category}:${toolName}.longDescription'`;
|
||||
}
|
||||
|
||||
i18nObject += `
|
||||
},`;
|
||||
|
||||
// Find the position to insert i18n (after the export line but before the closing bracket)
|
||||
const exportMatch = content.match(/export const tool = defineTool\([^{]*\{/);
|
||||
if (!exportMatch) {
|
||||
throw new Error(`Could not find export structure in ${filePath}`);
|
||||
}
|
||||
|
||||
const insertPosition = exportMatch.index + exportMatch[0].length;
|
||||
const beforeInsert = content.substring(0, insertPosition);
|
||||
const afterInsert = content.substring(insertPosition);
|
||||
|
||||
// Insert i18n field at the beginning of the object
|
||||
const updatedContent = beforeInsert + '\n' + i18nObject + afterInsert;
|
||||
|
||||
fs.writeFileSync(filePath, updatedContent, 'utf8');
|
||||
}
|
||||
|
||||
// Helper function to get category i18n file path
|
||||
function getCategoryI18nPath(category) {
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
||||
// Special case: image-generic tools use the image folder for i18n
|
||||
const folderName = TYPE_MAPPING[category] || category;
|
||||
return path.join(
|
||||
PROJECT_ROOT,
|
||||
'src',
|
||||
'pages',
|
||||
'tools',
|
||||
folderName,
|
||||
'i18n',
|
||||
'en.json'
|
||||
);
|
||||
}
|
||||
|
||||
// Helper function to load category i18n data
|
||||
function loadCategoryI18n(category) {
|
||||
const i18nPath = getCategoryI18nPath(category);
|
||||
|
||||
try {
|
||||
if (fs.existsSync(i18nPath)) {
|
||||
const i18nRaw = fs.readFileSync(i18nPath, 'utf8');
|
||||
return JSON.parse(i18nRaw);
|
||||
} else {
|
||||
const i18nDir = path.dirname(i18nPath);
|
||||
if (!fs.existsSync(i18nDir)) {
|
||||
fs.mkdirSync(i18nDir, { recursive: true });
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`❌ Failed to parse ${i18nPath}:`, err.message);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper function to save category i18n data
|
||||
function saveCategoryI18n(category, data) {
|
||||
const i18nPath = getCategoryI18nPath(category);
|
||||
fs.writeFileSync(i18nPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
||||
return i18nPath;
|
||||
}
|
||||
|
||||
// Main execution
|
||||
console.log('🚀 Adding i18n fields to meta.ts files...\n');
|
||||
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
// Target files as specified
|
||||
const rootDir = path.join(PROJECT_ROOT, 'src/pages/tools');
|
||||
const metaFiles = [];
|
||||
|
||||
function findMetaFiles(dir) {
|
||||
const items = fs.readdirSync(dir, { withFileTypes: true });
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(dir, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
findMetaFiles(fullPath); // Recurse
|
||||
} else if (item.isFile() && item.name === 'meta.ts') {
|
||||
metaFiles.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
findMetaFiles(rootDir);
|
||||
|
||||
let processedCount = 0;
|
||||
let skippedCount = 0;
|
||||
let errorCount = 0;
|
||||
const updatedCategories = new Set();
|
||||
const categoryData = {};
|
||||
|
||||
// Process each target file
|
||||
metaFiles.forEach((filePath) => {
|
||||
try {
|
||||
// Check if file exists
|
||||
if (!fs.existsSync(filePath)) {
|
||||
console.error(`❌ File not found: ${filePath}`);
|
||||
errorCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if i18n field already exists
|
||||
if (hasI18nField(filePath)) {
|
||||
console.log(`⏭️ Skipped ${filePath} (already has i18n field)`);
|
||||
skippedCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse meta.ts file
|
||||
const parsed = parseMeta(filePath);
|
||||
if (!parsed) {
|
||||
errorCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
const {
|
||||
category: rawCategory,
|
||||
name,
|
||||
description,
|
||||
shortDescription,
|
||||
longDescription
|
||||
} = parsed;
|
||||
|
||||
const category = TYPE_MAPPING[rawCategory] || rawCategory;
|
||||
// Get tool name from folder path
|
||||
const toolFolderName = path.basename(path.dirname(filePath));
|
||||
const toolKey = toCamelCase(toolFolderName); // camelCase for i18n file keys
|
||||
|
||||
// Load category i18n data if not already loaded
|
||||
if (!categoryData[category]) {
|
||||
categoryData[category] = loadCategoryI18n(category);
|
||||
}
|
||||
|
||||
// Ensure tool entry exists in i18n
|
||||
if (!categoryData[category][toolKey]) {
|
||||
categoryData[category][toolKey] = {};
|
||||
}
|
||||
|
||||
const entry = categoryData[category][toolKey];
|
||||
let hasI18nChanges = false;
|
||||
|
||||
// Add missing fields to i18n
|
||||
if (!entry.title) {
|
||||
entry.title = name;
|
||||
hasI18nChanges = true;
|
||||
}
|
||||
if (!entry.description) {
|
||||
entry.description = description;
|
||||
hasI18nChanges = true;
|
||||
}
|
||||
if (!entry.shortDescription) {
|
||||
entry.shortDescription = shortDescription;
|
||||
hasI18nChanges = true;
|
||||
}
|
||||
if (longDescription && !entry.longDescription) {
|
||||
entry.longDescription = longDescription;
|
||||
hasI18nChanges = true;
|
||||
}
|
||||
|
||||
// Add i18n field to meta.ts
|
||||
addI18nToMeta(filePath, category, toolKey, !!longDescription);
|
||||
|
||||
if (hasI18nChanges) {
|
||||
updatedCategories.add(category);
|
||||
}
|
||||
|
||||
console.log(`✅ Added i18n to ${filePath}`);
|
||||
processedCount++;
|
||||
} catch (err) {
|
||||
console.error(`❌ Error processing ${filePath}:`, err.message);
|
||||
errorCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// Save updated category i18n files
|
||||
if (updatedCategories.size > 0) {
|
||||
console.log('\n💾 Saving updated i18n files...');
|
||||
for (const category of updatedCategories) {
|
||||
const savedPath = saveCategoryI18n(category, categoryData[category]);
|
||||
console.log(` 📁 ${path.relative(PROJECT_ROOT, savedPath)}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Summary
|
||||
console.log('\n📊 Summary:');
|
||||
console.log(` ✅ Processed: ${processedCount} files`);
|
||||
console.log(` ⏭️ Skipped: ${skippedCount} files (already had i18n)`);
|
||||
console.log(` ❌ Errors: ${errorCount} files`);
|
||||
console.log(
|
||||
`\n🎉 Successfully updated ${processedCount} meta.ts files and ${updatedCategories.size} i18n files!`
|
||||
);
|
203
scripts/update-i18n-from-meta.js
Normal file
203
scripts/update-i18n-from-meta.js
Normal file
@@ -0,0 +1,203 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Helper function to convert kebab-case to camelCase
|
||||
function toCamelCase(str) {
|
||||
return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase());
|
||||
}
|
||||
|
||||
// Helper function to recursively find all meta.ts files
|
||||
function findMetaFiles(dir) {
|
||||
const files = [];
|
||||
|
||||
function traverse(currentDir) {
|
||||
const items = fs.readdirSync(currentDir, { withFileTypes: true });
|
||||
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(currentDir, item.name);
|
||||
|
||||
if (item.isDirectory()) {
|
||||
traverse(fullPath);
|
||||
} else if (item.name === 'meta.ts') {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
traverse(dir);
|
||||
return files;
|
||||
}
|
||||
|
||||
// Helper function to parse meta.ts file and extract the required fields
|
||||
function parseMeta(filePath) {
|
||||
const content = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Extract category from defineTool first parameter
|
||||
const categoryMatch = content.match(/defineTool\s*\(\s*['"]([^'"]+)['"]/);
|
||||
if (!categoryMatch) {
|
||||
throw new Error(`Could not find category in ${filePath}`);
|
||||
}
|
||||
const category = categoryMatch[1];
|
||||
|
||||
// Extract name, description, and shortDescription
|
||||
const nameMatch = content.match(/name\s*:\s*['"`]([^'"`]+)['"`]/);
|
||||
const descMatch = content.match(
|
||||
/description\s*:\s*['"`]([\s\S]*?)['"`]\s*,\s*shortDescription/
|
||||
);
|
||||
const shortMatch = content.match(
|
||||
/shortDescription\s*:\s*['"`]([^'"`]+)['"`]/
|
||||
);
|
||||
|
||||
if (!nameMatch || !descMatch || !shortMatch) {
|
||||
console.warn(`⚠️ Missing fields in ${filePath}`);
|
||||
console.warn(
|
||||
` name: ${!!nameMatch}, description: ${!!descMatch}, shortDescription: ${!!shortMatch}`
|
||||
);
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
category,
|
||||
name: nameMatch[1],
|
||||
description: descMatch[1].replace(/\s+/g, ' ').trim(),
|
||||
shortDescription: shortMatch[1]
|
||||
};
|
||||
}
|
||||
|
||||
// Main execution
|
||||
console.log('🚀 Starting i18n extraction from meta.ts files...\n');
|
||||
|
||||
const PROJECT_ROOT = path.resolve(__dirname, '..');
|
||||
|
||||
// Helper function to get or create category i18n file
|
||||
function getCategoryI18nPath(category) {
|
||||
return path.join(
|
||||
PROJECT_ROOT,
|
||||
'src',
|
||||
'pages',
|
||||
'tools',
|
||||
category,
|
||||
'i18n',
|
||||
'en.json'
|
||||
);
|
||||
}
|
||||
|
||||
function loadCategoryI18n(category) {
|
||||
const i18nPath = getCategoryI18nPath(category);
|
||||
|
||||
try {
|
||||
if (fs.existsSync(i18nPath)) {
|
||||
const i18nRaw = fs.readFileSync(i18nPath, 'utf8');
|
||||
return JSON.parse(i18nRaw);
|
||||
} else {
|
||||
// Create directory if it doesn't exist
|
||||
const i18nDir = path.dirname(i18nPath);
|
||||
if (!fs.existsSync(i18nDir)) {
|
||||
fs.mkdirSync(i18nDir, { recursive: true });
|
||||
}
|
||||
return {};
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`❌ Failed to parse ${i18nPath}:`, err.message);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
function saveCategoryI18n(category, data) {
|
||||
const i18nPath = getCategoryI18nPath(category);
|
||||
|
||||
// Create backup
|
||||
// if (fs.existsSync(i18nPath)) {
|
||||
// fs.copyFileSync(i18nPath, i18nPath + '.bak');
|
||||
// }
|
||||
|
||||
// Write updated file
|
||||
fs.writeFileSync(i18nPath, JSON.stringify(data, null, 2) + '\n', 'utf8');
|
||||
return i18nPath;
|
||||
}
|
||||
|
||||
// 2) Find all meta.ts files under src/pages/tools
|
||||
const toolsDir = path.join(PROJECT_ROOT, 'src', 'pages', 'tools');
|
||||
const files = findMetaFiles(toolsDir);
|
||||
console.log(`📁 Found ${files.length} meta.ts files\n`);
|
||||
|
||||
let addedCount = 0;
|
||||
let skippedCount = 0;
|
||||
let errorCount = 0;
|
||||
const updatedCategories = new Set();
|
||||
|
||||
// 3) Process each meta.ts file
|
||||
const categoryData = {};
|
||||
|
||||
files.forEach((file) => {
|
||||
try {
|
||||
const relativePath = path.relative(PROJECT_ROOT, file);
|
||||
const parsed = parseMeta(file);
|
||||
|
||||
if (!parsed) {
|
||||
errorCount++;
|
||||
return;
|
||||
}
|
||||
|
||||
const { category, name, description, shortDescription } = parsed;
|
||||
|
||||
// Load category i18n data if not already loaded
|
||||
if (!categoryData[category]) {
|
||||
categoryData[category] = loadCategoryI18n(category);
|
||||
}
|
||||
|
||||
// Get tool key from folder name (convert kebab-case to camelCase)
|
||||
const toolSlug = path.basename(path.dirname(file));
|
||||
const toolKey = toCamelCase(toolSlug);
|
||||
|
||||
// Ensure tool entry exists
|
||||
if (!categoryData[category][toolKey]) {
|
||||
categoryData[category][toolKey] = {};
|
||||
}
|
||||
|
||||
const entry = categoryData[category][toolKey];
|
||||
let hasChanges = false;
|
||||
|
||||
// Add missing fields
|
||||
if (!entry.name) {
|
||||
entry.name = name;
|
||||
hasChanges = true;
|
||||
}
|
||||
if (!entry.description) {
|
||||
entry.description = description;
|
||||
hasChanges = true;
|
||||
}
|
||||
if (!entry.shortDescription) {
|
||||
entry.shortDescription = shortDescription;
|
||||
hasChanges = true;
|
||||
}
|
||||
|
||||
if (hasChanges) {
|
||||
console.log(`✅ Updated ${category}/${toolKey}`);
|
||||
addedCount++;
|
||||
updatedCategories.add(category);
|
||||
} else {
|
||||
console.log(`⏭️ Skipped ${category}/${toolKey} (already exists)`);
|
||||
skippedCount++;
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`❌ Error processing ${file}:`, err.message);
|
||||
errorCount++;
|
||||
}
|
||||
});
|
||||
|
||||
// 4) Save updated category i18n files
|
||||
console.log('\n💾 Saving updated i18n files...');
|
||||
for (const category of updatedCategories) {
|
||||
const savedPath = saveCategoryI18n(category, categoryData[category]);
|
||||
console.log(` 📁 ${path.relative(PROJECT_ROOT, savedPath)}`);
|
||||
}
|
||||
|
||||
// 6) Summary
|
||||
console.log('\n📊 Summary:');
|
||||
console.log(` ✅ Updated: ${addedCount} tools`);
|
||||
console.log(` ⏭️ Skipped: ${skippedCount} tools (already had entries)`);
|
||||
console.log(` ❌ Errors: ${errorCount} tools`);
|
||||
console.log(
|
||||
`\n🎉 Successfully updated ${updatedCategories.size} category i18n files!`
|
||||
);
|
@@ -31,11 +31,13 @@
|
||||
"mergeAudio": {
|
||||
"title": "Merge Audio",
|
||||
"description": "Combine multiple audio files into a single audio file by concatenating them in sequence.",
|
||||
"shortDescription": "Merge multiple audio files into one (MP3, AAC, WAV)."
|
||||
"shortDescription": "Merge multiple audio files into one (MP3, AAC, WAV).",
|
||||
"longDescription": "This tool allows you to merge multiple audio files into a single file by concatenating them in the order you upload them. Perfect for combining podcast segments, music tracks, or any audio files that need to be joined together. Supports various audio formats including MP3, AAC, and WAV."
|
||||
},
|
||||
"trim": {
|
||||
"title": "Trim Audio",
|
||||
"description": "Cut and trim audio files to extract specific segments by specifying start and end times.",
|
||||
"shortDescription": "Trim audio files to extract specific time segments (MP3, AAC, WAV)."
|
||||
"shortDescription": "Trim audio files to extract specific time segments (MP3, AAC, WAV).",
|
||||
"longDescription": "This tool allows you to trim audio files by specifying start and end times. You can extract specific segments from longer audio files, remove unwanted parts, or create shorter clips. Supports various audio formats including MP3, AAC, and WAV. Perfect for podcast editing, music production, or any audio editing needs."
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('audio', {
|
||||
i18n: {
|
||||
name: 'audio:mergeAudio.title',
|
||||
description: 'audio:mergeAudio.description',
|
||||
shortDescription: 'audio:mergeAudio.shortDescription',
|
||||
longDescription: 'audio:mergeAudio.longDescription'
|
||||
},
|
||||
name: 'Merge Audio',
|
||||
path: 'merge-audio',
|
||||
icon: 'fluent:merge-20-regular',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('audio', {
|
||||
i18n: {
|
||||
name: 'audio:trim.title',
|
||||
description: 'audio:trim.description',
|
||||
shortDescription: 'audio:trim.shortDescription',
|
||||
longDescription: 'audio:trim.longDescription'
|
||||
},
|
||||
name: 'Trim Audio',
|
||||
path: 'trim',
|
||||
icon: 'mdi:scissors-cutting',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:csvRowsToColumns.title',
|
||||
description: 'csv:csvRowsToColumns.description',
|
||||
shortDescription: 'csv:csvRowsToColumns.shortDescription',
|
||||
longDescription: 'csv:csvRowsToColumns.longDescription'
|
||||
},
|
||||
name: 'Convert CSV Rows to Columns',
|
||||
path: 'csv-rows-to-columns',
|
||||
icon: 'fluent:text-arrow-down-right-column-24-filled',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:csvToJson.title',
|
||||
description: 'csv:csvToJson.description',
|
||||
shortDescription: 'csv:csvToJson.shortDescription'
|
||||
},
|
||||
name: 'Convert CSV to JSON',
|
||||
path: 'csv-to-json',
|
||||
icon: 'lets-icons:json-light',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:csvToTsv.title',
|
||||
description: 'csv:csvToTsv.description',
|
||||
shortDescription: 'csv:csvToTsv.shortDescription',
|
||||
longDescription: 'csv:csvToTsv.longDescription'
|
||||
},
|
||||
name: 'Convert CSV to TSV',
|
||||
path: 'csv-to-tsv',
|
||||
icon: 'codicon:keyboard-tab',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:csvToXml.title',
|
||||
description: 'csv:csvToXml.description',
|
||||
shortDescription: 'csv:csvToXml.shortDescription'
|
||||
},
|
||||
name: 'Convert CSV to XML',
|
||||
path: 'csv-to-xml',
|
||||
icon: 'mdi-light:xml',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:csvToYaml.title',
|
||||
description: 'csv:csvToYaml.description',
|
||||
shortDescription: 'csv:csvToYaml.shortDescription',
|
||||
longDescription: 'csv:csvToYaml.longDescription'
|
||||
},
|
||||
name: 'Convert CSV to YAML',
|
||||
path: 'csv-to-yaml',
|
||||
icon: 'nonicons:yaml-16',
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"insertCsvColumns": {
|
||||
"title": "Insert CSV Columns",
|
||||
"title": "Insert CSV columns",
|
||||
"description": "Add new columns to CSV data at specified positions.",
|
||||
"inputTitle": "Input CSV",
|
||||
"resultTitle": "Output CSV",
|
||||
@@ -29,7 +29,6 @@
|
||||
"title": "Insert CSV Columns",
|
||||
"description": "This tool allows you to insert new columns into CSV data at specified positions. You can prepend, append, or insert columns at custom positions based on header names or column numbers."
|
||||
},
|
||||
"title": "Insert CSV columns",
|
||||
"shortDescription": "Quickly insert one or more new columns anywhere in a CSV file."
|
||||
},
|
||||
"csvToJson": {
|
||||
@@ -52,7 +51,7 @@
|
||||
"shortDescription": "Convert CSV data to JSON format."
|
||||
},
|
||||
"findIncompleteCsvRecords": {
|
||||
"title": "Find Incomplete CSV Records",
|
||||
"title": "Find incomplete CSV records",
|
||||
"inputTitle": "Input CSV",
|
||||
"resultTitle": "CSV Status",
|
||||
"toolInfo": {
|
||||
@@ -69,7 +68,6 @@
|
||||
"findEmptyValuesDescription": "Display a message about CSV fields that are empty (These are not missing fields but fields that contain nothing).",
|
||||
"limitNumberOfMessages": "Limit number of messages",
|
||||
"messageLimitDescription": "Set the limit of number of messages in the output.",
|
||||
"title": "Find incomplete CSV records",
|
||||
"description": "Just upload your CSV file in the form below and this tool will automatically check if none of the rows or columns are missing values. In the tool options, you can adjust the input file format (specify the delimiter, quote character, and comment character). Additionally, you can enable checking for empty values, skip empty lines, and set a limit on the number of error messages in the output.",
|
||||
"shortDescription": "Quickly find rows and columns in CSV that are missing values."
|
||||
},
|
||||
@@ -81,12 +79,14 @@
|
||||
"csvRowsToColumns": {
|
||||
"title": "Convert CSV Rows to Columns",
|
||||
"description": "This tool converts rows of a CSV (Comma Separated Values) file into columns. It extracts the horizontal lines from the input CSV one by one, rotates them 90 degrees, and outputs them as vertical columns one after another, separated by commas.', longDescription: 'This tool converts rows of a CSV (Comma Separated Values) file into columns. For example, if the input CSV data has 6 rows, then the output will have 6 columns and the elements of the rows will be arranged from the top to bottom. In a well-formed CSV, the number of values in each row is the same. However, in cases when rows are missing fields, the program can fix them and you can choose from the available options: fill missing data with empty elements or replace missing data with custom elements, such as \"missing\", \"?\", or \"x\". During the conversion process, the tool also cleans the CSV file from unnecessary information, such as empty lines (these are lines without visible information) and comments. To help the tool correctly identify comments, in the options, you can specify the symbol at the beginning of a line that starts a comment. This symbol is typically a hash \"#\" or double slash \"//\". Csv-abulous!.",
|
||||
"shortDescription": "Convert CSV rows to columns."
|
||||
"shortDescription": "Convert CSV rows to columns.",
|
||||
"longDescription": "This tool converts rows of a CSV (Comma Separated Values) file into columns. For example, if the input CSV data has 6 rows, then the output will have 6 columns and the elements of the rows will be arranged from the top to bottom. In a well-formed CSV, the number of values in each row is the same. However, in cases when rows are missing fields, the program can fix them and you can choose from the available options: fill missing data with empty elements or replace missing data with custom elements, such as"
|
||||
},
|
||||
"csvToTsv": {
|
||||
"title": "Convert CSV to TSV",
|
||||
"description": "Upload your CSV file in the form below and it will automatically get converted to a TSV file. In the tool options, you can customize the input CSV format – specify the field delimiter, quotation character, and comment symbol, as well as skip empty CSV lines, and choose whether to preserve CSV column headers.",
|
||||
"shortDescription": "Convert CSV data to TSV format."
|
||||
"shortDescription": "Convert CSV data to TSV format.",
|
||||
"longDescription": "This tool transforms Comma Separated Values (CSV) data to Tab Separated Values (TSV) data. Both CSV and TSV are popular file formats for storing tabular data but they use different delimiters to separate values – CSV uses commas ("
|
||||
},
|
||||
"csvToXml": {
|
||||
"title": "Convert CSV to XML",
|
||||
@@ -96,16 +96,19 @@
|
||||
"csvToYaml": {
|
||||
"title": "Convert CSV to YAML",
|
||||
"description": "Just upload your CSV file in the form below and it will automatically get converted to a YAML file. In the tool options, you can specify the field delimiter character, field quote character, and comment character to adapt the tool to custom CSV formats. Additionally, you can select the output YAML format: one that preserves CSV headers or one that excludes CSV headers.",
|
||||
"shortDescription": "Quickly convert a CSV file to a YAML file."
|
||||
"shortDescription": "Quickly convert a CSV file to a YAML file.",
|
||||
"longDescription": "This tool transforms CSV (Comma Separated Values) data into the YAML (Yet Another Markup Language) data. CSV is a simple, tabular format that is used to represent matrix-like data types consisting of rows and columns. YAML, on the other hand, is a more advanced format (actually a superset of JSON), which creates more human-readable data for serialization, and it supports lists, dictionaries, and nested objects. This program supports various input CSV formats – the input data can be comma-separated (default), semicolon-separated, pipe-separated, or use another completely different delimiter. You can specify the exact delimiter your data uses in the options. Similarly, in the options, you can specify the quote character that is used to wrap CSV fields (by default a double-quote symbol). You can also skip lines that start with comments by specifying the comment symbols in the options. This allows you to keep your data clean by skipping unnecessary lines. There are two ways to convert CSV to YAML. The first method converts each CSV row into a YAML list. The second method extracts headers from the first CSV row and creates YAML objects with keys based on these headers. You can also customize the output YAML format by specifying the number of spaces for indenting YAML structures. If you need to perform the reverse conversion, that is, transform YAML into CSV, you can use our Convert YAML to CSV tool. Csv-abulous!"
|
||||
},
|
||||
"swapCsvColumns": {
|
||||
"title": "Swap CSV Columns",
|
||||
"description": "Just upload your CSV file in the form below, specify the columns to swap, and the tool will automatically change the positions of the specified columns in the output file. In the tool options, you can specify the column positions or names that you want to swap, as well as fix incomplete data and optionally remove empty records and records that have been commented out.",
|
||||
"shortDescription": "Reorder CSV columns."
|
||||
"shortDescription": "Reorder CSV columns.",
|
||||
"longDescription": "This tool reorganizes CSV data by swapping the positions of its columns. Swapping columns can enhance the readability of a CSV file by placing frequently used data together or in the front for easier data comparison and editing. For example, you can swap the first column with the last or swap the second column with the third. To swap columns based on their positions, select the"
|
||||
},
|
||||
"transposeCsv": {
|
||||
"title": "Transpose CSV",
|
||||
"description": "Just upload your CSV file in the form below, and this tool will automatically transpose your CSV. In the tool options, you can specify the character that starts the comment lines in the CSV to remove them. Additionally, if the CSV is incomplete (missing values), you can replace missing values with the empty character or a custom character.",
|
||||
"shortDescription": "Quickly transpose a CSV file."
|
||||
"shortDescription": "Quickly transpose a CSV file.",
|
||||
"longDescription": "This tool transposes Comma Separated Values (CSV). It treats the CSV as a matrix of data and flips all elements across the main diagonal. The output contains the same CSV data as the input, but now all the rows have become columns, and all the columns have become rows. After transposition, the CSV file will have opposite dimensions. For example, if the input file has 4 columns and 3 rows, the output file will have 3 columns and 4 rows. During conversion, the program also cleans the data from unnecessary lines and corrects incomplete data. Specifically, the tool automatically deletes all empty records and comments that begin with a specific character, which you can set in the option. Additionally, in cases where the CSV data is corrupted or lost, the utility completes the file with empty fields or custom fields that can be specified in the options. Csv-abulous!"
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:insertCsvColumns.title',
|
||||
description: 'csv:insertCsvColumns.description',
|
||||
shortDescription: 'csv:insertCsvColumns.shortDescription'
|
||||
},
|
||||
name: 'Insert CSV columns',
|
||||
path: 'insert-csv-columns',
|
||||
icon: 'hugeicons:column-insert',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:swapCsvColumns.title',
|
||||
description: 'csv:swapCsvColumns.description',
|
||||
shortDescription: 'csv:swapCsvColumns.shortDescription',
|
||||
longDescription: 'csv:swapCsvColumns.longDescription'
|
||||
},
|
||||
name: 'Swap CSV Columns',
|
||||
path: 'swap-csv-columns',
|
||||
icon: 'eva:swap-outline',
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('csv', {
|
||||
i18n: {
|
||||
name: 'csv:transposeCsv.title',
|
||||
description: 'csv:transposeCsv.description',
|
||||
shortDescription: 'csv:transposeCsv.shortDescription',
|
||||
longDescription: 'csv:transposeCsv.longDescription'
|
||||
},
|
||||
name: 'Transpose CSV',
|
||||
path: 'transpose-csv',
|
||||
icon: 'carbon:transpose',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:changeColors.title',
|
||||
description: 'image:changeColors.description',
|
||||
shortDescription: 'image:changeColors.shortDescription'
|
||||
},
|
||||
name: 'Change colors in image',
|
||||
path: 'change-colors',
|
||||
icon: 'cil:color-fill',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:changeOpacity.title',
|
||||
description: 'image:changeOpacity.description',
|
||||
shortDescription: 'image:changeOpacity.shortDescription'
|
||||
},
|
||||
name: 'Change image Opacity',
|
||||
path: 'change-opacity',
|
||||
icon: 'material-symbols:opacity',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:compress.title',
|
||||
description: 'image:compress.description',
|
||||
shortDescription: 'image:compress.shortDescription'
|
||||
},
|
||||
name: 'Compress Image',
|
||||
path: 'compress',
|
||||
component: lazy(() => import('./index')),
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:convertToJpg.title',
|
||||
description: 'image:convertToJpg.description',
|
||||
shortDescription: 'image:convertToJpg.shortDescription'
|
||||
},
|
||||
name: 'Convert Images to JPG',
|
||||
path: 'convert-to-jpg',
|
||||
icon: 'ph:file-jpg-thin',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:createTransparent.title',
|
||||
description: 'image:createTransparent.description',
|
||||
shortDescription: 'image:createTransparent.shortDescription'
|
||||
},
|
||||
name: 'Create transparent PNG',
|
||||
path: 'create-transparent',
|
||||
icon: 'mdi:circle-transparent',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:crop.title',
|
||||
description: 'image:crop.description',
|
||||
shortDescription: 'image:crop.shortDescription'
|
||||
},
|
||||
name: 'Crop',
|
||||
path: 'crop',
|
||||
icon: 'mdi:crop', // Iconify icon as a string
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:editor.title',
|
||||
description: 'image:editor.description',
|
||||
shortDescription: 'image:editor.shortDescription'
|
||||
},
|
||||
name: 'Image Editor',
|
||||
path: 'editor',
|
||||
icon: 'mdi:image-edit',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:imageToText.title',
|
||||
description: 'image:imageToText.description',
|
||||
shortDescription: 'image:imageToText.shortDescription'
|
||||
},
|
||||
name: 'Image to Text (OCR)',
|
||||
path: 'image-to-text',
|
||||
icon: 'mdi:text-recognition', // Iconify icon as a string
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:qrCode.title',
|
||||
description: 'image:qrCode.description',
|
||||
shortDescription: 'image:qrCode.shortDescription'
|
||||
},
|
||||
name: 'QR Code Generator',
|
||||
path: 'qr-code',
|
||||
icon: 'mdi:qrcode', // Iconify icon as a string
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:removeBackground.title',
|
||||
description: 'image:removeBackground.description',
|
||||
shortDescription: 'image:removeBackground.shortDescription'
|
||||
},
|
||||
name: 'Remove Background from Image',
|
||||
path: 'remove-background',
|
||||
icon: 'mdi:image-remove',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:resize.title',
|
||||
description: 'image:resize.description',
|
||||
shortDescription: 'image:resize.shortDescription'
|
||||
},
|
||||
name: 'Resize Image',
|
||||
path: 'resize',
|
||||
icon: 'mdi:resize', // Iconify icon as a string
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('image-generic', {
|
||||
i18n: {
|
||||
name: 'image:rotate.title',
|
||||
description: 'image:rotate.description',
|
||||
shortDescription: 'image:rotate.shortDescription'
|
||||
},
|
||||
name: 'Rotate Image',
|
||||
path: 'rotate',
|
||||
icon: 'mdi:rotate-clockwise',
|
||||
|
@@ -23,18 +23,76 @@
|
||||
"toolInfo": {
|
||||
"title": "Resize Image",
|
||||
"description": "This tool allows you to resize JPG, PNG, SVG, or GIF images. You can resize by specifying dimensions in pixels or by percentage, with options to maintain the original aspect ratio."
|
||||
}
|
||||
},
|
||||
"shortDescription": "Resize images easily."
|
||||
},
|
||||
"compress": {
|
||||
"title": "Compress Image",
|
||||
"description": "Reduce image file size while maintaining quality.",
|
||||
"inputTitle": "Input image",
|
||||
"resultTitle": "Compressed image"
|
||||
"resultTitle": "Compressed image",
|
||||
"shortDescription": "Compress images to reduce file size while maintaining reasonable quality."
|
||||
},
|
||||
"crop": {
|
||||
"title": "Crop Image",
|
||||
"description": "Crop images to remove unwanted areas.",
|
||||
"inputTitle": "Input image",
|
||||
"resultTitle": "Cropped image"
|
||||
"resultTitle": "Cropped image",
|
||||
"shortDescription": "Crop images quickly."
|
||||
},
|
||||
"changeColors": {
|
||||
"title": "Change colors in image",
|
||||
"description": "World",
|
||||
"shortDescription": "Quickly swap colors in a image"
|
||||
},
|
||||
"changeOpacity": {
|
||||
"title": "Change image Opacity",
|
||||
"description": "Easily adjust the transparency of your images. Simply upload your image, use the slider to set the desired opacity level between 0 (fully transparent) and 1 (fully opaque), and download the modified image.",
|
||||
"shortDescription": "Adjust transparency of images"
|
||||
},
|
||||
"convertToJpg": {
|
||||
"title": "Convert Images to JPG",
|
||||
"description": "Convert various image formats (PNG, GIF, TIF, PSD, SVG, WEBP, HEIC, RAW) to JPG with customizable quality and background color settings.",
|
||||
"shortDescription": "Convert images to JPG with quality control"
|
||||
},
|
||||
"createTransparent": {
|
||||
"title": "Create transparent PNG",
|
||||
"description": "World",
|
||||
"shortDescription": "Quickly make an image transparent"
|
||||
},
|
||||
"editor": {
|
||||
"title": "Image Editor",
|
||||
"description": "Advanced image editor with tools for cropping, rotating, annotating, adjusting colors, and adding watermarks. Edit your images with professional-grade tools directly in your browser.",
|
||||
"shortDescription": "Edit images with advanced tools and features"
|
||||
},
|
||||
"imageToText": {
|
||||
"title": "Image to Text (OCR)",
|
||||
"description": "Extract text from images (JPG, PNG) using optical character recognition (OCR).",
|
||||
"shortDescription": "Extract text from images using OCR."
|
||||
},
|
||||
"qrCode": {
|
||||
"title": "QR Code Generator",
|
||||
"description": "Generate QR codes for different data types: URL, Text, Email, Phone, SMS, WiFi, vCard, and more.",
|
||||
"shortDescription": "Create customized QR codes for various data formats."
|
||||
},
|
||||
"removeBackground": {
|
||||
"title": "Remove Background from Image",
|
||||
"description": "World",
|
||||
"shortDescription": "Automatically remove backgrounds from images"
|
||||
},
|
||||
"rotate": {
|
||||
"title": "Rotate Image",
|
||||
"description": "Rotate an image by a specified angle.",
|
||||
"shortDescription": "Rotate an image easily."
|
||||
},
|
||||
"compressPng": {
|
||||
"title": "Compress png",
|
||||
"description": "This is a program that compresses PNG pictures. As soon as you paste your PNG picture in the input area, the program will compress it and show the result in the output area. In the options, you can adjust the compression level, as well as find the old and new picture file sizes.",
|
||||
"shortDescription": "Quickly compress a PNG"
|
||||
},
|
||||
"convertJgpToPng": {
|
||||
"title": "Convert JPG to PNG",
|
||||
"description": "Quickly convert your JPG images to PNG. Just import your PNG image in the editor on the left",
|
||||
"shortDescription": "Quickly convert your JPG images to PNG"
|
||||
}
|
||||
}
|
||||
|
@@ -3,6 +3,11 @@ import { lazy } from 'react';
|
||||
// import image from '@assets/text.png';
|
||||
|
||||
export const tool = defineTool('png', {
|
||||
i18n: {
|
||||
name: 'image:compressPng.title',
|
||||
description: 'image:compressPng.description',
|
||||
shortDescription: 'image:compressPng.shortDescription'
|
||||
},
|
||||
name: 'Compress png',
|
||||
path: 'compress-png',
|
||||
icon: 'material-symbols-light:compress',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('png', {
|
||||
i18n: {
|
||||
name: 'image:convertJgpToPng.title',
|
||||
description: 'image:convertJgpToPng.description',
|
||||
shortDescription: 'image:convertJgpToPng.shortDescription'
|
||||
},
|
||||
name: 'Convert JPG to PNG',
|
||||
path: 'convert-jgp-to-png',
|
||||
icon: 'ph:file-jpg-thin',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('pdf', {
|
||||
i18n: {
|
||||
name: 'pdf:editor.title',
|
||||
description: 'pdf:editor.description',
|
||||
shortDescription: 'pdf:editor.shortDescription'
|
||||
},
|
||||
name: 'PDF Editor',
|
||||
path: 'editor',
|
||||
icon: 'mdi:file-document-edit',
|
||||
|
@@ -14,7 +14,6 @@
|
||||
"title": "Merge PDF Files",
|
||||
"description": "This tool allows you to combine multiple PDF files into a single document. You can choose how to sort the PDFs and the tool will merge them in the specified order."
|
||||
},
|
||||
"title": "Merge PDF",
|
||||
"shortDescription": "Merge multiple PDF files into a single document"
|
||||
},
|
||||
"splitPdf": {
|
||||
@@ -32,7 +31,6 @@
|
||||
"title": "Split PDF",
|
||||
"description": "This tool allows you to extract specific pages from a PDF document. You can specify individual pages or ranges of pages to extract."
|
||||
},
|
||||
"title": "Split PDF",
|
||||
"shortDescription": "Extract specific pages from a PDF file"
|
||||
},
|
||||
"rotatePdf": {
|
||||
@@ -58,8 +56,8 @@
|
||||
"title": "How to Use the Rotate PDF Tool",
|
||||
"description": "This tool allows you to rotate pages in a PDF document. You can rotate all pages or specify individual pages to rotate. Choose a rotation angle: 90° Clockwise, 180° (Upside down), or 270° (90° Counter-clockwise). To rotate specific pages, uncheck \"Apply to all pages\" and enter page numbers or ranges separated by commas (e.g., 1,3,5-7)."
|
||||
},
|
||||
"title": "Rotate PDF",
|
||||
"shortDescription": "Rotate pages in a PDF document"
|
||||
"shortDescription": "Rotate pages in a PDF document",
|
||||
"longDescription": "Change the orientation of PDF pages by rotating them 90, 180, or 270 degrees. Useful for fixing incorrectly scanned documents or preparing PDFs for printing."
|
||||
},
|
||||
"compressPdf": {
|
||||
"inputTitle": "Input PDF",
|
||||
@@ -104,7 +102,8 @@
|
||||
"pdfToPng": {
|
||||
"title": "PDF to PNG",
|
||||
"description": "Transform PDF documents into PNG panels.",
|
||||
"shortDescription": "Convert PDF into PNG images"
|
||||
"shortDescription": "Convert PDF into PNG images",
|
||||
"longDescription": "Upload a PDF and convert each page into a high-quality PNG image directly in your browser. This tool is ideal for extracting visual content or sharing individual pages. No data is uploaded — everything runs locally."
|
||||
},
|
||||
"protectPdf": {
|
||||
"title": "Protect PDF",
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('pdf', {
|
||||
i18n: {
|
||||
name: 'pdf:pdfToPng.title',
|
||||
description: 'pdf:pdfToPng.description',
|
||||
shortDescription: 'pdf:pdfToPng.shortDescription',
|
||||
longDescription: 'pdf:pdfToPng.longDescription'
|
||||
},
|
||||
name: 'PDF to PNG',
|
||||
path: 'pdf-to-png',
|
||||
icon: 'mdi:image-multiple', // Iconify icon ID
|
||||
|
@@ -2,6 +2,12 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('pdf', {
|
||||
i18n: {
|
||||
name: 'pdf:rotatePdf.title',
|
||||
description: 'pdf:rotatePdf.description',
|
||||
shortDescription: 'pdf:rotatePdf.shortDescription',
|
||||
longDescription: 'pdf:rotatePdf.longDescription'
|
||||
},
|
||||
name: 'Rotate PDF',
|
||||
path: 'rotate-pdf',
|
||||
icon: 'carbon:rotate',
|
||||
|
@@ -174,7 +174,8 @@
|
||||
"toolInfo": {
|
||||
"title": "Text Replacer",
|
||||
"description": "Easily replace specific text in your content with this simple, browser-based tool. Just input your text, set the text you want to replace and the replacement value, and instantly get the updated version."
|
||||
}
|
||||
},
|
||||
"shortDescription": "Quickly replace text in your content"
|
||||
},
|
||||
"reverse": {
|
||||
"reversalOptions": "Reversal options",
|
||||
|
@@ -3,6 +3,11 @@ import { lazy } from 'react';
|
||||
// import image from '@assets/text.png';
|
||||
|
||||
export const tool = defineTool('string', {
|
||||
i18n: {
|
||||
name: 'string:rot13.title',
|
||||
description: 'string:rot13.description',
|
||||
shortDescription: 'string:rot13.shortDescription'
|
||||
},
|
||||
name: 'Rot13',
|
||||
path: 'rot13',
|
||||
icon: 'hugeicons:encrypt',
|
||||
|
@@ -3,6 +3,11 @@ import { lazy } from 'react';
|
||||
// import image from '@assets/text.png';
|
||||
|
||||
export const tool = defineTool('string', {
|
||||
i18n: {
|
||||
name: 'string:rotate.title',
|
||||
description: 'string:rotate.description',
|
||||
shortDescription: 'string:rotate.shortDescription'
|
||||
},
|
||||
name: 'Rotate',
|
||||
path: 'rotate',
|
||||
icon: 'carbon:rotate',
|
||||
|
@@ -2,6 +2,11 @@ import { defineTool } from '@tools/defineTool';
|
||||
import { lazy } from 'react';
|
||||
|
||||
export const tool = defineTool('string', {
|
||||
i18n: {
|
||||
name: 'string:textReplacer.title',
|
||||
description: 'string:textReplacer.description',
|
||||
shortDescription: 'string:textReplacer.shortDescription'
|
||||
},
|
||||
name: 'Text Replacer',
|
||||
path: 'replacer',
|
||||
shortDescription: 'Quickly replace text in your content',
|
||||
|
@@ -12,7 +12,7 @@ export interface ToolMeta {
|
||||
description: string;
|
||||
shortDescription: string;
|
||||
longDescription?: string;
|
||||
i18n?: {
|
||||
i18n: {
|
||||
name: FullI18nKey;
|
||||
description: FullI18nKey;
|
||||
shortDescription: FullI18nKey;
|
||||
|
Reference in New Issue
Block a user