fix: organize appearance settings sections
Separated theme and localization controls Added localized section title
This commit is contained in:
@@ -445,6 +445,8 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
|
|
||||||
const isVSCode = isVSCodeRuntime();
|
const isVSCode = isVSCodeRuntime();
|
||||||
const hasAppearanceSettings = (shouldShow('theme') || shouldShow('pwaInstallName') || shouldShow('pwaOrientation') || shouldShow('timeFormat') || shouldShow('weekStart')) && !isVSCode;
|
const hasAppearanceSettings = (shouldShow('theme') || shouldShow('pwaInstallName') || shouldShow('pwaOrientation') || shouldShow('timeFormat') || shouldShow('weekStart')) && !isVSCode;
|
||||||
|
const hasThemeSettings = shouldShow('theme') && !isVSCode;
|
||||||
|
const hasLocalizationSettings = (shouldShow('theme') || shouldShow('timeFormat') || shouldShow('weekStart')) && !isVSCode;
|
||||||
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('spacing') || shouldShow('inputBarOffset');
|
const hasLayoutSettings = shouldShow('fontSize') || shouldShow('terminalFontSize') || shouldShow('spacing') || shouldShow('inputBarOffset');
|
||||||
const hasNavigationSettings = shouldShow('terminalQuickKeys') && !isMobile;
|
const hasNavigationSettings = shouldShow('terminalQuickKeys') && !isMobile;
|
||||||
const hasBehaviorSettings = shouldShow('mermaidRendering')
|
const hasBehaviorSettings = shouldShow('mermaidRendering')
|
||||||
@@ -580,10 +582,9 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
|
|
||||||
{/* --- Appearance & Themes --- */}
|
{/* --- Appearance & Themes --- */}
|
||||||
{hasAppearanceSettings && (
|
{hasAppearanceSettings && (
|
||||||
<div className="mb-8 space-y-3">
|
<div className="mb-8 space-y-6">
|
||||||
<section className="px-2 pb-2 pt-0 space-y-0.5">
|
{hasThemeSettings && (
|
||||||
|
<section className="px-2 pb-2 pt-0 space-y-2">
|
||||||
<div className="pb-1.5">
|
|
||||||
<div className="flex min-w-0 flex-col gap-1.5">
|
<div className="flex min-w-0 flex-col gap-1.5">
|
||||||
<span className="typography-ui-header font-medium text-foreground">{t('settings.openchamber.visual.section.colorMode')}</span>
|
<span className="typography-ui-header font-medium text-foreground">{t('settings.openchamber.visual.section.colorMode')}</span>
|
||||||
<div className="flex flex-wrap items-center gap-1">
|
<div className="flex flex-wrap items-center gap-1">
|
||||||
@@ -593,149 +594,159 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
variant="chip"
|
variant="chip"
|
||||||
size="xs"
|
size="xs"
|
||||||
aria-pressed={themeMode === option.value}
|
aria-pressed={themeMode === option.value}
|
||||||
className="!font-normal"
|
className="!font-normal"
|
||||||
onClick={() => setThemeMode(option.value)}
|
onClick={() => setThemeMode(option.value)}
|
||||||
>
|
>
|
||||||
{tUnsafe(option.labelKey)}
|
{tUnsafe(option.labelKey)}
|
||||||
</Button>
|
</Button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-2 grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
<div className="grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
||||||
<div className="flex min-w-0 flex-col">
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
<span className="typography-ui-label text-foreground shrink-0">{t('settings.appearance.language.label')}</span>
|
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.lightTheme')}</span>
|
||||||
<span className="typography-meta text-muted-foreground">{t('settings.appearance.language.description')}</span>
|
<Select value={selectedLightTheme?.metadata.id ?? ''} onValueChange={setLightThemePreference}>
|
||||||
|
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectLightThemeAria')} className="w-fit">
|
||||||
|
<SelectValue placeholder={t('settings.openchamber.visual.field.selectThemePlaceholder')}>
|
||||||
|
{selectedLightTheme
|
||||||
|
? formatThemeLabel(selectedLightTheme.metadata.name, 'light')
|
||||||
|
: undefined}
|
||||||
|
</SelectValue>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{lightThemes.map((theme) => (
|
||||||
|
<SelectItem key={theme.metadata.id} value={theme.metadata.id}>
|
||||||
|
{formatThemeLabel(theme.metadata.name, 'light')}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
|
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.darkTheme')}</span>
|
||||||
|
<Select value={selectedDarkTheme?.metadata.id ?? ''} onValueChange={setDarkThemePreference}>
|
||||||
|
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectDarkThemeAria')} className="w-fit">
|
||||||
|
<SelectValue placeholder={t('settings.openchamber.visual.field.selectThemePlaceholder')}>
|
||||||
|
{selectedDarkTheme
|
||||||
|
? formatThemeLabel(selectedDarkTheme.metadata.name, 'dark')
|
||||||
|
: undefined}
|
||||||
|
</SelectValue>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{darkThemes.map((theme) => (
|
||||||
|
<SelectItem key={theme.metadata.id} value={theme.metadata.id}>
|
||||||
|
{formatThemeLabel(theme.metadata.name, 'dark')}
|
||||||
|
</SelectItem>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Select value={locale} onValueChange={(value) => setLocale(value as Locale)}>
|
|
||||||
<SelectTrigger aria-label={t('settings.appearance.language.select')} className="w-fit">
|
|
||||||
<SelectValue>{label(locale)}</SelectValue>
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{locales.map((availableLocale) => (
|
|
||||||
<SelectItem key={availableLocale} value={availableLocale}>
|
|
||||||
{label(availableLocale)}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="mt-2 grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
<div className="flex items-center gap-2 py-1.5">
|
||||||
<div className="flex min-w-0 items-center gap-2">
|
<button
|
||||||
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.lightTheme')}</span>
|
type="button"
|
||||||
<Select value={selectedLightTheme?.metadata.id ?? ''} onValueChange={setLightThemePreference}>
|
disabled={customThemesLoading || themesReloading}
|
||||||
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectLightThemeAria')} className="w-fit">
|
onClick={() => {
|
||||||
<SelectValue placeholder={t('settings.openchamber.visual.field.selectThemePlaceholder')}>
|
const startedAt = Date.now();
|
||||||
{selectedLightTheme
|
setThemesReloading(true);
|
||||||
? formatThemeLabel(selectedLightTheme.metadata.name, 'light')
|
void reloadCustomThemes().finally(() => {
|
||||||
: undefined}
|
const elapsed = Date.now() - startedAt;
|
||||||
</SelectValue>
|
if (elapsed < 500) {
|
||||||
|
window.setTimeout(() => {
|
||||||
|
setThemesReloading(false);
|
||||||
|
}, 500 - elapsed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setThemesReloading(false);
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
className="inline-flex items-center typography-ui-label font-normal text-foreground underline decoration-[1px] underline-offset-2 hover:text-foreground/80 disabled:cursor-not-allowed disabled:text-muted-foreground/60"
|
||||||
|
>
|
||||||
|
{themesReloading ? t('settings.openchamber.visual.actions.reloadingThemes') : t('settings.openchamber.visual.actions.reloadThemes')}
|
||||||
|
</button>
|
||||||
|
<Tooltip delayDuration={700}>
|
||||||
|
<TooltipTrigger asChild>
|
||||||
|
<button
|
||||||
|
type="button"
|
||||||
|
className="flex items-center justify-center rounded-md p-1 text-muted-foreground/70 hover:text-foreground"
|
||||||
|
aria-label={t('settings.openchamber.visual.field.themeImportInfoAria')}
|
||||||
|
>
|
||||||
|
<RiInformationLine className="h-3.5 w-3.5" />
|
||||||
|
</button>
|
||||||
|
</TooltipTrigger>
|
||||||
|
<TooltipContent sideOffset={8}>
|
||||||
|
{t('settings.openchamber.visual.field.themeImportInfoTooltip')}
|
||||||
|
</TooltipContent>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasLocalizationSettings && (
|
||||||
|
<section className="px-2 pb-2 pt-0 space-y-2">
|
||||||
|
<h4 className="typography-ui-header font-medium text-foreground">{t('settings.openchamber.visual.section.localization')}</h4>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
||||||
|
<div className="flex min-w-0 flex-col">
|
||||||
|
<span className="typography-ui-label text-foreground shrink-0">{t('settings.appearance.language.label')}</span>
|
||||||
|
<span className="typography-meta text-muted-foreground">{t('settings.appearance.language.description')}</span>
|
||||||
|
</div>
|
||||||
|
<Select value={locale} onValueChange={(value) => setLocale(value as Locale)}>
|
||||||
|
<SelectTrigger aria-label={t('settings.appearance.language.select')} className="w-fit">
|
||||||
|
<SelectValue>{label(locale)}</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{lightThemes.map((theme) => (
|
{locales.map((availableLocale) => (
|
||||||
<SelectItem key={theme.metadata.id} value={theme.metadata.id}>
|
<SelectItem key={availableLocale} value={availableLocale}>
|
||||||
{formatThemeLabel(theme.metadata.name, 'light')}
|
{label(availableLocale)}
|
||||||
</SelectItem>
|
</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
<div className="flex min-w-0 items-center gap-2">
|
|
||||||
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.darkTheme')}</span>
|
|
||||||
<Select value={selectedDarkTheme?.metadata.id ?? ''} onValueChange={setDarkThemePreference}>
|
|
||||||
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectDarkThemeAria')} className="w-fit">
|
|
||||||
<SelectValue placeholder={t('settings.openchamber.visual.field.selectThemePlaceholder')}>
|
|
||||||
{selectedDarkTheme
|
|
||||||
? formatThemeLabel(selectedDarkTheme.metadata.name, 'dark')
|
|
||||||
: undefined}
|
|
||||||
</SelectValue>
|
|
||||||
</SelectTrigger>
|
|
||||||
<SelectContent>
|
|
||||||
{darkThemes.map((theme) => (
|
|
||||||
<SelectItem key={theme.metadata.id} value={theme.metadata.id}>
|
|
||||||
{formatThemeLabel(theme.metadata.name, 'dark')}
|
|
||||||
</SelectItem>
|
|
||||||
))}
|
|
||||||
</SelectContent>
|
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{(shouldShow('timeFormat') || shouldShow('weekStart')) && (
|
{(shouldShow('timeFormat') || shouldShow('weekStart')) && (
|
||||||
<div className="mt-1 grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
<div className="grid grid-cols-1 gap-2 py-1.5 md:grid-cols-[14rem_auto] md:gap-x-8 md:gap-y-2">
|
||||||
{shouldShow('timeFormat') && (
|
{shouldShow('timeFormat') && (
|
||||||
<div className="flex min-w-0 items-center gap-2">
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.timeFormat')}</span>
|
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.timeFormat')}</span>
|
||||||
<Select value={timeFormatPreference} onValueChange={(value: 'auto' | '12h' | '24h') => handleTimeFormatPreferenceChange(value)}>
|
<Select value={timeFormatPreference} onValueChange={(value: 'auto' | '12h' | '24h') => handleTimeFormatPreferenceChange(value)}>
|
||||||
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectTimeFormatAria')} className="w-fit">
|
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectTimeFormatAria')} className="w-fit">
|
||||||
<SelectValue>{selectedTimeFormatLabel}</SelectValue>
|
<SelectValue>{selectedTimeFormatLabel}</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{TIME_FORMAT_OPTIONS.map((option) => (
|
{TIME_FORMAT_OPTIONS.map((option) => (
|
||||||
<SelectItem key={option.id} value={option.id}>{tUnsafe(option.labelKey)}</SelectItem>
|
<SelectItem key={option.id} value={option.id}>{tUnsafe(option.labelKey)}</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{shouldShow('weekStart') && (
|
{shouldShow('weekStart') && (
|
||||||
<div className="flex min-w-0 items-center gap-2">
|
<div className="flex min-w-0 items-center gap-2">
|
||||||
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.weekStartsOn')}</span>
|
<span className="typography-ui-label text-foreground shrink-0">{t('settings.openchamber.visual.field.weekStartsOn')}</span>
|
||||||
<Select value={weekStartPreference} onValueChange={(value: 'auto' | 'monday' | 'sunday') => handleWeekStartPreferenceChange(value)}>
|
<Select value={weekStartPreference} onValueChange={(value: 'auto' | 'monday' | 'sunday') => handleWeekStartPreferenceChange(value)}>
|
||||||
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectWeekStartAria')} className="w-fit">
|
<SelectTrigger aria-label={t('settings.openchamber.visual.field.selectWeekStartAria')} className="w-fit">
|
||||||
<SelectValue>{selectedWeekStartLabel}</SelectValue>
|
<SelectValue>{selectedWeekStartLabel}</SelectValue>
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
{WEEK_START_OPTIONS.map((option) => (
|
{WEEK_START_OPTIONS.map((option) => (
|
||||||
<SelectItem key={option.id} value={option.id}>{tUnsafe(option.labelKey)}</SelectItem>
|
<SelectItem key={option.id} value={option.id}>{tUnsafe(option.labelKey)}</SelectItem>
|
||||||
))}
|
))}
|
||||||
</SelectContent>
|
</SelectContent>
|
||||||
</Select>
|
</Select>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
<div className="flex items-center gap-2 py-1.5">
|
{(showPwaInstallNameSetting || showPwaOrientationSetting) && (
|
||||||
<button
|
<section className="px-2 pb-2 pt-0 space-y-2">
|
||||||
type="button"
|
|
||||||
disabled={customThemesLoading || themesReloading}
|
|
||||||
onClick={() => {
|
|
||||||
const startedAt = Date.now();
|
|
||||||
setThemesReloading(true);
|
|
||||||
void reloadCustomThemes().finally(() => {
|
|
||||||
const elapsed = Date.now() - startedAt;
|
|
||||||
if (elapsed < 500) {
|
|
||||||
window.setTimeout(() => {
|
|
||||||
setThemesReloading(false);
|
|
||||||
}, 500 - elapsed);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
setThemesReloading(false);
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
className="inline-flex items-center typography-ui-label font-normal text-foreground underline decoration-[1px] underline-offset-2 hover:text-foreground/80 disabled:cursor-not-allowed disabled:text-muted-foreground/60"
|
|
||||||
>
|
|
||||||
{themesReloading ? t('settings.openchamber.visual.actions.reloadingThemes') : t('settings.openchamber.visual.actions.reloadThemes')}
|
|
||||||
</button>
|
|
||||||
<Tooltip delayDuration={700}>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
className="flex items-center justify-center rounded-md p-1 text-muted-foreground/70 hover:text-foreground"
|
|
||||||
aria-label={t('settings.openchamber.visual.field.themeImportInfoAria')}
|
|
||||||
>
|
|
||||||
<RiInformationLine className="h-3.5 w-3.5" />
|
|
||||||
</button>
|
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent sideOffset={8}>
|
|
||||||
{t('settings.openchamber.visual.field.themeImportInfoTooltip')}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{showPwaInstallNameSetting && (
|
{showPwaInstallNameSetting && (
|
||||||
<div className="py-1.5 space-y-1.5">
|
<div className="py-1.5 space-y-1.5">
|
||||||
@@ -824,7 +835,8 @@ export const OpenChamberVisualSettings: React.FC<OpenChamberVisualSettingsProps>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ export const settingsDict = {
|
|||||||
'settings.voice.page.preview.voiceLine': 'Hello! I\'m {voiceName}. This is how I sound.',
|
'settings.voice.page.preview.voiceLine': 'Hello! I\'m {voiceName}. This is how I sound.',
|
||||||
'settings.voice.page.preview.customServerLine': 'Hello! This is a preview of the custom TTS server.',
|
'settings.voice.page.preview.customServerLine': 'Hello! This is a preview of the custom TTS server.',
|
||||||
'settings.openchamber.visual.section.colorMode': 'Color Mode',
|
'settings.openchamber.visual.section.colorMode': 'Color Mode',
|
||||||
|
'settings.openchamber.visual.section.localization': 'Localization',
|
||||||
'settings.openchamber.visual.section.spacingAndLayout': 'Spacing & Layout',
|
'settings.openchamber.visual.section.spacingAndLayout': 'Spacing & Layout',
|
||||||
'settings.openchamber.visual.section.navigation': 'Navigation',
|
'settings.openchamber.visual.section.navigation': 'Navigation',
|
||||||
'settings.openchamber.visual.section.chatRenderMode': 'Chat Render Mode',
|
'settings.openchamber.visual.section.chatRenderMode': 'Chat Render Mode',
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ export const settingsDict = {
|
|||||||
"settings.voice.page.preview.voiceLine": "¡Hola! Soy {voiceName}. Así suena mi voz.",
|
"settings.voice.page.preview.voiceLine": "¡Hola! Soy {voiceName}. Así suena mi voz.",
|
||||||
"settings.voice.page.preview.customServerLine": "¡Hola! Esta es una previsualización del servidor TTS personalizado.",
|
"settings.voice.page.preview.customServerLine": "¡Hola! Esta es una previsualización del servidor TTS personalizado.",
|
||||||
"settings.openchamber.visual.section.colorMode": "Modo de color",
|
"settings.openchamber.visual.section.colorMode": "Modo de color",
|
||||||
|
"settings.openchamber.visual.section.localization": "Localización",
|
||||||
"settings.openchamber.visual.section.spacingAndLayout": "Espaciado y diseño",
|
"settings.openchamber.visual.section.spacingAndLayout": "Espaciado y diseño",
|
||||||
"settings.openchamber.visual.section.navigation": "Navegación",
|
"settings.openchamber.visual.section.navigation": "Navegación",
|
||||||
"settings.openchamber.visual.section.chatRenderMode": "Modo de renderizado de chat",
|
"settings.openchamber.visual.section.chatRenderMode": "Modo de renderizado de chat",
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ export const settingsDict = {
|
|||||||
"settings.voice.page.preview.voiceLine": "Olá! Sou {voiceName}. É assim que minha voz soa.",
|
"settings.voice.page.preview.voiceLine": "Olá! Sou {voiceName}. É assim que minha voz soa.",
|
||||||
"settings.voice.page.preview.customServerLine": "Olá! Esta é uma prévia do servidor TTS personalizado.",
|
"settings.voice.page.preview.customServerLine": "Olá! Esta é uma prévia do servidor TTS personalizado.",
|
||||||
"settings.openchamber.visual.section.colorMode": "Modo de cor",
|
"settings.openchamber.visual.section.colorMode": "Modo de cor",
|
||||||
|
"settings.openchamber.visual.section.localization": "Localização",
|
||||||
"settings.openchamber.visual.section.spacingAndLayout": "Espaçamento e layout",
|
"settings.openchamber.visual.section.spacingAndLayout": "Espaçamento e layout",
|
||||||
"settings.openchamber.visual.section.navigation": "Navegação",
|
"settings.openchamber.visual.section.navigation": "Navegação",
|
||||||
"settings.openchamber.visual.section.chatRenderMode": "Modo de renderizado de chat",
|
"settings.openchamber.visual.section.chatRenderMode": "Modo de renderizado de chat",
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ export const settingsDict = {
|
|||||||
"settings.voice.page.preview.voiceLine": "Привіт! Я {voiceName}. Ось як я звучу.",
|
"settings.voice.page.preview.voiceLine": "Привіт! Я {voiceName}. Ось як я звучу.",
|
||||||
"settings.voice.page.preview.customServerLine": "Привіт! Це попередній перегляд спеціального сервера TTS.",
|
"settings.voice.page.preview.customServerLine": "Привіт! Це попередній перегляд спеціального сервера TTS.",
|
||||||
"settings.openchamber.visual.section.colorMode": "Режим теми",
|
"settings.openchamber.visual.section.colorMode": "Режим теми",
|
||||||
|
"settings.openchamber.visual.section.localization": "Локалізація",
|
||||||
"settings.openchamber.visual.section.spacingAndLayout": "Відступи й компонування",
|
"settings.openchamber.visual.section.spacingAndLayout": "Відступи й компонування",
|
||||||
"settings.openchamber.visual.section.navigation": "Навігація",
|
"settings.openchamber.visual.section.navigation": "Навігація",
|
||||||
"settings.openchamber.visual.section.chatRenderMode": "Режим візуалізації чату",
|
"settings.openchamber.visual.section.chatRenderMode": "Режим візуалізації чату",
|
||||||
|
|||||||
@@ -1322,6 +1322,7 @@ export const settingsDict = {
|
|||||||
'settings.voice.page.preview.voiceLine': '你好!我是 {voiceName}。这是我的声音效果。',
|
'settings.voice.page.preview.voiceLine': '你好!我是 {voiceName}。这是我的声音效果。',
|
||||||
'settings.voice.page.preview.customServerLine': '你好!这是自定义 TTS 服务器的预览。',
|
'settings.voice.page.preview.customServerLine': '你好!这是自定义 TTS 服务器的预览。',
|
||||||
'settings.openchamber.visual.section.colorMode': '颜色模式',
|
'settings.openchamber.visual.section.colorMode': '颜色模式',
|
||||||
|
'settings.openchamber.visual.section.localization': '本地化',
|
||||||
'settings.openchamber.visual.section.spacingAndLayout': '间距与布局',
|
'settings.openchamber.visual.section.spacingAndLayout': '间距与布局',
|
||||||
'settings.openchamber.visual.section.navigation': '导航',
|
'settings.openchamber.visual.section.navigation': '导航',
|
||||||
'settings.openchamber.visual.section.chatRenderMode': '聊天渲染模式',
|
'settings.openchamber.visual.section.chatRenderMode': '聊天渲染模式',
|
||||||
|
|||||||
Reference in New Issue
Block a user