mirror of
https://github.com/iib0011/omni-tools.git
synced 2025-09-20 22:49:33 +02:00
fix: i18n
This commit is contained in:
56
.idea/workspace.xml
generated
56
.idea/workspace.xml
generated
@@ -4,9 +4,19 @@
|
|||||||
<option name="autoReloadType" value="SELECTIVE" />
|
<option name="autoReloadType" value="SELECTIVE" />
|
||||||
</component>
|
</component>
|
||||||
<component name="ChangeListManager">
|
<component name="ChangeListManager">
|
||||||
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="fix: create-tool.mjs to use i18n object">
|
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="chore: sync locales">
|
||||||
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/workspace.xml" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/locales/en/translation.json" beforeDir="false" afterPath="$PROJECT_DIR$/public/locales/en/translation.json" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/locales/fr/translation.json" beforeDir="false" afterPath="$PROJECT_DIR$/public/locales/fr/translation.json" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/public/locales/hi/translation.json" beforeDir="false" afterPath="$PROJECT_DIR$/public/locales/hi/translation.json" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/Hero.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/Hero.tsx" afterDir="false" />
|
||||||
<change beforePath="$PROJECT_DIR$/src/components/ToolHeader.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolHeader.tsx" afterDir="false" />
|
<change beforePath="$PROJECT_DIR$/src/components/ToolHeader.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolHeader.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/components/ToolLayout.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/components/ToolLayout.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/i18n/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/i18n/index.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/home/Categories.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/home/Categories.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools-by-category/index.tsx" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/tools/index.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/tools/index.ts" afterDir="false" />
|
||||||
|
<change beforePath="$PROJECT_DIR$/src/utils/string.ts" beforeDir="false" afterPath="$PROJECT_DIR$/src/utils/string.ts" afterDir="false" />
|
||||||
</list>
|
</list>
|
||||||
<option name="SHOW_DIALOG" value="false" />
|
<option name="SHOW_DIALOG" value="false" />
|
||||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||||
@@ -338,7 +348,7 @@
|
|||||||
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\categories" />
|
<recent name="C:\Users\Ibrahima\IdeaProjects\omni-tools\src\pages\categories" />
|
||||||
</key>
|
</key>
|
||||||
</component>
|
</component>
|
||||||
<component name="RunManager" selected="npm.i18n:pull">
|
<component name="RunManager" selected="npm.dev">
|
||||||
<configuration name="generatePassword" type="JavaScriptTestRunnerVitest" temporary="true" nameIsGenerated="true">
|
<configuration name="generatePassword" type="JavaScriptTestRunnerVitest" temporary="true" nameIsGenerated="true">
|
||||||
<node-interpreter value="project" />
|
<node-interpreter value="project" />
|
||||||
<vitest-package value="$PROJECT_DIR$/node_modules/vitest" />
|
<vitest-package value="$PROJECT_DIR$/node_modules/vitest" />
|
||||||
@@ -412,9 +422,9 @@
|
|||||||
</list>
|
</list>
|
||||||
<recent_temporary>
|
<recent_temporary>
|
||||||
<list>
|
<list>
|
||||||
<item itemvalue="Vitest.generatePassword" />
|
|
||||||
<item itemvalue="npm.dev" />
|
<item itemvalue="npm.dev" />
|
||||||
<item itemvalue="npm.i18n:sync" />
|
<item itemvalue="npm.i18n:sync" />
|
||||||
|
<item itemvalue="Vitest.generatePassword" />
|
||||||
<item itemvalue="npm.i18n:push" />
|
<item itemvalue="npm.i18n:push" />
|
||||||
<item itemvalue="npm.i18n:pull" />
|
<item itemvalue="npm.i18n:pull" />
|
||||||
</list>
|
</list>
|
||||||
@@ -531,22 +541,6 @@
|
|||||||
<workItem from="1752493585622" duration="11629000" />
|
<workItem from="1752493585622" duration="11629000" />
|
||||||
<workItem from="1752507105323" duration="9008000" />
|
<workItem from="1752507105323" duration="9008000" />
|
||||||
</task>
|
</task>
|
||||||
<task id="LOCAL-00187" summary="fix: tests">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1743691399769</created>
|
|
||||||
<option name="number" value="00187" />
|
|
||||||
<option name="presentableId" value="LOCAL-00187" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1743691399769</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00188" summary="chore: uninstall @jspawn/ghostscript-wasm">
|
|
||||||
<option name="closed" value="true" />
|
|
||||||
<created>1743691471368</created>
|
|
||||||
<option name="number" value="00188" />
|
|
||||||
<option name="presentableId" value="LOCAL-00188" />
|
|
||||||
<option name="project" value="LOCAL" />
|
|
||||||
<updated>1743691471368</updated>
|
|
||||||
</task>
|
|
||||||
<task id="LOCAL-00189" summary="feat: protect pdf">
|
<task id="LOCAL-00189" summary="feat: protect pdf">
|
||||||
<option name="closed" value="true" />
|
<option name="closed" value="true" />
|
||||||
<created>1743705749057</created>
|
<created>1743705749057</created>
|
||||||
@@ -923,7 +917,23 @@
|
|||||||
<option name="project" value="LOCAL" />
|
<option name="project" value="LOCAL" />
|
||||||
<updated>1752586932190</updated>
|
<updated>1752586932190</updated>
|
||||||
</task>
|
</task>
|
||||||
<option name="localTasksCounter" value="236" />
|
<task id="LOCAL-00236" summary="fix: show Use this tool only if medium breakpoint">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1752591387066</created>
|
||||||
|
<option name="number" value="00236" />
|
||||||
|
<option name="presentableId" value="LOCAL-00236" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1752591387066</updated>
|
||||||
|
</task>
|
||||||
|
<task id="LOCAL-00237" summary="chore: sync locales">
|
||||||
|
<option name="closed" value="true" />
|
||||||
|
<created>1752596436284</created>
|
||||||
|
<option name="number" value="00237" />
|
||||||
|
<option name="presentableId" value="LOCAL-00237" />
|
||||||
|
<option name="project" value="LOCAL" />
|
||||||
|
<updated>1752596436284</updated>
|
||||||
|
</task>
|
||||||
|
<option name="localTasksCounter" value="238" />
|
||||||
<servers />
|
<servers />
|
||||||
</component>
|
</component>
|
||||||
<component name="TypeScriptGeneratedFilesManager">
|
<component name="TypeScriptGeneratedFilesManager">
|
||||||
@@ -970,8 +980,6 @@
|
|||||||
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
<option name="CHECK_CODE_SMELLS_BEFORE_PROJECT_COMMIT" value="false" />
|
||||||
<option name="CHECK_NEW_TODO" value="false" />
|
<option name="CHECK_NEW_TODO" value="false" />
|
||||||
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
<option name="ADD_EXTERNAL_FILES_SILENTLY" value="true" />
|
||||||
<MESSAGE value="chore: png icon" />
|
|
||||||
<MESSAGE value="fix: remove xml viewer" />
|
|
||||||
<MESSAGE value="feat: convert to jpg" />
|
<MESSAGE value="feat: convert to jpg" />
|
||||||
<MESSAGE value="feat: edit image" />
|
<MESSAGE value="feat: edit image" />
|
||||||
<MESSAGE value="fix: favicons" />
|
<MESSAGE value="fix: favicons" />
|
||||||
@@ -995,7 +1003,9 @@
|
|||||||
<MESSAGE value="fix: translations" />
|
<MESSAGE value="fix: translations" />
|
||||||
<MESSAGE value="chore: delete unused i18n json files" />
|
<MESSAGE value="chore: delete unused i18n json files" />
|
||||||
<MESSAGE value="fix: create-tool.mjs to use i18n object" />
|
<MESSAGE value="fix: create-tool.mjs to use i18n object" />
|
||||||
<option name="LAST_COMMIT_MESSAGE" value="fix: create-tool.mjs to use i18n object" />
|
<MESSAGE value="fix: show Use this tool only if medium breakpoint" />
|
||||||
|
<MESSAGE value="chore: sync locales" />
|
||||||
|
<option name="LAST_COMMIT_MESSAGE" value="chore: sync locales" />
|
||||||
</component>
|
</component>
|
||||||
<component name="VgoProject">
|
<component name="VgoProject">
|
||||||
<integration-enabled>false</integration-enabled>
|
<integration-enabled>false</integration-enabled>
|
||||||
|
@@ -220,7 +220,7 @@
|
|||||||
"seeExamples": "See Examples"
|
"seeExamples": "See Examples"
|
||||||
},
|
},
|
||||||
"toolLayout": {
|
"toolLayout": {
|
||||||
"allToolsTitle": "All {{type}} Tools"
|
"allToolsTitle": "All {{type}}"
|
||||||
},
|
},
|
||||||
"toolMultiFileResult": {
|
"toolMultiFileResult": {
|
||||||
"copied": "File copied",
|
"copied": "File copied",
|
||||||
|
@@ -58,7 +58,7 @@
|
|||||||
"description": "Outils pour travailler avec des images PNG : convertissez des PNG en JPG, créez des PNG transparents, modifiez les couleurs PNG, recadrez, faites pivoter, redimensionnez des PNG et bien plus encore.",
|
"description": "Outils pour travailler avec des images PNG : convertissez des PNG en JPG, créez des PNG transparents, modifiez les couleurs PNG, recadrez, faites pivoter, redimensionnez des PNG et bien plus encore.",
|
||||||
"title": "Outils PNG"
|
"title": "Outils PNG"
|
||||||
},
|
},
|
||||||
"seeAll": "Tout voir {{title}}",
|
"seeAll": "Voir les {{title}}",
|
||||||
"string": {
|
"string": {
|
||||||
"description": "Outils pour travailler avec du texte : convertissez du texte en images, recherchez et remplacez du texte, divisez du texte en fragments, joignez des lignes de texte, répétez du texte et bien plus encore.",
|
"description": "Outils pour travailler avec du texte : convertissez du texte en images, recherchez et remplacez du texte, divisez du texte en fragments, joignez des lignes de texte, répétez du texte et bien plus encore.",
|
||||||
"title": "Outils de texte"
|
"title": "Outils de texte"
|
||||||
@@ -220,7 +220,7 @@
|
|||||||
"seeExamples": "Voir des exemples"
|
"seeExamples": "Voir des exemples"
|
||||||
},
|
},
|
||||||
"toolLayout": {
|
"toolLayout": {
|
||||||
"allToolsTitle": "Tous {{type}} Outils"
|
"allToolsTitle": "Tous les {{type}}"
|
||||||
},
|
},
|
||||||
"toolMultiFileResult": {
|
"toolMultiFileResult": {
|
||||||
"copied": "Fichier copié",
|
"copied": "Fichier copié",
|
||||||
|
@@ -220,7 +220,7 @@
|
|||||||
"seeExamples": "उदाहरण देखें"
|
"seeExamples": "उदाहरण देखें"
|
||||||
},
|
},
|
||||||
"toolLayout": {
|
"toolLayout": {
|
||||||
"allToolsTitle": "सभी {{type}} टूल्स"
|
"allToolsTitle": "सभी {{type}}"
|
||||||
},
|
},
|
||||||
"toolMultiFileResult": {
|
"toolMultiFileResult": {
|
||||||
"copied": "फ़ाइल कॉपी की गई",
|
"copied": "फ़ाइल कॉपी की गई",
|
||||||
|
@@ -151,7 +151,7 @@ export default function Hero() {
|
|||||||
renderGroup={(params) => {
|
renderGroup={(params) => {
|
||||||
return (
|
return (
|
||||||
<li key={params.key}>
|
<li key={params.key}>
|
||||||
<GroupHeader>{getToolCategoryTitle(params.group)}</GroupHeader>
|
<GroupHeader>{getToolCategoryTitle(params.group, t)}</GroupHeader>
|
||||||
<GroupItems>{params.children}</GroupItems>
|
<GroupItems>{params.children}</GroupItems>
|
||||||
</li>
|
</li>
|
||||||
);
|
);
|
||||||
|
@@ -11,6 +11,7 @@ import { isBookmarked, toggleBookmarked } from '@utils/bookmark';
|
|||||||
import IconButton from '@mui/material/IconButton';
|
import IconButton from '@mui/material/IconButton';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import useMediaQuery from '@mui/material/useMediaQuery';
|
import useMediaQuery from '@mui/material/useMediaQuery';
|
||||||
|
import { validNamespaces } from '../i18n';
|
||||||
|
|
||||||
const StyledButton = styled(Button)(({ theme }) => ({
|
const StyledButton = styled(Button)(({ theme }) => ({
|
||||||
backgroundColor: 'white',
|
backgroundColor: 'white',
|
||||||
@@ -94,6 +95,7 @@ export default function ToolHeader({
|
|||||||
path
|
path
|
||||||
}: ToolHeaderProps) {
|
}: ToolHeaderProps) {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
|
const { t } = useTranslation();
|
||||||
const [bookmarked, setBookmarked] = useState<boolean>(isBookmarked(path));
|
const [bookmarked, setBookmarked] = useState<boolean>(isBookmarked(path));
|
||||||
return (
|
return (
|
||||||
<Box my={4}>
|
<Box my={4}>
|
||||||
@@ -101,7 +103,7 @@ export default function ToolHeader({
|
|||||||
items={[
|
items={[
|
||||||
{ title: 'All tools', link: '/' },
|
{ title: 'All tools', link: '/' },
|
||||||
{
|
{
|
||||||
title: getToolsByCategory().find(
|
title: getToolsByCategory(t).find(
|
||||||
(category) => category.type === type
|
(category) => category.type === type
|
||||||
)!.rawTitle,
|
)!.rawTitle,
|
||||||
link: '/categories/' + type
|
link: '/categories/' + type
|
||||||
|
@@ -43,7 +43,7 @@ export default function ToolLayout({
|
|||||||
const toolDescription: string = t(i18n.description);
|
const toolDescription: string = t(i18n.description);
|
||||||
|
|
||||||
const otherCategoryTools =
|
const otherCategoryTools =
|
||||||
getToolsByCategory()
|
getToolsByCategory(t)
|
||||||
.find((category) => category.type === type)
|
.find((category) => category.type === type)
|
||||||
?.tools.filter((tool) => t(tool.name) !== toolTitle)
|
?.tools.filter((tool) => t(tool.name) !== toolTitle)
|
||||||
.map((tool) => ({
|
.map((tool) => ({
|
||||||
@@ -75,10 +75,10 @@ export default function ToolLayout({
|
|||||||
{children}
|
{children}
|
||||||
<Separator backgroundColor="#5581b5" margin="50px" />
|
<Separator backgroundColor="#5581b5" margin="50px" />
|
||||||
<AllTools
|
<AllTools
|
||||||
title={t('toolLayout.allToolsTitle', {
|
title={t('translation:toolLayout.allToolsTitle', {
|
||||||
type: capitalizeFirstLetter(
|
type: capitalizeFirstLetter(
|
||||||
getToolsByCategory().find((category) => category.type === type)!
|
getToolsByCategory(t).find((category) => category.type === type)!
|
||||||
.rawTitle
|
.title
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
toolCards={otherCategoryTools}
|
toolCards={otherCategoryTools}
|
||||||
|
@@ -2,7 +2,7 @@ import i18n, { ParseKeys } from 'i18next';
|
|||||||
import { initReactI18next } from 'react-i18next';
|
import { initReactI18next } from 'react-i18next';
|
||||||
import Backend from 'i18next-http-backend';
|
import Backend from 'i18next-http-backend';
|
||||||
|
|
||||||
export const validNamespaces: string[] = [
|
export const validNamespaces: (string | 'translation')[] = [
|
||||||
'string',
|
'string',
|
||||||
'number',
|
'number',
|
||||||
'video',
|
'video',
|
||||||
|
@@ -9,6 +9,7 @@ import { categoriesColors } from 'config/uiConfig';
|
|||||||
import { Icon } from '@iconify/react';
|
import { Icon } from '@iconify/react';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { getI18nNamespaceFromToolCategory } from '@utils/string';
|
import { getI18nNamespaceFromToolCategory } from '@utils/string';
|
||||||
|
import { validNamespaces } from '../../i18n';
|
||||||
|
|
||||||
type ArrayElement<ArrayType extends readonly unknown[]> =
|
type ArrayElement<ArrayType extends readonly unknown[]> =
|
||||||
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
ArrayType extends readonly (infer ElementType)[] ? ElementType : never;
|
||||||
@@ -32,10 +33,10 @@ const SingleCategory = function ({
|
|||||||
`categories.${category.type}.description`,
|
`categories.${category.type}.description`,
|
||||||
category.description
|
category.description
|
||||||
);
|
);
|
||||||
const seeAllText = t('categories.seeAll', 'See all {{title}}', {
|
const seeAllText = t('translation:categories.seeAll', 'See all {{title}}', {
|
||||||
title: categoryTitle
|
title: categoryTitle
|
||||||
});
|
});
|
||||||
const tryText = t('categories.try', 'Try {{title}}', {
|
const tryText = t('translation:categories.try', 'Try {{title}}', {
|
||||||
//@ts-ignore
|
//@ts-ignore
|
||||||
title: t(category.example.title)
|
title: t(category.example.title)
|
||||||
});
|
});
|
||||||
@@ -111,9 +112,10 @@ const SingleCategory = function ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
export default function Categories() {
|
export default function Categories() {
|
||||||
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<Grid width={'80%'} container mt={2} spacing={2}>
|
<Grid width={'80%'} container mt={2} spacing={2}>
|
||||||
{getToolsByCategory().map((category, index) => (
|
{getToolsByCategory(t).map((category, index) => (
|
||||||
<SingleCategory key={category.type} category={category} index={index} />
|
<SingleCategory key={category.type} category={category} index={index} />
|
||||||
))}
|
))}
|
||||||
</Grid>
|
</Grid>
|
||||||
|
@@ -23,7 +23,7 @@ import ArrowBackIcon from '@mui/icons-material/ArrowBack';
|
|||||||
import SearchIcon from '@mui/icons-material/Search';
|
import SearchIcon from '@mui/icons-material/Search';
|
||||||
import { Helmet } from 'react-helmet';
|
import { Helmet } from 'react-helmet';
|
||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { I18nNamespaces } from '../../i18n';
|
import { I18nNamespaces, validNamespaces } from '../../i18n';
|
||||||
|
|
||||||
const StyledLink = styled(Link)(({ theme }) => ({
|
const StyledLink = styled(Link)(({ theme }) => ({
|
||||||
'&:hover': {
|
'&:hover': {
|
||||||
@@ -36,16 +36,12 @@ export default function ToolsByCategory() {
|
|||||||
const mainContentRef = React.useRef<HTMLDivElement>(null);
|
const mainContentRef = React.useRef<HTMLDivElement>(null);
|
||||||
const { categoryName } = useParams();
|
const { categoryName } = useParams();
|
||||||
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
const [searchTerm, setSearchTerm] = React.useState<string>('');
|
||||||
const rawTitle = getToolCategoryTitle(categoryName as string);
|
const { t } = useTranslation(validNamespaces);
|
||||||
|
const rawTitle = getToolCategoryTitle(categoryName as string, t);
|
||||||
// First get tools by category without filtering
|
// First get tools by category without filtering
|
||||||
const toolsByCategory =
|
const toolsByCategory =
|
||||||
getToolsByCategory().find(({ type }) => type === categoryName)?.tools ?? [];
|
getToolsByCategory(t).find(({ type }) => type === categoryName)?.tools ??
|
||||||
|
[];
|
||||||
const namespace =
|
|
||||||
toolsByCategory.length > 0
|
|
||||||
? getI18nNamespaceFromToolCategory(toolsByCategory[0].type)
|
|
||||||
: 'translation';
|
|
||||||
const { t } = useTranslation(namespace);
|
|
||||||
|
|
||||||
const categoryTools = filterTools(toolsByCategory, searchTerm, t);
|
const categoryTools = filterTools(toolsByCategory, searchTerm, t);
|
||||||
|
|
||||||
@@ -77,10 +73,9 @@ export default function ToolsByCategory() {
|
|||||||
<IconButton onClick={() => navigate('/')}>
|
<IconButton onClick={() => navigate('/')}>
|
||||||
<ArrowBackIcon color={'primary'} />
|
<ArrowBackIcon color={'primary'} />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
<Typography
|
<Typography fontSize={22} color={theme.palette.primary.main}>
|
||||||
fontSize={22}
|
{t('translation:toolLayout.allToolsTitle', { type: rawTitle })}
|
||||||
color={theme.palette.primary.main}
|
</Typography>
|
||||||
>{`All ${rawTitle} Tools`}</Typography>
|
|
||||||
</Stack>
|
</Stack>
|
||||||
<TextField
|
<TextField
|
||||||
placeholder={'Search'}
|
placeholder={'Search'}
|
||||||
|
@@ -14,7 +14,7 @@ import { IconifyIcon } from '@iconify/react';
|
|||||||
import { pdfTools } from '../pages/tools/pdf';
|
import { pdfTools } from '../pages/tools/pdf';
|
||||||
import { xmlTools } from '../pages/tools/xml';
|
import { xmlTools } from '../pages/tools/xml';
|
||||||
import { TFunction } from 'i18next';
|
import { TFunction } from 'i18next';
|
||||||
import { I18nNamespaces } from '../i18n';
|
import { FullI18nKey, I18nNamespaces } from '../i18n';
|
||||||
|
|
||||||
const toolCategoriesOrder: ToolCategory[] = [
|
const toolCategoriesOrder: ToolCategory[] = [
|
||||||
'image-generic',
|
'image-generic',
|
||||||
@@ -47,95 +47,93 @@ export const tools: DefinedTool[] = [
|
|||||||
];
|
];
|
||||||
const categoriesConfig: {
|
const categoriesConfig: {
|
||||||
type: ToolCategory;
|
type: ToolCategory;
|
||||||
value: string;
|
title: FullI18nKey;
|
||||||
title?: string;
|
value: FullI18nKey;
|
||||||
icon: IconifyIcon | string;
|
icon: IconifyIcon | string;
|
||||||
}[] = [
|
}[] = [
|
||||||
{
|
{
|
||||||
type: 'string',
|
type: 'string',
|
||||||
title: 'Text',
|
|
||||||
icon: 'solar:text-bold-duotone',
|
icon: 'solar:text-bold-duotone',
|
||||||
value:
|
value: 'translation:categories.string.description',
|
||||||
'Tools for working with text – convert text to images, find and replace text, split text into fragments, join text lines, repeat text, and much more.'
|
title: 'translation:categories.string.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'png',
|
type: 'png',
|
||||||
icon: 'ph:file-png-thin',
|
icon: 'ph:file-png-thin',
|
||||||
value:
|
value: 'translation:categories.png.description',
|
||||||
'Tools for working with PNG images – convert PNGs to JPGs, create transparent PNGs, change PNG colors, crop, rotate, resize PNGs, and much more.'
|
title: 'translation:categories.png.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'number',
|
type: 'number',
|
||||||
icon: 'lsicon:number-filled',
|
icon: 'lsicon:number-filled',
|
||||||
value:
|
value: 'translation:categories.number.description',
|
||||||
'Tools for working with numbers – generate number sequences, convert numbers to words and words to numbers, sort, round, factor numbers, and much more.'
|
title: 'translation:categories.number.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'gif',
|
type: 'gif',
|
||||||
icon: 'material-symbols-light:gif-rounded',
|
icon: 'material-symbols-light:gif-rounded',
|
||||||
value:
|
value: 'translation:categories.gif.description',
|
||||||
'Tools for working with GIF animations – create transparent GIFs, extract GIF frames, add text to GIF, crop, rotate, reverse GIFs, and much more.'
|
title: 'translation:categories.gif.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'list',
|
type: 'list',
|
||||||
icon: 'solar:list-bold-duotone',
|
icon: 'solar:list-bold-duotone',
|
||||||
value:
|
value: 'translation:categories.list.description',
|
||||||
'Tools for working with lists – sort, reverse, randomize lists, find unique and duplicate list items, change list item separators, and much more.'
|
title: 'translation:categories.list.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'json',
|
type: 'json',
|
||||||
icon: 'lets-icons:json-light',
|
icon: 'lets-icons:json-light',
|
||||||
value:
|
value: 'translation:categories.json.description',
|
||||||
'Tools for working with JSON data structures – prettify and minify JSON objects, flatten JSON arrays, stringify JSON values, analyze data, and much more'
|
title: 'translation:categories.json.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'time',
|
type: 'time',
|
||||||
icon: 'mdi:clock-time-five',
|
icon: 'mdi:clock-time-five',
|
||||||
value:
|
value: 'translation:categories.time.description',
|
||||||
'Tools for working with time and date – calculate time differences, convert between time zones, format dates, generate date sequences, and much more.'
|
title: 'translation:categories.time.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'csv',
|
type: 'csv',
|
||||||
icon: 'material-symbols-light:csv-outline',
|
icon: 'material-symbols-light:csv-outline',
|
||||||
value:
|
value: 'translation:categories.csv.description',
|
||||||
'Tools for working with CSV files - convert CSV to different formats, manipulate CSV data, validate CSV structure, and process CSV files efficiently.'
|
title: 'translation:categories.csv.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'video',
|
type: 'video',
|
||||||
icon: 'lets-icons:video-light',
|
icon: 'lets-icons:video-light',
|
||||||
value:
|
value: 'translation:categories.video.description',
|
||||||
'Tools for working with videos – extract frames from videos, create GIFs from videos, convert videos to different formats, and much more.'
|
title: 'translation:categories.video.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'pdf',
|
type: 'pdf',
|
||||||
icon: 'tabler:pdf',
|
icon: 'tabler:pdf',
|
||||||
value:
|
value: 'translation:categories.pdf.description',
|
||||||
'Tools for working with PDF files - extract text from PDFs, convert PDFs to other formats, manipulate PDFs, and much more.'
|
title: 'translation:categories.pdf.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'time',
|
type: 'time',
|
||||||
icon: 'fluent-mdl2:date-time',
|
icon: 'fluent-mdl2:date-time',
|
||||||
value:
|
value: 'translation:categories.time.description',
|
||||||
'Tools for working with time and date – draw clocks and calendars, generate time and date sequences, calculate average time, convert between time zones, and much more.'
|
title: 'translation:categories.time.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'image-generic',
|
type: 'image-generic',
|
||||||
title: 'Image',
|
|
||||||
icon: 'material-symbols-light:image-outline-rounded',
|
icon: 'material-symbols-light:image-outline-rounded',
|
||||||
value:
|
value: 'translation:categories.image-generic.description',
|
||||||
'Tools for working with pictures – compress, resize, crop, convert to JPG, rotate, remove background and much more.'
|
title: 'translation:categories.image-generic.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'audio',
|
type: 'audio',
|
||||||
icon: 'ic:twotone-audiotrack',
|
icon: 'ic:twotone-audiotrack',
|
||||||
value:
|
value: 'translation:categories.audio.description',
|
||||||
'Tools for working with audio – extract audio from video, adjusting audio speed, merging multiple audio files and much more.'
|
title: 'translation:categories.audio.title'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'xml',
|
type: 'xml',
|
||||||
icon: 'mdi-light:xml',
|
icon: 'mdi-light:xml',
|
||||||
value:
|
value: 'translation:categories.xml.description',
|
||||||
'Tools for working with XML data structures - viewer, beautifier, validator and much more'
|
title: 'translation:categories.xml.title'
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
// use for changelogs
|
// use for changelogs
|
||||||
@@ -162,7 +160,9 @@ export const filterTools = (
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getToolsByCategory = (): {
|
export const getToolsByCategory = (
|
||||||
|
t: TFunction<I18nNamespaces[]>
|
||||||
|
): {
|
||||||
title: string;
|
title: string;
|
||||||
rawTitle: string;
|
rawTitle: string;
|
||||||
description: string;
|
description: string;
|
||||||
@@ -179,9 +179,13 @@ export const getToolsByCategory = (): {
|
|||||||
(config) => config.type === type
|
(config) => config.type === type
|
||||||
);
|
);
|
||||||
return {
|
return {
|
||||||
rawTitle: categoryConfig?.title ?? capitalizeFirstLetter(type),
|
rawTitle: categoryConfig?.title
|
||||||
title: `${categoryConfig?.title ?? capitalizeFirstLetter(type)} Tools`,
|
? t(categoryConfig.title)
|
||||||
description: categoryConfig?.value ?? '',
|
: capitalizeFirstLetter(type),
|
||||||
|
title: categoryConfig?.title
|
||||||
|
? t(categoryConfig.title)
|
||||||
|
: `${capitalizeFirstLetter(type)} Tools`,
|
||||||
|
description: categoryConfig?.value ? t(categoryConfig.value) : '',
|
||||||
type,
|
type,
|
||||||
icon: categoryConfig!.icon,
|
icon: categoryConfig!.icon,
|
||||||
tools: tools ?? [],
|
tools: tools ?? [],
|
||||||
|
@@ -2,6 +2,7 @@ import { UpdateField } from '@components/options/ToolOptions';
|
|||||||
import { getToolsByCategory } from '@tools/index';
|
import { getToolsByCategory } from '@tools/index';
|
||||||
import { ToolCategory } from '@tools/defineTool';
|
import { ToolCategory } from '@tools/defineTool';
|
||||||
import { I18nNamespaces, validNamespaces } from '../i18n';
|
import { I18nNamespaces, validNamespaces } from '../i18n';
|
||||||
|
import { TFunction } from 'i18next';
|
||||||
|
|
||||||
// Here starting the shared values for string manipulation.
|
// Here starting the shared values for string manipulation.
|
||||||
|
|
||||||
@@ -109,8 +110,11 @@ export function itemCounter(
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getToolCategoryTitle = (categoryName: string): string =>
|
export const getToolCategoryTitle = (
|
||||||
getToolsByCategory().find((category) => category.type === categoryName)!
|
categoryName: string,
|
||||||
|
t: TFunction<I18nNamespaces[]>
|
||||||
|
): string =>
|
||||||
|
getToolsByCategory(t).find((category) => category.type === categoryName)!
|
||||||
.rawTitle;
|
.rawTitle;
|
||||||
|
|
||||||
// Type guard to check if a value is a valid I18nNamespaces
|
// Type guard to check if a value is a valid I18nNamespaces
|
||||||
|
Reference in New Issue
Block a user