Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion apps/desktop/src/app/settings/config-settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,13 @@ export function ConfigSettings({
: enumOptionsFor(key, getNested(config, key), config)
}
onChange={value => updateConfig(setNested(config, key, value))}
optionLabels={key === 'tts.elevenlabs.voice_id' ? elevenLabsVoiceLabels : undefined}
optionLabels={
key === 'tts.elevenlabs.voice_id'
? elevenLabsVoiceLabels
: key === 'display.personality'
? t.settings.config.personalityLabels
: undefined
}
schema={field}
schemaKey={key}
value={getNested(config, key)}
Expand Down
22 changes: 22 additions & 0 deletions apps/desktop/src/app/settings/helpers.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { describe, expect, it } from 'vitest'

import { TRANSLATIONS } from '@/i18n/catalog'
import type { HermesConfigRecord } from '@/types/hermes'

import { BUILTIN_PERSONALITIES } from './constants'
import { defineFieldCopy, fieldCopyForSchemaKey, schemaKeyToFieldCopyKey } from './field-copy'
import {
enumOptionsFor,
Expand Down Expand Up @@ -42,6 +44,26 @@ describe('settings helpers', () => {
})
})

describe('personalityLabels', () => {
it('covers every built-in personality in every locale', () => {
for (const [locale, catalog] of Object.entries(TRANSLATIONS)) {
for (const id of BUILTIN_PERSONALITIES) {
expect(catalog.settings.config.personalityLabels[id], `${locale}: ${id}`).toBeTruthy()
}
}
})

it('actually translates labels in non-English locales (not just the English fallback)', () => {
const english = TRANSLATIONS.en.settings.config.personalityLabels

for (const locale of ['zh', 'zh-hant', 'ja'] as const) {
const labels = TRANSLATIONS[locale].settings.config.personalityLabels
expect(labels.pirate, `${locale}: pirate should differ from English`).not.toBe(english.pirate)
expect(labels.teacher, `${locale}: teacher should differ from English`).not.toBe(english.teacher)
}
})
})

describe('defineFieldCopy', () => {
it('flattens nested field copy paths', () => {
const copy = defineFieldCopy({
Expand Down
20 changes: 19 additions & 1 deletion apps/desktop/src/i18n/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -522,7 +522,25 @@ export const en: Translations = {
failedLoad: 'Settings failed to load',
autosaveFailed: 'Autosave failed',
imported: 'Config imported',
invalidJson: 'Invalid config JSON'
invalidJson: 'Invalid config JSON',
// Display names for the built-in personalities (config IDs stay English).
// Custom personalities fall back to prettyName(id) in the picker.
personalityLabels: {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a matching Japanese override in ja.ts. ja is registered in the catalog and defineLocale() fills absent keys from this English map, so without an override the Japanese picker still displays English labels; the current truthiness test will not catch that fallback.

helpful: 'Helpful',
concise: 'Concise',
technical: 'Technical',
creative: 'Creative',
teacher: 'Teacher',
kawaii: 'Kawaii',
catgirl: 'Catgirl',
pirate: 'Pirate',
shakespeare: 'Shakespeare',
surfer: 'Surfer',
noir: 'Noir',
uwu: 'uwu',
philosopher: 'Philosopher',
hype: 'Hype'
}
},
credentials: {
pasteKey: 'Paste key',
Expand Down
18 changes: 17 additions & 1 deletion apps/desktop/src/i18n/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,7 +620,23 @@ export const ja = defineLocale({
failedLoad: '設定の読み込みに失敗しました',
autosaveFailed: '自動保存に失敗しました',
imported: '設定をインポートしました',
invalidJson: '設定 JSON が無効です'
invalidJson: '設定 JSON が無効です',
personalityLabels: {
helpful: '親切',
concise: '簡潔',
technical: 'テクニカル',
creative: 'クリエイティブ',
teacher: '先生',
kawaii: 'カワイイ',
catgirl: 'ネコガール',
pirate: '海賊',
shakespeare: 'シェイクスピア',
surfer: 'サーファー',
noir: 'ノワール',
uwu: 'uwu',
philosopher: '哲学者',
hype: 'ハイテンション'
}
},
credentials: {
pasteKey: 'キーを貼り付け',
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/i18n/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,7 @@ export interface Translations {
autosaveFailed: string
imported: string
invalidJson: string
personalityLabels: Record<string, string>
}
credentials: {
pasteKey: string
Expand Down
Loading