feat: add internationalization support

This commit is contained in:
AshAnand34
2025-07-12 23:02:35 -07:00
parent 3b702b260c
commit f22bb8bd57
149 changed files with 2807 additions and 1045 deletions

View File

@@ -2,14 +2,17 @@ import { defineTool } from '@tools/defineTool';
import { lazy } from 'react';
export const tool = defineTool('csv', {
name: 'Change CSV separator',
name: 'Change CSV Separator',
path: 'change-csv-separator',
icon: 'material-symbols:split-scene-rounded',
icon: 'material-symbols:code',
description:
'Just upload your CSV file in the form below and it will automatically get a new column delimiter character. In the tool options, you can specify which delimiter and quote characters are used in the source CSV file and customize the desired delimiter and quote characters for the output CSV. You can also filter the input CSV before the conversion process and skip blank lines and comment lines.',
shortDescription: 'Quickly change the CSV column delimiter to a new symbol.',
keywords: ['change', 'csv', 'sepa rator'],
longDescription:
'This tool changes the field separator in CSV (Comma Separated Values) files. This is useful because different programs may use different default separators. While a comma is the most common separator in CSV files, some programs require files to be tab-separated (TSV), semicolon-separated (SSV), pipe-separated (PSV), or have another separation symbol. The default comma may not be so convenient as a delimiter in CSV files because commas are frequently present within fields. In such cases, it can be difficult and confusing to distinguish between commas as delimiters and commas as punctuation symbols. By replacing the comma with another delimiter, you can convert the file into a more easily readable and parsable format. In the options section of this tool, you can configure both the input and output CSV file formats. For the input CSV, you can specify its current delimiter (by default, it is a comma) and also indicate the quotation mark character used to wrap fields. For the output CSV, you can set a new delimiter, choose a new quotation mark character, and optionally enclose all the fields in quotes. Additionally, you have the option to remove empty lines from the input CSV and eliminate comment lines that start with a specified character (usually a hash "#" or double slashes "//"). Csv-abulous!',
component: lazy(() => import('./index'))
'Change the delimiter/separator in CSV files. Convert between different CSV formats like comma, semicolon, tab, or custom separators.',
shortDescription: 'Change CSV file delimiter',
keywords: ['csv', 'separator', 'delimiter', 'change'],
component: lazy(() => import('./index')),
i18n: {
name: 'csv.changeCsvSeparator.name',
description: 'csv.changeCsvSeparator.description',
shortDescription: 'csv.changeCsvSeparator.shortDescription'
}
});

View File

@@ -6,10 +6,9 @@ import { convertCsvToJson } from './service';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { Box } from '@mui/material';
import RadioWithTextField from '@components/options/RadioWithTextField';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { useTranslation } from 'react-i18next';
type InitialValuesType = {
delimiter: string;
@@ -114,6 +113,7 @@ id,name,active
];
export default function CsvToJson({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -148,28 +148,36 @@ export default function CsvToJson({ title }: ToolComponentProps) {
compute={compute}
exampleCards={exampleCards}
inputComponent={
<ToolTextInput title="Input CSV" value={input} onChange={setInput} />
<ToolTextInput
title={t('csv.csvToJson.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title="Output JSON" value={result} extension={'json'} />
<ToolTextResult
title={t('csv.csvToJson.resultTitle')}
value={result}
extension={'json'}
/>
}
getGroups={({ values, updateField }) => [
{
title: 'Input CSV Format',
title: t('csv.csvToJson.inputCsvFormat'),
component: (
<Box>
<TextFieldWithDesc
description="Column Separator"
description={t('csv.csvToJson.columnSeparator')}
value={values.delimiter}
onOwnChange={(val) => updateField('delimiter', val)}
/>
<TextFieldWithDesc
description="Field Quote"
description={t('csv.csvToJson.fieldQuote')}
onOwnChange={(val) => updateField('quote', val)}
value={values.quote}
/>
<TextFieldWithDesc
description="Comment Symbol"
description={t('csv.csvToJson.commentSymbol')}
value={values.comment}
onOwnChange={(val) => updateField('comment', val)}
/>
@@ -177,26 +185,26 @@ export default function CsvToJson({ title }: ToolComponentProps) {
)
},
{
title: 'Conversion Options',
title: t('csv.csvToJson.conversionOptions'),
component: (
<Box>
<CheckboxWithDesc
checked={values.useHeaders}
onChange={(value) => updateField('useHeaders', value)}
title="Use Headers"
description="First row is treated as column headers"
title={t('csv.csvToJson.useHeaders')}
description={t('csv.csvToJson.useHeadersDescription')}
/>
<CheckboxWithDesc
checked={values.skipEmptyLines}
onChange={(value) => updateField('skipEmptyLines', value)}
title="Skip Empty Lines"
description="Don't process empty lines in the CSV"
title={t('csv.csvToJson.skipEmptyLines')}
description={t('csv.csvToJson.skipEmptyLinesDescription')}
/>
<CheckboxWithDesc
checked={values.dynamicTypes}
onChange={(value) => updateField('dynamicTypes', value)}
title="Dynamic Types"
description="Convert numbers and booleans to their proper types"
title={t('csv.csvToJson.dynamicTypes')}
description={t('csv.csvToJson.dynamicTypesDescription')}
/>
</Box>
)

View File

@@ -10,6 +10,7 @@ import { findIncompleteCsvRecords } from './service';
import { InitialValuesType } from './types';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { useTranslation } from 'react-i18next';
const initialValues: InitialValuesType = {
csvSeparator: ',',
@@ -103,6 +104,7 @@ export default function FindIncompleteCsvRecords({
title,
longDescription
}: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -115,55 +117,59 @@ export default function FindIncompleteCsvRecords({
updateField
}) => [
{
title: 'Csv input Options',
title: t('csv.findIncompleteCsvRecords.csvInputOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.csvSeparator}
onOwnChange={(val) => updateField('csvSeparator', val)}
description={
'Enter the character used to delimit columns in the CSV input file.'
}
description={t(
'csv.findIncompleteCsvRecords.csvSeparatorDescription'
)}
/>
<TextFieldWithDesc
value={values.quoteCharacter}
onOwnChange={(val) => updateField('quoteCharacter', val)}
description={
'Enter the quote character used to quote the CSV input fields.'
}
description={t(
'csv.findIncompleteCsvRecords.quoteCharacterDescription'
)}
/>
<TextFieldWithDesc
value={values.commentCharacter}
onOwnChange={(val) => updateField('commentCharacter', val)}
description={
'Enter the character indicating the start of a comment line. Lines starting with this symbol will be skipped.'
}
description={t(
'csv.findIncompleteCsvRecords.commentCharacterDescription'
)}
/>
</Box>
)
},
{
title: 'Checking Options',
title: t('csv.findIncompleteCsvRecords.checkingOptions'),
component: (
<Box>
<CheckboxWithDesc
checked={values.emptyLines}
onChange={(value) => updateField('emptyLines', value)}
title="Delete Lines with No Data"
description="Remove empty lines from CSV input file."
title={t('csv.findIncompleteCsvRecords.deleteLinesWithNoData')}
description={t(
'csv.findIncompleteCsvRecords.deleteLinesWithNoDataDescription'
)}
/>
<CheckboxWithDesc
checked={values.emptyValues}
onChange={(value) => updateField('emptyValues', value)}
title="Find Empty Values"
description="Display a message about CSV fields that are empty (These are not missing fields but fields that contain nothing)."
title={t('csv.findIncompleteCsvRecords.findEmptyValues')}
description={t(
'csv.findIncompleteCsvRecords.findEmptyValuesDescription'
)}
/>
<CheckboxWithDesc
checked={values.messageLimit}
onChange={(value) => updateField('messageLimit', value)}
title="Limit number of messages"
title={t('csv.findIncompleteCsvRecords.limitNumberOfMessages')}
/>
{values.messageLimit && (
@@ -172,7 +178,9 @@ export default function FindIncompleteCsvRecords({
onOwnChange={(val) => updateField('messageNumber', Number(val))}
type="number"
inputProps={{ min: 1 }}
description={'Set the limit of number of messages in the output.'}
description={t(
'csv.findIncompleteCsvRecords.messageLimitDescription'
)}
/>
)}
</Box>
@@ -184,15 +192,27 @@ export default function FindIncompleteCsvRecords({
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input CSV'} value={input} onChange={setInput} />
<ToolTextInput
title={t('csv.findIncompleteCsvRecords.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult
title={t('csv.findIncompleteCsvRecords.resultTitle')}
value={result}
/>
}
resultComponent={<ToolTextResult title={'CSV Status'} value={result} />}
initialValues={initialValues}
exampleCards={exampleCards}
getGroups={getGroups}
setInput={setInput}
compute={compute}
toolInfo={{ title: `What is a ${title}?`, description: longDescription }}
toolInfo={{
title: t('csv.findIncompleteCsvRecords.toolInfo.title', { title }),
description: longDescription
}}
/>
);
}

View File

@@ -11,6 +11,11 @@ export const tool = defineTool('csv', {
'Quickly find rows and columns in CSV that are missing values.',
keywords: ['find', 'incomplete', 'csv', 'records'],
longDescription:
'This tool checks the completeness of CSV (Comma Separated Values) files and identifies incomplete records within the data. It finds rows and columns where one or more values are missing and displays their positions in the output so that you can quickly find and fix your CSV file. A valid CSV file has the same number of values (fields) in all rows and the same number of values (fields) in all columns. If the CSV you load in this tool is complete, the program will notify you with a green badge. If at least one value is missing in any row or column, the program will show a red badge and indicate the exact location of the missing value. If the CSV file has a field with no characters in it, then such a field is called an empty field. It is not a missing field, just empty as it contains nothing. You can activate the "Find Empty Values" checkbox in the options to identify all such fields in the CSV. If the file contains empty lines, you can ignore them with the "Skip Empty Lines" option or check them for completeness along with other lines. You can also configure the delimiter, quote, and comment characters in the options. This allows you to adapt to other file formats besides CSV, such as TSV (Tab Separated Values), SSV (Semicolon Separated Values), or PSV (Pipe Separated Values). If the file has too many incomplete or empty records, you can set a limit on the output messages to display, for example, 5, 10, or 20 messages. If you want to quickly fill in the missing data with default values, you can use our Fill Incomplete CSV Records tool. Csv-abulous!',
component: lazy(() => import('./index'))
'This tool allows you to find incomplete or missing records in CSV data. It can detect missing columns, empty values, and other data quality issues in your CSV files. You can customize the CSV parsing options and set limits on error reporting.',
component: lazy(() => import('./index')),
i18n: {
name: 'csv.findIncompleteCsvRecords.name',
description: 'csv.findIncompleteCsvRecords.description',
shortDescription: 'csv.findIncompleteCsvRecords.shortDescription'
}
});

View File

@@ -0,0 +1,63 @@
{
"csvToJson": {
"title": "CSV to JSON",
"description": "Convert CSV data to JSON format.",
"inputTitle": "Input CSV",
"resultTitle": "JSON Output",
"csvOptions": "CSV Options",
"separatorDescription": "Character used to separate columns",
"quoteCharDescription": "Character used to quote fields",
"commentCharDescription": "Character that indicates comment lines",
"jsonOptions": "JSON Options",
"prettyPrintDescription": "Format JSON with indentation",
"toolInfo": {
"title": "CSV to JSON Converter",
"description": "This tool allows you to convert CSV (Comma-Separated Values) data to JSON format. You can customize the CSV parsing options and JSON output format."
}
},
"findIncompleteCsvRecords": {
"title": "Find Incomplete CSV Records",
"description": "Identify CSV records with missing or incomplete data.",
"inputTitle": "Input CSV",
"resultTitle": "Incomplete Records",
"csvOptions": "CSV Options",
"separatorDescription": "Character used to separate columns",
"quoteCharDescription": "Character used to quote fields",
"commentCharDescription": "Character that indicates comment lines",
"toolInfo": {
"title": "Find Incomplete CSV Records",
"description": "This tool helps you identify CSV records that have missing or incomplete data. It's useful for data validation and cleaning."
}
},
"insertCsvColumns": {
"title": "Insert CSV Columns",
"description": "Add new columns to CSV data at specified positions.",
"inputTitle": "Input CSV",
"resultTitle": "Output CSV",
"csvToInsert": "CSV to insert",
"csvSeparator": "CSV separator",
"csvToInsertDescription": "Enter one or more columns you want to insert into the CSV. the character used to delimit columns has to be the same with the one in the CSV input file. Ps: Blank lines will be ignored",
"csvOptions": "CSV Options",
"separatorDescription": "Enter the character used to delimit columns in the CSV input file.",
"quoteCharDescription": "Enter the quote character used to quote the CSV input fields.",
"commentCharacterDescription": "Enter the character indicating the start of a comment line. Lines starting with this symbol will be skipped.",
"fillWithEmptyValues": "Fill With Empty Values",
"fillWithCustomValues": "Fill With Customs Values",
"customFillDescription": "If the input CSV file is incomplete (missing values), then add empty fields or custom symbols to records to make a well-formed CSV?",
"customFillValueDescription": "Use this custom value to fill in missing fields. (Works only with \"Custom Values\" mode above.)",
"positionOptions": "Position Options",
"prependColumns": "Prepend columns",
"appendColumns": "Append columns",
"customPosition": "Custom position",
"insertingPositionDescription": "Specify where to insert the columns in the CSV file.",
"headerName": "Header name",
"position": "Position",
"customPositionOptionsDescription": "Select the method to insert the columns in the CSV file.",
"headerNameDescription": "Header of the column you want to insert columns after.",
"rowNumberDescription": "Number of the column you want to insert columns after.",
"toolInfo": {
"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."
}
}
}

View File

@@ -1,16 +1,17 @@
import { Box } from '@mui/material';
import React, { useState } from 'react';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import ToolTextInput from '@components/input/ToolTextInput';
import ToolTextResult from '@components/result/ToolTextResult';
import { GetGroupsType } from '@components/options/ToolOptions';
import { CardExampleType } from '@components/examples/ToolExamples';
import { main } from './service';
import { getCsvHeaders } from '@utils/csv';
import { InitialValuesType } from './types';
import { GetGroupsType } from '@components/options/ToolOptions';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SelectWithDesc from '@components/options/SelectWithDesc';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import { getCsvHeaders } from '@utils/csv';
import { useTranslation } from 'react-i18next';
const initialValues: InitialValuesType = {
csvToInsert: '',
@@ -27,15 +28,19 @@ const initialValues: InitialValuesType = {
const exampleCards: CardExampleType<InitialValuesType>[] = [
{
title: 'Add One Column to a CSV File',
title: 'Insert a single column by position',
description:
'In this example, we insert a column with the title "city" into a CSV file that already contains two other columns with titles "name" and "age". The new column consists of three values: "city", "dallas", and "houston", corresponding to the height of the input CSV data. The value "city" is the header value (appearing on the first row) and values "dallas" and "houston" are data values (appearing on rows two and three). We specify the position of the new column by an ordinal number and set it to 1 in the options. This value indicates that the new "city" column should be placed after the first column.',
sampleText: `name,age
john,25
emma,22`,
sampleResult: `name,city,age
john,dallas,25
emma,houston,22`,
'In this example, we insert a single column "city" at position 1 in the CSV data. The input CSV has data about cars, including the "Brand" and "Model" of the car. We now add a "city" column at position 1. To do this, we enter the city data in the comma-separated format in the "New Column" option, and to quickly add the new column at position 1, then we specify the position number.',
sampleText: `Brand,Model
Toyota,Camry
Ford,Mustang
Honda,Accord
Chevrolet,Malibu`,
sampleResult: `city,Brand,Model
dallas,Toyota,Camry
houston,Ford,Mustang
dallas,Honda,Accord
houston,Chevrolet,Malibu`,
sampleOptions: {
csvToInsert: `city
dallas
@@ -118,6 +123,7 @@ export default function InsertCsvColumns({
title,
longDescription
}: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -139,7 +145,7 @@ export default function InsertCsvColumns({
updateField
}) => [
{
title: 'CSV to insert',
title: t('csv.insertCsvColumns.csvToInsert'),
component: (
<Box>
<TextFieldWithDesc
@@ -147,44 +153,42 @@ export default function InsertCsvColumns({
rows={3}
value={values.csvToInsert}
onOwnChange={(val) => updateField('csvToInsert', val)}
title="CSV separator"
description={`Enter one or more columns you want to insert into the CSV.
the character used to delimit columns has to be the same with the one in the CSV input file.
Ps: Blank lines will be ignored`}
title={t('csv.insertCsvColumns.csvSeparator')}
description={t('csv.insertCsvColumns.csvToInsertDescription')}
/>
</Box>
)
},
{
title: 'CSV Options',
title: t('csv.insertCsvColumns.csvOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.separator}
onOwnChange={(val) => updateField('separator', val)}
description={
'Enter the character used to delimit columns in the CSV input file.'
}
description={t('csv.insertCsvColumns.separatorDescription')}
/>
<TextFieldWithDesc
value={values.quoteChar}
onOwnChange={(val) => updateField('quoteChar', val)}
description={
'Enter the quote character used to quote the CSV input fields.'
}
description={t('csv.insertCsvColumns.quoteCharDescription')}
/>
<TextFieldWithDesc
value={values.commentCharacter}
onOwnChange={(val) => updateField('commentCharacter', val)}
description={
'Enter the character indicating the start of a comment line. Lines starting with this symbol will be skipped.'
}
description={t('csv.insertCsvColumns.commentCharacterDescription')}
/>
<SelectWithDesc
selected={values.customFill}
options={[
{ label: 'Fill With Empty Values', value: false },
{ label: 'Fill With Customs Values', value: true }
{
label: t('csv.insertCsvColumns.fillWithEmptyValues'),
value: false
},
{
label: t('csv.insertCsvColumns.fillWithCustomValues'),
value: true
}
]}
onChange={(value) => {
updateField('customFill', value);
@@ -192,48 +196,59 @@ export default function InsertCsvColumns({
updateField('customFillValue', ''); // Reset custom fill value
}
}}
description={
'If the input CSV file is incomplete (missing values), then add empty fields or custom symbols to records to make a well-formed CSV?'
}
description={t('csv.insertCsvColumns.customFillDescription')}
/>
{values.customFill && (
<TextFieldWithDesc
value={values.customFillValue}
onOwnChange={(val) => updateField('customFillValue', val)}
description={
'Use this custom value to fill in missing fields. (Works only with "Custom Values" mode above.)'
}
description={t('csv.insertCsvColumns.customFillValueDescription')}
/>
)}
</Box>
)
},
{
title: 'Position Options',
title: t('csv.insertCsvColumns.positionOptions'),
component: (
<Box>
<SelectWithDesc
selected={values.insertingPosition}
options={[
{ label: 'Prepend columns', value: 'prepend' },
{ label: 'Append columns', value: 'append' },
{ label: 'Custom position', value: 'custom' }
{
label: t('csv.insertCsvColumns.prependColumns'),
value: 'prepend'
},
{
label: t('csv.insertCsvColumns.appendColumns'),
value: 'append'
},
{
label: t('csv.insertCsvColumns.customPosition'),
value: 'custom'
}
]}
onChange={(value) => updateField('insertingPosition', value)}
description={'Specify where to insert the columns in the CSV file.'}
description={t('csv.insertCsvColumns.insertingPositionDescription')}
/>
{values.insertingPosition === 'custom' && (
<SelectWithDesc
selected={values.customPostionOptions}
options={[
{ label: 'Header name', value: 'headerName' },
{ label: 'Position ', value: 'rowNumber' }
{
label: t('csv.insertCsvColumns.headerName'),
value: 'headerName'
},
{
label: t('csv.insertCsvColumns.position'),
value: 'rowNumber'
}
]}
onChange={(value) => updateField('customPostionOptions', value)}
description={
'Select the method to insert the columns in the CSV file.'
}
description={t(
'csv.insertCsvColumns.customPositionOptionsDescription'
)}
/>
)}
@@ -243,42 +258,53 @@ export default function InsertCsvColumns({
selected={values.headerName}
options={headerOptions}
onChange={(value) => updateField('headerName', value)}
description={
'Header of the column you want to insert columns after.'
}
description={t('csv.insertCsvColumns.headerNameDescription')}
/>
)}
{values.insertingPosition === 'custom' &&
values.customPostionOptions === 'rowNumber' && (
<TextFieldWithDesc
value={values.rowNumber}
onOwnChange={(val) => updateField('rowNumber', Number(val))}
inputProps={{ min: 1, max: headers.length }}
type="number"
description={
'Number of the column you want to insert columns after.'
value={values.rowNumber.toString()}
onOwnChange={(val) =>
updateField('rowNumber', parseInt(val) || 0)
}
description={t('csv.insertCsvColumns.rowNumberDescription')}
type="number"
/>
)}
</Box>
)
}
];
return (
<ToolContent
title={title}
input={input}
inputComponent={
<ToolTextInput value={input} title="Input CSV" onChange={setInput} />
<ToolTextInput
title={t('csv.insertCsvColumns.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult
title={t('csv.insertCsvColumns.resultTitle')}
value={result}
extension={'csv'}
/>
}
resultComponent={<ToolTextResult title="Output CSV" value={result} />}
initialValues={initialValues}
exampleCards={exampleCards}
getGroups={getGroups}
setInput={setInput}
compute={compute}
toolInfo={{ title: `What is a ${title}?`, description: longDescription }}
input={input}
setInput={setInput}
toolInfo={{
title: t('csv.insertCsvColumns.toolInfo.title'),
description: t('csv.insertCsvColumns.toolInfo.description')
}}
exampleCards={exampleCards}
/>
);
}