Files
hy 1eedabb914 feat: add support for language and service route preferences
- Updated ModelSource type to include 'huggingface'.
- Enhanced MODEL_SOURCE_LABELS for better clarity.
- Introduced defaultModelSource function to determine default source based on service route.
- Modified AppSettings to include language and serviceRoute.
- Created end-to-end tests for language and service route settings.
- Added unit tests for application language and service preferences.
- Updated free models test to reflect new catalog naming conventions.
- Enhanced official API tests to ensure correct handling of service regions.
- Adjusted release artifact tests to accommodate internationalization.
- Updated SQLite migration and storage tests to include new preferences.
2026-10-21 10:05:42 +08:00

59 lines
2.0 KiB
JavaScript

import fs from 'node:fs'
import ts from 'typescript'
let source
const read = (node) => {
if (ts.isAsExpression(node)) return read(node.expression)
if (ts.isStringLiteral(node)) return node.text
if (ts.isObjectLiteralExpression(node))
return Object.fromEntries(
node.properties.map((property) => {
if (!ts.isPropertyAssignment(property))
throw new Error('Translation resources must be literal objects')
return [
property.name.getText(source).replace(/^['"]|['"]$/g, ''),
read(property.initializer)
]
})
)
throw new Error('Translation resources must contain strings only')
}
const resources = {}
for (const [locale, filename] of [
['zh', 'zh-CN.ts'],
['en', 'en.ts']
]) {
source = ts.createSourceFile(
filename,
fs.readFileSync(`src/renderer/src/i18n/${filename}`, 'utf8'),
ts.ScriptTarget.Latest,
true
)
for (const statement of source.statements) {
if (!ts.isVariableStatement(statement)) continue
for (const declaration of statement.declarationList.declarations) {
if (declaration.name.getText(source) === locale)
resources[locale] = read(declaration.initializer)
}
}
}
const flatten = (object, prefix = '') =>
Object.fromEntries(
Object.entries(object).flatMap(([key, value]) =>
typeof value === 'string'
? [[`${prefix}${key}`, value]]
: Object.entries(flatten(value, `${prefix}${key}.`))
)
)
const zh = flatten(resources.zh),
en = flatten(resources.en)
const placeholders = (value) =>
[...new Set(value.match(/\{\{\w+\}\}|\$\{\w+\}|\{\d+\}/g) || [])].sort().join(',')
if (Object.keys(zh).sort().join('\n') !== Object.keys(en).sort().join('\n'))
throw new Error('Chinese and English translation keys differ')
for (const key of Object.keys(zh)) {
if (!en[key].trim() || placeholders(zh[key]) !== placeholders(en[key]))
throw new Error(`Translation placeholders differ: ${key}`)
}
process.stdout.write(`[i18n] ${Object.keys(zh).length} bilingual keys validated\n`)