From 2e962f659902c4480c631fdf1d306bb46b86d5c7 Mon Sep 17 00:00:00 2001 From: James Pine Date: Mon, 20 Apr 2026 03:12:34 -0700 Subject: [PATCH] feat(i18n): localize EffectsChainEditor and built-in preset names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Effect type labels (Chorus/Flanger, Reverb, Delay, Compressor, Gain, High-Pass, Low-Pass, Pitch Shift) and every param label (LFO speed, Modulation depth, Threshold, Ratio, etc.) go through `effects.types..{label,params.}` with the backend string as defaultValue fallback. - Chain-level controls: "Load preset…", "Add effect…", "Clear", Power/Remove button titles. - Built-in preset names + descriptions (Robotic, Radio, Echo Chamber, Deep Voice) are translated client-side; user-created presets keep their original names. Backend keeps returning English — frontend intercepts and translates via key lookup, defaulting to the backend string so unknown effects/params don't break. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../components/Effects/EffectsChainEditor.tsx | 49 ++++++---- .../components/EffectsTab/EffectsDetail.tsx | 21 ++++- app/src/components/EffectsTab/EffectsList.tsx | 12 ++- app/src/i18n/locales/en/translation.json | 89 +++++++++++++++++++ app/src/i18n/locales/zh-CN/translation.json | 89 +++++++++++++++++++ 5 files changed, 238 insertions(+), 22 deletions(-) diff --git a/app/src/components/Effects/EffectsChainEditor.tsx b/app/src/components/Effects/EffectsChainEditor.tsx index e913808c..04728077 100644 --- a/app/src/components/Effects/EffectsChainEditor.tsx +++ b/app/src/components/Effects/EffectsChainEditor.tsx @@ -18,6 +18,7 @@ import { CSS } from '@dnd-kit/utilities'; import { useQuery } from '@tanstack/react-query'; import { ChevronDown, ChevronRight, GripVertical, Plus, Power, Trash2 } from 'lucide-react'; import { useCallback, useMemo, useRef, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import { Button } from '@/components/ui/button'; import { Label } from '@/components/ui/label'; import { @@ -55,6 +56,7 @@ export function EffectsChainEditor({ compact = false, showPresets = true, }: EffectsChainEditorProps) { + const { t } = useTranslation(); const [expandedId, setExpandedId] = useState(null); // Maintain stable IDs for each effect across renders. @@ -177,17 +179,27 @@ export function EffectsChainEditor({ }} > - + - {presets?.map((p) => ( - - {p.name} - {p.description && ( - - {p.description} - )} - - ))} + {presets?.map((p) => { + const name = p.is_builtin + ? t(`effects.builtinPresets.${p.name}.name`, { defaultValue: p.name }) + : p.name; + const description = p.is_builtin + ? t(`effects.builtinPresets.${p.name}.description`, { + defaultValue: p.description ?? '', + }) + : p.description; + return ( + + {name} + {description && ( + - {description} + )} + + ); + })} @@ -198,7 +210,7 @@ export function EffectsChainEditor({ className="h-8 px-2 text-xs text-muted-foreground" onClick={clearAll} > - Clear + {t('effects.chain.clear')} )} @@ -229,12 +241,12 @@ export function EffectsChainEditor({