This commit is contained in:
Timothy Jaeryang Baek 2026-10-10 21:28:33 +04:00
parent a69722f932
commit 79d376a1f3
3 changed files with 94 additions and 5 deletions

View file

@ -13,7 +13,7 @@
import Check from '$lib/components/icons/Check.svelte';
import Tooltip from '$lib/components/common/Tooltip.svelte';
import Knobs from '$lib/components/icons/Knobs.svelte';
import { resolveLocalizedModelName } from '$lib/utils/localizedContent';
import { localizeModelControls, resolveLocalizedModelName } from '$lib/utils/localizedContent';
const i18n: any = getContext('i18n');
export let selectedModels: string[] = [];
@ -143,7 +143,7 @@
{resolveLocalizedModelName(model, $i18n.language)}
</div>
{/if}
{#each Object.entries(model.info?.params?.model_controls ?? {}) as [key, control] (key)}
{#each Object.entries(localizeModelControls(model, $i18n.language)) as [key, control] (key)}
{#if control.display === 'slider'}
<ModelControlSlider
{control}

View file

@ -56,7 +56,10 @@
import AccessControlModal from '../common/AccessControlModal.svelte';
import AccessButton from '$lib/components/common/AccessButton.svelte';
import { copyToClipboard, extractInputVariables } from '$lib/utils';
import { pruneEmptyLocaleEntries } from '$lib/utils/localizedContent';
import {
modelControlTranslationSource,
pruneEmptyLocaleEntries
} from '$lib/utils/localizedContent';
const i18n: any = getContext('i18n');
const formId = `model-editor-${uuidv4()}`;
@ -163,7 +166,7 @@
voice: undefined as { voice?: string } | undefined,
voice_avatar: null as VoiceAvatarConfig | null,
description: '',
i18n: {},
i18n: {} as Record<string, Record<string, any>>,
suggestion_prompts: null,
tags: []
},
@ -1426,7 +1429,54 @@
</fieldset>
{/if}
<fieldset disabled={readOnly} class="min-w-0">
<ModelControls bind:controls={params.model_controls} />
{#if !editingLocale}
<ModelControls bind:controls={params.model_controls} />
{:else if Object.keys(params.model_controls ?? {}).length}
{@const fields = modelControlTranslationSource(params.model_controls ?? {})}
{@const customized = Object.keys(fields).some((key) =>
info.meta.i18n?.[editingLocale]?.[key]?.trim()
)}
<ModelSettingsSection
label={$i18n.t('Model controls')}
description={$i18n.t(
'Let people choose approved parameter presets in chat.'
)}
summary={customized ? $i18n.t('Custom') : $i18n.t('Default')}
>
{#each Object.entries(fields) as [key, original] (key)}
<div
class="rounded-xl px-2 py-1.5 focus-within:bg-gray-50 dark:focus-within:bg-gray-850 {info.meta.i18n?.[
editingLocale
]?.[key]?.trim()
? ''
: 'opacity-60 focus-within:opacity-100'}"
>
<Textarea
className="min-h-5 w-full min-w-0 resize-none overflow-hidden bg-transparent text-[0.8125rem] font-normal leading-5 text-gray-900 outline-hidden placeholder:text-gray-500 dark:text-gray-100 dark:placeholder:text-gray-400"
placeholder={original}
value={info.meta.i18n?.[editingLocale]?.[key] ?? ''}
onInput={(event) =>
setLocalizedField(
key,
(event.currentTarget as HTMLTextAreaElement).value
)}
/>
</div>
{/each}
{#if customized}
<div
class="flex justify-end px-2 py-1 text-xs text-gray-500 dark:text-gray-400"
>
<button
type="button"
class="hover:text-gray-900 disabled:opacity-40 dark:hover:text-gray-100"
on:click={() => Object.keys(fields).forEach(clearLocalizedField)}
>{$i18n.t('Use default')}</button
>
</div>
{/if}
</ModelSettingsSection>
{/if}
</fieldset>
</div>
</section>

View file

@ -1,3 +1,5 @@
import type { ModelControl } from '$lib/apis';
type LocaleEntry = Record<string, any>;
type LocalizedMap = Record<string, LocaleEntry>;
@ -117,6 +119,43 @@ export const valveTranslationSource = (schema: any, prefix: string): Record<stri
return strings;
};
export const modelControlTranslationSource = (
controls: Record<string, ModelControl> = {}
): Record<string, string> => {
const strings: Record<string, string> = {};
for (const [key, control] of Object.entries(controls)) {
strings[`model_controls.${key}.label`] = control.label;
if (control.description) strings[`model_controls.${key}.description`] = control.description;
for (const [value, option] of Object.entries(control.options)) {
strings[`model_controls.${key}.options.${value}.label`] = option.label;
}
}
return strings;
};
export const localizeModelControls = (model: any, locale: string): Record<string, ModelControl> => {
const translate = (value: string | undefined, key: string) =>
resolveLocalizedString(value, model?.info?.meta?.i18n, locale, `model_controls.${key}`);
return Object.fromEntries(
Object.entries<ModelControl>(model?.info?.params?.model_controls ?? {}).map(
([key, control]) => [
key,
{
...control,
label: translate(control.label, `${key}.label`),
description: translate(control.description, `${key}.description`),
options: Object.fromEntries(
Object.entries(control.options).map(([value, option]) => [
value,
{ ...option, label: translate(option.label, `${key}.options.${value}.label`) }
])
)
}
]
)
);
};
export const resolveLocalizedModelName = (model: any, locale?: string | null) => {
const meta = model?.info?.meta ?? model?.meta;
const info = model?.info ?? model;