This commit is contained in:
Ibrahima G. Coulibaly
2025-07-13 15:39:12 +01:00
parent 0ed18c7231
commit 24e0e38b4a
6 changed files with 43 additions and 80 deletions

42
.idea/workspace.xml generated
View File

@@ -6,27 +6,11 @@
<component name="ChangeListManager"> <component name="ChangeListManager">
<list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="fix: i18n tsc"> <list default="true" id="b30e2810-c4c1-4aad-b134-794e52cc1c7d" name="Changes" comment="fix: i18n tsc">
<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$/@types/i18n.d.ts" beforeDir="false" afterPath="$PROJECT_DIR$/@types/i18n.d.ts" 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/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/tools/audio/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/audio/i18n/en.json" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/pages/tools/audio/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/audio/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/csv/find-incomplete-csv-records/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/csv/find-incomplete-csv-records/index.tsx" afterDir="false" /> <change beforePath="$PROJECT_DIR$/src/tools/defineTool.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/tools/defineTool.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/csv/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/csv/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/csv/insert-csv-columns/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/csv/insert-csv-columns/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/list/group/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/list/group/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/list/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/list/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/list/reverse/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/list/reverse/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/number/arithmetic-sequence/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/number/arithmetic-sequence/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/number/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/number/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/number/sum/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/number/sum/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/pdf/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/pdf/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/string/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/string/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/string/join/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/string/join/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/string/split/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/string/split/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/string/statistic/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/string/statistic/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/time/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/time/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/time/truncate-clock-time/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/time/truncate-clock-time/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/flip/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/flip/index.tsx" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/i18n/en.json" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/i18n/en.json" afterDir="false" />
<change beforePath="$PROJECT_DIR$/src/pages/tools/video/rotate/index.tsx" beforeDir="false" afterPath="$PROJECT_DIR$/src/pages/tools/video/rotate/index.tsx" 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" />
@@ -528,15 +512,7 @@
<workItem from="1752077170501" duration="4261000" /> <workItem from="1752077170501" duration="4261000" />
<workItem from="1752127185450" duration="1168000" /> <workItem from="1752127185450" duration="1168000" />
<workItem from="1752157409587" duration="2415000" /> <workItem from="1752157409587" duration="2415000" />
<workItem from="1752403829295" duration="8019000" /> <workItem from="1752403829295" duration="13253000" />
</task>
<task id="LOCAL-00171" summary="chore: zoom on hover">
<option name="closed" value="true" />
<created>1743052111988</created>
<option name="number" value="00171" />
<option name="presentableId" value="LOCAL-00171" />
<option name="project" value="LOCAL" />
<updated>1743052111988</updated>
</task> </task>
<task id="LOCAL-00172" summary="refactor: time between dates"> <task id="LOCAL-00172" summary="refactor: time between dates">
<option name="closed" value="true" /> <option name="closed" value="true" />
@@ -922,7 +898,15 @@
<option name="project" value="LOCAL" /> <option name="project" value="LOCAL" />
<updated>1752408068771</updated> <updated>1752408068771</updated>
</task> </task>
<option name="localTasksCounter" value="220" /> <task id="LOCAL-00220" summary="fix: i18n tsc">
<option name="closed" value="true" />
<created>1752412149075</created>
<option name="number" value="00220" />
<option name="presentableId" value="LOCAL-00220" />
<option name="project" value="LOCAL" />
<updated>1752412149075</updated>
</task>
<option name="localTasksCounter" value="221" />
<servers /> <servers />
</component> </component>
<component name="TypeScriptGeneratedFilesManager"> <component name="TypeScriptGeneratedFilesManager">

28
@types/i18n.d.ts vendored
View File

@@ -1,33 +1,9 @@
// types/i18next.d.ts // types/i18next.d.ts
import 'i18next'; import 'i18next';
import enGlobal from '../src/i18n/en.json'; import { resources } from '../src/i18n';
import enList from '../src/pages/tools/list/i18n/en.json';
import enString from '../src/pages/tools/string/i18n/en.json';
import enCsv from '../src/pages/tools/csv/i18n/en.json';
import enJson from '../src/pages/tools/json/i18n/en.json';
import enPdf from '../src/pages/tools/pdf/i18n/en.json';
import enImage from '../src/pages/tools/image/i18n/en.json';
import enAudio from '../src/pages/tools/audio/i18n/en.json';
import enVideo from '../src/pages/tools/video/i18n/en.json';
import enNumber from '../src/pages/tools/number/i18n/en.json';
import enTime from '../src/pages/tools/time/i18n/en.json';
import enXml from '../src/pages/tools/xml/i18n/en.json';
declare module 'i18next' { declare module 'i18next' {
interface CustomTypeOptions { interface CustomTypeOptions {
resources: { resources: (typeof resources)['en'];
translation: typeof enGlobal;
list: typeof enList;
string: typeof enString;
csv: typeof enCsv;
json: typeof enJson;
pdf: typeof enPdf;
image: typeof enImage;
audio: typeof enAudio;
video: typeof enVideo;
number: typeof enNumber;
time: typeof enTime;
xml: typeof enXml;
};
} }
} }

View File

@@ -8,6 +8,8 @@ import { getToolsByCategory } from '@tools/index';
import { capitalizeFirstLetter } from '../utils/string'; import { capitalizeFirstLetter } from '../utils/string';
import { IconifyIcon } from '@iconify/react'; import { IconifyIcon } from '@iconify/react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { ToolCategory } from '@tools/defineTool';
import { FullI18nKey } from '../i18n';
export default function ToolLayout({ export default function ToolLayout({
children, children,
@@ -20,12 +22,12 @@ export default function ToolLayout({
title: string; title: string;
description: string; description: string;
icon?: IconifyIcon | string; icon?: IconifyIcon | string;
type: string; type: ToolCategory;
children: ReactNode; children: ReactNode;
i18n?: { i18n?: {
name: string; name: FullI18nKey;
description: string; description: FullI18nKey;
shortDescription: string; shortDescription: FullI18nKey;
}; };
}) { }) {
const { t } = useTranslation(); const { t } = useTranslation();

View File

@@ -1,4 +1,4 @@
import i18n from 'i18next'; import i18n, { ParseKeys } from 'i18next';
import { initReactI18next } from 'react-i18next'; import { initReactI18next } from 'react-i18next';
import enGlobal from './en.json'; import enGlobal from './en.json';
import hiGlobal from './hi.json'; import hiGlobal from './hi.json';
@@ -33,7 +33,7 @@ const locizeOptions = {
version: 'latest' version: 'latest'
}; };
// Merge translations for demonstration; in a real app, use namespaces // Merge translations for demonstration; in a real app, use namespaces
const resources = { export const resources = {
en: { en: {
translation: enGlobal, translation: enGlobal,
list: enList, list: enList,
@@ -62,21 +62,18 @@ const resources = {
time: hiTime, time: hiTime,
xml: hiXml xml: hiXml
} }
}; } as const;
i18n export type I18nNamespaces = keyof (typeof resources)['en'];
// .use(Backend) export type FullI18nKey = `${string}:${ParseKeys<I18nNamespaces>}`;
.use(initReactI18next)
.init({ i18n.use(Backend).use(initReactI18next).init({
resources, resources,
lng: 'en', lng: 'en',
fallbackLng: 'en', fallbackLng: 'en',
interpolation: { backend: locizeOptions,
escapeValue: false saveMissing: true, // Send missing keys to Locize
}, updateMissing: true // Update keys in Locize
backend: locizeOptions, });
saveMissing: true, // Send missing keys to Locize
updateMissing: true // Update keys in Locize
});
export default i18n; export default i18n;

View File

@@ -13,6 +13,9 @@
} }
}, },
"changeSpeed": { "changeSpeed": {
"title": "Change audio speed",
"description": "Change the playback speed of audio files. Speed up or slow down audio while maintaining pitch.",
"shortDescription": "Change the speed of audio files",
"newAudioSpeed": "New Audio Speed", "newAudioSpeed": "New Audio Speed",
"speedDescription": "Default multiplier: 2 means 2x faster", "speedDescription": "Default multiplier: 2 means 2x faster",
"outputFormat": "Output Format", "outputFormat": "Output Format",

View File

@@ -1,6 +1,7 @@
import ToolLayout from '../components/ToolLayout'; import ToolLayout from '../components/ToolLayout';
import React, { JSXElementConstructor, LazyExoticComponent } from 'react'; import React, { JSXElementConstructor, LazyExoticComponent } from 'react';
import { IconifyIcon } from '@iconify/react'; import { IconifyIcon } from '@iconify/react';
import { FullI18nKey } from '../i18n';
export interface ToolMeta { export interface ToolMeta {
path: string; path: string;
@@ -12,10 +13,10 @@ export interface ToolMeta {
shortDescription: string; shortDescription: string;
longDescription?: string; longDescription?: string;
i18n?: { i18n?: {
name: string; name: FullI18nKey;
description: string; description: FullI18nKey;
shortDescription: string; shortDescription: FullI18nKey;
longDescription?: string; longDescription?: FullI18nKey;
}; };
} }