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

@@ -11,6 +11,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
@@ -101,6 +102,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
];
export default function Duplicate({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -134,55 +136,53 @@ export default function Duplicate({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Split Options',
title: t('list.duplicate.splitOptions'),
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
title={t('list.duplicate.splitBySymbol')}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
title={t('list.duplicate.splitByRegex')}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
description={t('list.duplicate.splitSeparatorDescription')}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the duplicated list'}
description={t('list.duplicate.joinSeparatorDescription')}
/>
</Box>
)
},
{
title: 'Duplication Options',
title: t('list.duplicate.duplicationOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.copy}
onOwnChange={(val) => updateField('copy', val)}
description={'Number of copies (can be fractional)'}
description={t('list.duplicate.copyDescription')}
type="number"
/>
<CheckboxWithDesc
title={'Concatenate'}
title={t('list.duplicate.concatenate')}
checked={values.concatenate}
onChange={(checked) => updateField('concatenate', checked)}
description={
'Concatenate copies (if unchecked, items will be interweaved)'
}
description={t('list.duplicate.concatenateDescription')}
/>
<CheckboxWithDesc
title={'Reverse'}
title={t('list.duplicate.reverse')}
checked={values.reverse}
onChange={(checked) => updateField('reverse', checked)}
description={'Reverse the duplicated items'}
description={t('list.duplicate.reverseDescription')}
/>
</Box>
)
@@ -193,18 +193,24 @@ export default function Duplicate({ title }: ToolComponentProps) {
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
<ToolTextInput
title={t('list.duplicate.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title="Duplicated List" value={result} />
<ToolTextResult
title={t('list.duplicate.resultTitle')}
value={result}
/>
}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Duplication',
description:
"This tool allows you to duplicate items in a list. You can specify the number of copies (including fractional values), control whether items are concatenated or interweaved, and even reverse the duplicated items. It's useful for creating repeated patterns, generating test data, or expanding lists with predictable content."
title: t('list.duplicate.toolInfo.title'),
description: t('list.duplicate.toolInfo.description')
}}
exampleCards={exampleCards}
input={input}

View File

@@ -5,10 +5,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Duplicate',
path: 'duplicate',
icon: 'mdi:content-duplicate',
icon: 'material-symbols-light:content-copy',
description:
'A tool to duplicate each item in a list a specified number of times. Perfect for creating repeated patterns, test data, or expanding datasets.',
shortDescription: 'Repeat items in a list multiple times.',
"World's simplest browser-based utility for duplicating list items. Input your list and specify duplication criteria to create copies of items. Perfect for data expansion, testing, or creating repeated patterns.",
shortDescription: 'Duplicate list items with specified criteria',
keywords: ['duplicate'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.duplicate.name',
description: 'list.duplicate.description',
shortDescription: 'list.duplicate.shortDescription'
}
});

View File

@@ -5,10 +5,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Find most popular',
path: 'find-most-popular',
icon: 'material-symbols-light:query-stats',
icon: 'material-symbols-light:trending-up',
description:
'A tool to identify and count the most frequently occurring items in a list. Useful for data analysis, finding trends, or identifying common elements.',
shortDescription: 'Find most common items in a list.',
"World's simplest browser-based utility for finding the most popular items in a list. Input your list and instantly get the items that appear most frequently. Perfect for data analysis, trend identification, or finding common elements.",
shortDescription: 'Find most frequently occurring items',
keywords: ['find', 'most', 'popular'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.findMostPopular.name',
description: 'list.findMostPopular.description',
shortDescription: 'list.findMostPopular.shortDescription'
}
});

View File

@@ -7,6 +7,7 @@ import { findUniqueCompute, SplitOperatorType } from './service';
import SimpleRadio from '@components/options/SimpleRadio';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -35,6 +36,7 @@ const splitOperators: {
];
export default function FindUnique() {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -64,18 +66,27 @@ export default function FindUnique() {
return (
<ToolContent
title="Find Unique"
title={t('list.findUnique.title')}
initialValues={initialValues}
compute={compute}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('list.findUnique.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult
title={t('list.findUnique.resultTitle')}
value={result}
/>
}
resultComponent={<ToolTextResult title={'Unique items'} value={result} />}
getGroups={({ values, updateField }) => [
{
title: 'Input List Delimiter',
title: t('list.findUnique.inputListDelimiter'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
@@ -88,7 +99,7 @@ export default function FindUnique() {
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('list.findUnique.delimiterDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -96,7 +107,7 @@ export default function FindUnique() {
)
},
{
title: 'Output List Delimiter',
title: t('list.findUnique.outputListDelimiter'),
component: (
<Box>
<TextFieldWithDesc
@@ -104,18 +115,14 @@ export default function FindUnique() {
onOwnChange={(value) => updateField('joinSeparator', value)}
/>
<CheckboxWithDesc
title={'Trim top list items'}
description={
'Remove leading and trailing spaces before comparing items'
}
title={t('list.findUnique.trimItems')}
description={t('list.findUnique.trimItemsDescription')}
checked={values.trimItems}
onChange={(value) => updateField('trimItems', value)}
/>
<CheckboxWithDesc
title={'Skip empty items'}
description={
"Don't include the empty list items in the output."
}
title={t('list.findUnique.skipEmptyItems')}
description={t('list.findUnique.skipEmptyItemsDescription')}
checked={values.deleteEmptyItems}
onChange={(value) => updateField('deleteEmptyItems', value)}
/>
@@ -123,22 +130,20 @@ export default function FindUnique() {
)
},
{
title: 'Unique Item Options',
title: t('list.findUnique.uniqueItemOptions'),
component: (
<Box>
<CheckboxWithDesc
title={'Find Absolutely Unique Items'}
description={
'Display only those items of the list that exist in a single copy.'
}
title={t('list.findUnique.findAbsolutelyUniqueItems')}
description={t(
'list.findUnique.findAbsolutelyUniqueItemsDescription'
)}
checked={values.absolutelyUnique}
onChange={(value) => updateField('absolutelyUnique', value)}
/>
<CheckboxWithDesc
title={'Case Sensitive Items'}
description={
'Output items with different case as unique elements in the list.'
}
title={t('list.findUnique.caseSensitiveItems')}
description={t('list.findUnique.caseSensitiveItemsDescription')}
checked={values.caseSensitive}
onChange={(value) => updateField('caseSensitive', value)}
/>

View File

@@ -4,9 +4,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Find unique',
path: 'find-unique',
icon: 'mynaui:one',
description: "World's simplest browser-based utility for finding unique items in a list. Just input your list with any separator, and it will automatically identify and extract unique items. Perfect for removing duplicates, finding distinct values, or analyzing data uniqueness. You can customize the input/output separators and choose whether to preserve the original order.",
icon: 'material-symbols-light:search',
description:
"World's simplest browser-based utility for finding unique items in a list. Input your list and instantly get all unique values with duplicates removed. Perfect for data cleaning, deduplication, or finding distinct elements.",
shortDescription: 'Find unique items in a list',
keywords: ['find', 'unique'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.findUnique.name',
description: 'list.findUnique.description',
shortDescription: 'list.findUnique.shortDescription'
}
});

View File

@@ -9,6 +9,7 @@ import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import { formatNumber } from '../../../../utils/number';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -40,6 +41,7 @@ const splitOperators: {
];
export default function FindUnique({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -78,28 +80,34 @@ export default function FindUnique({ title }: ToolComponentProps) {
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('list.group.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Grouped items'} value={result} />
<ToolTextResult title={t('list.group.resultTitle')} value={result} />
}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Input Item Separator',
title: t('list.group.inputItemSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitOperatorType', type)}
title={title}
description={description}
title={t(`list.group.splitOperators.${type}.title`)}
description={t(
`list.group.splitOperators.${type}.description`
)}
checked={values.splitOperatorType === type}
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('list.group.splitSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -107,12 +115,12 @@ export default function FindUnique({ title }: ToolComponentProps) {
)
},
{
title: 'Group Size and Separators',
title: t('list.group.groupSizeAndSeparators'),
component: (
<Box>
<TextFieldWithDesc
value={values.groupNumber}
description={'Number of items in a group'}
description={t('list.group.groupNumberDescription')}
type={'number'}
onOwnChange={(value) =>
updateField('groupNumber', formatNumber(value, 1))
@@ -120,52 +128,46 @@ export default function FindUnique({ title }: ToolComponentProps) {
/>
<TextFieldWithDesc
value={values.itemSeparator}
description={'Item separator character'}
description={t('list.group.itemSeparatorDescription')}
onOwnChange={(value) => updateField('itemSeparator', value)}
/>
<TextFieldWithDesc
value={values.groupSeparator}
description={'Group separator character'}
description={t('list.group.groupSeparatorDescription')}
onOwnChange={(value) => updateField('groupSeparator', value)}
/>
<TextFieldWithDesc
value={values.leftWrap}
description={"Group's left wrap symbol."}
description={t('list.group.leftWrapDescription')}
onOwnChange={(value) => updateField('leftWrap', value)}
/>
<TextFieldWithDesc
value={values.rightWrap}
description={"Group's right wrap symbol."}
description={t('list.group.rightWrapDescription')}
onOwnChange={(value) => updateField('rightWrap', value)}
/>
</Box>
)
},
{
title: 'Empty Items and Padding',
title: t('list.group.emptyItemsAndPadding'),
component: (
<Box>
<CheckboxWithDesc
title={'Delete Empty Items'}
description={
"Ignore empty items and don't include them in the groups."
}
title={t('list.group.deleteEmptyItems')}
description={t('list.group.deleteEmptyItemsDescription')}
checked={values.deleteEmptyItems}
onChange={(value) => updateField('deleteEmptyItems', value)}
/>
<CheckboxWithDesc
title={'Pad Non-full Groups'}
description={
'Fill non-full groups with a custom item (enter below).'
}
title={t('list.group.padNonFullGroups')}
description={t('list.group.padNonFullGroupsDescription')}
checked={values.padNonFullGroup}
onChange={(value) => updateField('padNonFullGroup', value)}
/>
<TextFieldWithDesc
value={values.paddingChar}
description={
'Use this character or item to pad non-full groups.'
}
description={t('list.group.paddingCharDescription')}
onOwnChange={(value) => updateField('paddingChar', value)}
/>
</Box>

View File

@@ -5,8 +5,14 @@ export const tool = defineTool('list', {
name: 'Group',
path: 'group',
icon: 'pajamas:group',
description: "World's simplest browser-based utility for grouping list items. Input your list and specify grouping criteria to organize items into logical groups. Perfect for categorizing data, organizing information, or creating structured lists. Supports custom separators and various grouping options.",
description:
"World's simplest browser-based utility for grouping list items. Input your list and specify grouping criteria to organize items into logical groups. Perfect for categorizing data, organizing information, or creating structured lists. Supports custom separators and various grouping options.",
shortDescription: 'Group list items by common properties',
keywords: ['group'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.group.name',
description: 'list.group.description',
shortDescription: 'list.group.shortDescription'
}
});

View File

@@ -0,0 +1,115 @@
{
"group": {
"title": "Group List",
"description": "Group list items by common properties.",
"inputTitle": "Input list",
"resultTitle": "Grouped list",
"groupingOptions": "Grouping Options",
"groupByDescription": "Choose how to group the list items",
"groupByValue": "Group by Value",
"groupByValueDescription": "Group items that have the same value",
"groupByLength": "Group by Length",
"groupByLengthDescription": "Group items by their character length",
"groupByFirstChar": "Group by First Character",
"groupByFirstCharDescription": "Group items by their first character",
"groupByLastChar": "Group by Last Character",
"groupByLastCharDescription": "Group items by their last character",
"toolInfo": {
"title": "Group List",
"description": "This tool allows you to group list items by various criteria such as value, length, or character position. It's useful for organizing and categorizing data."
}
},
"reverse": {
"title": "Reverse List",
"description": "Reverse the order of items in a list.",
"inputTitle": "Input list",
"resultTitle": "Reversed list",
"reverseOptions": "Reverse Options",
"reverseEachLine": "Reverse Each Line",
"reverseEachLineDescription": "Reverse each line separately instead of the entire list",
"toolInfo": {
"title": "Reverse List",
"description": "This tool allows you to reverse the order of items in a list. You can reverse the entire list or each line separately."
}
},
"sort": {
"title": "Sort List",
"description": "Sort list items in ascending or descending order.",
"inputTitle": "Input list",
"resultTitle": "Sorted list",
"sortOptions": "Sort Options",
"sortOrder": "Sort Order",
"ascending": "Ascending",
"descending": "Descending",
"sortType": "Sort Type",
"alphabetical": "Alphabetical",
"numerical": "Numerical",
"natural": "Natural",
"toolInfo": {
"title": "Sort List",
"description": "This tool allows you to sort list items in various orders and types. You can sort alphabetically, numerically, or using natural sorting."
}
},
"duplicate": {
"title": "Find Duplicates",
"description": "Find and remove duplicate items from a list.",
"inputTitle": "Input list",
"resultTitle": "Unique list",
"duplicateOptions": "Duplicate Options",
"removeDuplicates": "Remove Duplicates",
"removeDuplicatesDescription": "Remove duplicate items from the list",
"showDuplicates": "Show Duplicates",
"showDuplicatesDescription": "Show only the duplicate items",
"toolInfo": {
"title": "Find Duplicates",
"description": "This tool allows you to find and handle duplicate items in a list. You can remove duplicates or show only the duplicate items."
}
},
"findUnique": {
"title": "Find Unique",
"description": "Find unique items in a list.",
"inputTitle": "Input list",
"resultTitle": "Unique items",
"uniqueOptions": "Unique Options",
"showUnique": "Show Unique",
"showUniqueDescription": "Show only unique items",
"showDuplicates": "Show Duplicates",
"showDuplicatesDescription": "Show only duplicate items",
"toolInfo": {
"title": "Find Unique",
"description": "This tool allows you to find unique items in a list. You can show unique items or duplicate items."
}
},
"shuffle": {
"title": "Shuffle List",
"description": "Randomly shuffle the order of list items.",
"inputTitle": "Input list",
"resultTitle": "Shuffled list",
"shuffleOptions": "Shuffle Options",
"shuffleEachLine": "Shuffle Each Line",
"shuffleEachLineDescription": "Shuffle each line separately instead of the entire list",
"toolInfo": {
"title": "Shuffle List",
"description": "This tool allows you to randomly shuffle the order of items in a list. You can shuffle the entire list or each line separately."
}
},
"wrap": {
"title": "Wrap List",
"description": "Add text before and after each list item.",
"inputTitle": "Input List",
"resultTitle": "Wrapped List",
"splitOptions": "Split Options",
"splitBySymbol": "Split by Symbol",
"splitByRegex": "Split by Regular Expression",
"splitSeparatorDescription": "Separator to split the list",
"joinSeparatorDescription": "Separator to join the wrapped list",
"removeEmptyItems": "Remove empty items",
"wrapOptions": "Wrap Options",
"leftTextDescription": "Text to add before each item",
"rightTextDescription": "Text to add after each item",
"toolInfo": {
"title": "List Wrapping",
"description": "This tool allows you to add text before and after each item in a list. You can specify different text for the left and right sides, and control how the list is processed. It's useful for adding quotes, brackets, or other formatting to list items, preparing data for different formats, or creating structured text."
}
}
}

View File

@@ -9,6 +9,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { CardExampleType } from '@components/examples/ToolExamples';
import { ToolComponentProps } from '@tools/defineTool';
import ToolContent from '@components/ToolContent';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -111,6 +112,7 @@ argument`,
];
export default function Reverse({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -119,15 +121,15 @@ export default function Reverse({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Splitter Mode',
title: t('list.reverse.splitterMode'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitOperatorType', type)}
title={title}
description={description}
title={t(`list.reverse.splitOperators.${type}.title`)}
description={t(`list.reverse.splitOperators.${type}.description`)}
checked={values.splitOperatorType === type}
/>
))}
@@ -135,11 +137,11 @@ export default function Reverse({ title }: ToolComponentProps) {
)
},
{
title: 'Item Separator',
title: t('list.reverse.itemSeparator'),
component: (
<Box>
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('list.reverse.itemSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -147,11 +149,11 @@ export default function Reverse({ title }: ToolComponentProps) {
)
},
{
title: 'Output List Options',
title: t('list.reverse.outputListOptions'),
component: (
<Box>
<TextFieldWithDesc
description={'Output list item separator.'}
description={t('list.reverse.outputSeparatorDescription')}
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
/>
@@ -176,15 +178,18 @@ export default function Reverse({ title }: ToolComponentProps) {
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('list.reverse.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Reversed list'} value={result} />
<ToolTextResult title={t('list.reverse.resultTitle')} value={result} />
}
toolInfo={{
title: 'What Is a List Reverser?',
description:
'With this utility, you can reverse the order of items in a list. The utility first splits the input list into individual items and then iterates through them from the last item to the first item, printing each item to the output during the iteration. The input list may contain anything that can be represented as textual data, which includes digits, numbers, strings, words, sentences, etc. The input item separator can also be a regular expression. For example, the regex /[;,]/ will allow you to use items that are either comma- or semicolon-separated. The input and output list items delimiters can be customized in the options. By default, both input and output lists are comma-separated. Listabulous!'
title: t('list.reverse.toolInfo.title'),
description: t('list.reverse.toolInfo.description')
}}
exampleCards={exampleCards}
/>

View File

@@ -6,8 +6,14 @@ export const tool = defineTool('list', {
name: 'Reverse',
path: 'reverse',
icon: 'proicons:reverse',
description: 'This is a super simple browser-based application prints all list items in reverse. The input items can be separated by any symbol and you can also change the separator of the reversed list items.',
description:
'This is a super simple browser-based application prints all list items in reverse. The input items can be separated by any symbol and you can also change the separator of the reversed list items.',
shortDescription: 'Quickly reverse a list',
keywords: ['reverse'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.reverse.name',
description: 'list.reverse.description',
shortDescription: 'list.reverse.shortDescription'
}
});

View File

@@ -7,8 +7,13 @@ export const tool = defineTool('list', {
path: 'rotate',
icon: 'material-symbols-light:rotate-right',
description:
'A tool to rotate items in a list by a specified number of positions. Shift elements left or right while maintaining their relative order.',
shortDescription: 'Shift list items by position.',
"World's simplest browser-based utility for rotating list items. Input your list and specify rotation amount to shift items by a specified number of positions. Perfect for data manipulation, circular shifts, or reordering lists.",
shortDescription: 'Rotate list items by specified positions',
keywords: ['rotate'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.rotate.name',
description: 'list.rotate.description',
shortDescription: 'list.rotate.shortDescription'
}
});

View File

@@ -7,6 +7,7 @@ import { shuffleList, SplitOperatorType } from './service';
import SimpleRadio from '@components/options/SimpleRadio';
import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import { isNumber } from '@utils/string';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitOperatorType: 'symbol' as SplitOperatorType,
@@ -32,6 +33,7 @@ const splitOperators: {
];
export default function Shuffle() {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -51,20 +53,24 @@ export default function Shuffle() {
return (
<ToolContent
title="Shuffle"
title={t('list.shuffle.title')}
initialValues={initialValues}
compute={compute}
input={input}
setInput={setInput}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('list.shuffle.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={'Shuffled list'} value={result} />
<ToolTextResult title={t('list.shuffle.resultTitle')} value={result} />
}
getGroups={({ values, updateField }) => [
{
title: 'Input list separator',
title: t('list.shuffle.inputListSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
@@ -77,7 +83,7 @@ export default function Shuffle() {
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('list.shuffle.delimiterDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -85,11 +91,11 @@ export default function Shuffle() {
)
},
{
title: 'Shuffled List Length',
title: t('list.shuffle.shuffledListLength'),
component: (
<Box>
<TextFieldWithDesc
description={'Output this many random items'}
description={t('list.shuffle.outputLengthDescription')}
value={values.length}
onOwnChange={(val) => updateField('length', val)}
/>
@@ -97,13 +103,13 @@ export default function Shuffle() {
)
},
{
title: 'Shuffled List Separator',
title: t('list.shuffle.shuffledListSeparator'),
component: (
<Box>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(value) => updateField('joinSeparator', value)}
description={'Use this separator in the randomized list.'}
description={t('list.shuffle.joinSeparatorDescription')}
/>
</Box>
)

View File

@@ -7,8 +7,13 @@ export const tool = defineTool('list', {
path: 'shuffle',
icon: 'material-symbols-light:shuffle',
description:
'A tool to randomly reorder items in a list. Perfect for randomizing data, creating random selections, or generating random sequences.',
shortDescription: 'Randomly reorder list items.',
"World's simplest browser-based utility for shuffling list items. Input your list and instantly get a randomized version with items in random order. Perfect for creating variety, testing randomness, or mixing up ordered data.",
shortDescription: 'Randomize the order of list items',
keywords: ['shuffle'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.shuffle.name',
description: 'list.shuffle.description',
shortDescription: 'list.shuffle.shortDescription'
}
});

View File

@@ -9,6 +9,7 @@ import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import SelectWithDesc from '@components/options/SelectWithDesc';
import ToolContent from '@components/ToolContent';
import { ToolComponentProps } from '@tools/defineTool';
import { useTranslation } from 'react-i18next';
const initialValues = {
splitSeparatorType: 'symbol' as SplitOperatorType,
@@ -37,6 +38,7 @@ const splitOperators: {
];
export default function SplitText({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
const compute = (optionsValues: typeof initialValues, input: any) => {
@@ -69,26 +71,34 @@ export default function SplitText({ title }: ToolComponentProps) {
title={title}
input={input}
inputComponent={
<ToolTextInput title={'Input list'} value={input} onChange={setInput} />
<ToolTextInput
title={t('list.sort.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={t('list.sort.resultTitle')} value={result} />
}
resultComponent={<ToolTextResult title={'Sorted list'} value={result} />}
initialValues={initialValues}
getGroups={({ values, updateField }) => [
{
title: 'Input item separator',
title: t('list.sort.inputItemSeparator'),
component: (
<Box>
{splitOperators.map(({ title, description, type }) => (
<SimpleRadio
key={type}
onClick={() => updateField('splitSeparatorType', type)}
title={title}
description={description}
title={t(`list.sort.splitOperators.${type}.title`)}
description={t(
`list.sort.splitOperators.${type}.description`
)}
checked={values.splitSeparatorType === type}
/>
))}
<TextFieldWithDesc
description={'Set a delimiting symbol or regular expression.'}
description={t('list.sort.splitSeparatorDescription')}
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
/>
@@ -96,35 +106,45 @@ export default function SplitText({ title }: ToolComponentProps) {
)
},
{
title: 'Sort method',
title: t('list.sort.sortMethod'),
component: (
<Box>
<SelectWithDesc
selected={values.sortingMethod}
options={[
{ label: 'Sort Alphabetically', value: 'alphabetic' },
{ label: 'Sort Numerically', value: 'numeric' },
{ label: 'Sort by Length', value: 'length' }
{
label: t('list.sort.sortOptions.alphabetic'),
value: 'alphabetic'
},
{
label: t('list.sort.sortOptions.numeric'),
value: 'numeric'
},
{ label: t('list.sort.sortOptions.length'), value: 'length' }
]}
onChange={(value) => updateField('sortingMethod', value)}
description={'Select a sorting method.'}
description={t('list.sort.sortMethodDescription')}
/>
<SelectWithDesc
selected={values.increasing}
options={[
{ label: 'Increasing order', value: true },
{ label: 'Decreasing order', value: false }
{
label: t('list.sort.orderOptions.increasing'),
value: true
},
{
label: t('list.sort.orderOptions.decreasing'),
value: false
}
]}
onChange={(value) => {
updateField('increasing', value);
}}
description={'Select a sorting order.'}
description={t('list.sort.orderDescription')}
/>
<CheckboxWithDesc
title={'Case Sensitive Sort'}
description={
'Sort uppercase and lowercase items separately. Capital letters precede lowercase letters in an ascending list. (Works only in alphabetical sorting mode.)'
}
title={t('list.sort.caseSensitive')}
description={t('list.sort.caseSensitiveDescription')}
checked={values.caseSensitive}
onChange={(val) => updateField('caseSensitive', val)}
/>
@@ -132,19 +152,17 @@ export default function SplitText({ title }: ToolComponentProps) {
)
},
{
title: 'Sorted item properties',
title: t('list.sort.sortedItemProperties'),
component: (
<Box>
<TextFieldWithDesc
description={
'Use this symbol as a joiner between items in a sorted list.'
}
description={t('list.sort.joinSeparatorDescription')}
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
/>
<CheckboxWithDesc
title={'Remove duplicates'}
description={'Delete duplicate list items.'}
title={t('list.sort.removeDuplicates')}
description={t('list.sort.removeDuplicatesDescription')}
checked={values.removeDuplicated}
onChange={(val) => updateField('removeDuplicated', val)}
/>

View File

@@ -5,10 +5,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Sort',
path: 'sort',
icon: 'basil:sort-outline',
icon: 'material-symbols-light:sort',
description:
'This is a super simple browser-based application that sorts items in a list and arranges them in increasing or decreasing order. You can sort the items alphabetically, numerically, or by their length. You can also remove duplicate and empty items, as well as trim individual items that have whitespace around them. You can use any separator character to separate the input list items or alternatively use a regular expression to separate them. Additionally, you can create a new delimiter for the sorted output list.',
shortDescription: 'Quickly sort a list',
"World's simplest browser-based utility for sorting list items. Input your list and specify sorting criteria to organize items in ascending or descending order. Perfect for data organization, text processing, or creating ordered lists.",
shortDescription: 'Sort list items in specified order',
keywords: ['sort'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.sort.name',
description: 'list.sort.description',
shortDescription: 'list.sort.shortDescription'
}
});

View File

@@ -4,10 +4,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Truncate',
path: 'truncate',
icon: 'mdi:format-horizontal-align-right',
icon: 'material-symbols-light:content-cut',
description:
"World's simplest browser-based utility for truncating lists. Quickly limit the number of items in your list by specifying a maximum length. Perfect for sampling data, creating previews, or managing large lists. Supports custom separators and various truncation options.",
shortDescription: 'Limit the number of items in a list',
"World's simplest browser-based utility for truncating lists. Input your list and specify the maximum number of items to keep. Perfect for data processing, list management, or limiting content length.",
shortDescription: 'Truncate list to specified number of items',
keywords: ['truncate'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.truncate.name',
description: 'list.truncate.description',
shortDescription: 'list.truncate.shortDescription'
}
});

View File

@@ -5,10 +5,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Unwrap',
path: 'unwrap',
icon: 'mdi:unwrap',
icon: 'material-symbols-light:unfold-more',
description:
'A tool to remove characters from the beginning and end of each item in a list. Perfect for cleaning up formatted data or removing unwanted wrappers.',
shortDescription: 'Remove characters around list items.',
"World's simplest browser-based utility for unwrapping list items. Input your wrapped list and specify unwrapping criteria to flatten organized items. Perfect for data processing, text manipulation, or extracting content from structured lists.",
shortDescription: 'Unwrap list items from structured format',
keywords: ['unwrap'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.unwrap.name',
description: 'list.unwrap.description',
shortDescription: 'list.unwrap.shortDescription'
}
});

View File

@@ -11,6 +11,7 @@ import TextFieldWithDesc from '@components/options/TextFieldWithDesc';
import SimpleRadio from '@components/options/SimpleRadio';
import CheckboxWithDesc from '@components/options/CheckboxWithDesc';
import * as Yup from 'yup';
import { useTranslation } from 'react-i18next';
interface InitialValuesType {
splitOperatorType: SplitOperatorType;
@@ -85,6 +86,7 @@ const exampleCards: CardExampleType<InitialValuesType>[] = [
];
export default function Wrap({ title }: ToolComponentProps) {
const { t } = useTranslation();
const [input, setInput] = useState<string>('');
const [result, setResult] = useState<string>('');
@@ -117,50 +119,50 @@ export default function Wrap({ title }: ToolComponentProps) {
updateField
}) => [
{
title: 'Split Options',
title: t('list.wrap.splitOptions'),
component: (
<Box>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'symbol')}
checked={values.splitOperatorType === 'symbol'}
title={'Split by Symbol'}
title={t('list.wrap.splitBySymbol')}
/>
<SimpleRadio
onClick={() => updateField('splitOperatorType', 'regex')}
checked={values.splitOperatorType === 'regex'}
title={'Split by Regular Expression'}
title={t('list.wrap.splitByRegex')}
/>
<TextFieldWithDesc
value={values.splitSeparator}
onOwnChange={(val) => updateField('splitSeparator', val)}
description={'Separator to split the list'}
description={t('list.wrap.splitSeparatorDescription')}
/>
<TextFieldWithDesc
value={values.joinSeparator}
onOwnChange={(val) => updateField('joinSeparator', val)}
description={'Separator to join the wrapped list'}
description={t('list.wrap.joinSeparatorDescription')}
/>
<CheckboxWithDesc
checked={values.deleteEmptyItems}
onChange={(checked) => updateField('deleteEmptyItems', checked)}
title={'Remove empty items'}
title={t('list.wrap.removeEmptyItems')}
/>
</Box>
)
},
{
title: 'Wrap Options',
title: t('list.wrap.wrapOptions'),
component: (
<Box>
<TextFieldWithDesc
value={values.left}
onOwnChange={(val) => updateField('left', val)}
description={'Text to add before each item'}
description={t('list.wrap.leftTextDescription')}
/>
<TextFieldWithDesc
value={values.right}
onOwnChange={(val) => updateField('right', val)}
description={'Text to add after each item'}
description={t('list.wrap.rightTextDescription')}
/>
</Box>
)
@@ -171,16 +173,21 @@ export default function Wrap({ title }: ToolComponentProps) {
<ToolContent
title={title}
inputComponent={
<ToolTextInput title="Input List" value={input} onChange={setInput} />
<ToolTextInput
title={t('list.wrap.inputTitle')}
value={input}
onChange={setInput}
/>
}
resultComponent={
<ToolTextResult title={t('list.wrap.resultTitle')} value={result} />
}
resultComponent={<ToolTextResult title="Wrapped List" value={result} />}
initialValues={initialValues}
getGroups={getGroups}
validationSchema={validationSchema}
toolInfo={{
title: 'List Wrapping',
description:
"This tool allows you to add text before and after each item in a list. You can specify different text for the left and right sides, and control how the list is processed. It's useful for adding quotes, brackets, or other formatting to list items, preparing data for different formats, or creating structured text."
title: t('list.wrap.toolInfo.title'),
description: t('list.wrap.toolInfo.description')
}}
exampleCards={exampleCards}
input={input}

View File

@@ -5,10 +5,15 @@ import { lazy } from 'react';
export const tool = defineTool('list', {
name: 'Wrap',
path: 'wrap',
icon: 'mdi:wrap',
icon: 'material-symbols-light:wrap-text',
description:
'A tool to wrap each item in a list with custom prefix and suffix characters. Useful for formatting lists for code, markup languages, or presentation.',
shortDescription: 'Add characters around list items.',
"World's simplest browser-based utility for wrapping list items. Input your list and specify wrapping criteria to organize items into logical groups. Perfect for categorizing data, organizing information, or creating structured lists.",
shortDescription: 'Wrap list items with specified criteria',
keywords: ['wrap'],
component: lazy(() => import('./index'))
component: lazy(() => import('./index')),
i18n: {
name: 'list.wrap.name',
description: 'list.wrap.description',
shortDescription: 'list.wrap.shortDescription'
}
});