Skip to content
Merged
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
13 changes: 11 additions & 2 deletions BitFun-Installer/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Install BitFun</title>
<script>
(function () {
var dark = '#121214';
var light = '#e8ecf2';
var m = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)');
document.documentElement.style.backgroundColor = m && m.matches ? dark : light;
})();
</script>
<style>
/* Prevent flash of white during load */
html, body { background: transparent; margin: 0; padding: 0; }
html, body { margin: 0; padding: 0; }
html { background-color: #121214; }
body { background-color: inherit; }
</style>
</head>
<body>
Expand Down
126 changes: 92 additions & 34 deletions BitFun-Installer/scripts/sync-model-i18n.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -54,39 +54,93 @@ function buildProviderPatch(settingsAiModel) {
return providerPatch;
}

function buildModelPatch(onboarding, settingsAiModel, languageTag) {
function buildFormPatch(form) {
if (!form || typeof form !== 'object') return {};
return {
baseUrl: form.baseUrl ?? '',
apiKey: form.apiKey ?? '',
apiKeyPlaceholder: form.apiKeyPlaceholder ?? '',
provider: form.provider ?? '',
providerPlaceholder: form.providerPlaceholder ?? '',
modelSelection: form.modelSelection ?? '',
modelName: form.modelName ?? '',
resolvedUrlLabel: form.resolvedUrlLabel ?? '',
};
}

function buildFormatsPatch(formats) {
if (!formats || typeof formats !== 'object') return {};
return {
openaiCompatible: formats.openaiCompatible ?? '',
responsesApi: formats.responsesApi ?? '',
claudeApi: formats.claudeApi ?? '',
geminiApi: formats.geminiApi ?? '',
};
}

function buildModelPatch(settingsAiModel, languageTag, components) {
const isZh = languageTag === 'zh';
const form = get(settingsAiModel, 'form', {});
const formats = get(settingsAiModel, 'formats', {});
const input = get(components, 'input', {});
return {
description: get(
onboarding,
'model.description',
settingsAiModel,
'subtitle',
'Configure AI model provider, API key, and advanced parameters.'
),
providerLabel: get(onboarding, 'model.provider.label', 'Model Provider'),
selectProvider: get(onboarding, 'model.provider.placeholder', 'Select a provider...'),
customProvider: get(onboarding, 'model.provider.options.custom', 'Custom'),
getApiKey: get(onboarding, 'model.apiKey.help', 'How to get an API Key?'),
modelNamePlaceholder: get(
onboarding,
'model.modelName.inputPlaceholder',
get(onboarding, 'model.modelName.placeholder', 'Enter model name...')
providerLabel: get(settingsAiModel, 'providerSelection.title', 'Model Provider'),
selectProvider: get(settingsAiModel, 'providerSelection.orSelectProvider', 'Select a provider...'),
customProvider: get(settingsAiModel, 'providerSelection.customTitle', 'Custom'),
getApiKey: get(settingsAiModel, 'providerSelection.getApiKey', 'How to get an API Key?'),
fillApiKeyBeforeFetch: get(
settingsAiModel,
'providerSelection.fillApiKeyBeforeFetch',
'Enter the API key before fetching models'
),
fetchingModels: get(settingsAiModel, 'providerSelection.fetchingModels', 'Fetching model list...'),
fetchFailedFallback: get(
settingsAiModel,
'providerSelection.fetchFailedFallback',
'Failed to fetch model list, fell back to common preset models'
),
fetchEmptyFallback: get(
settingsAiModel,
'providerSelection.fetchEmptyFallback',
'Provider returned no models, fell back to common preset models'
),
modelNameSelectPlaceholder: get(onboarding, 'model.modelName.selectPlaceholder', 'Select a model...'),
modelSearchPlaceholder: get(
onboarding,
'model.modelName.searchPlaceholder',
'Search or enter a custom model name...'
usingPresetModels: get(
settingsAiModel,
'providerSelection.usingPresetModels',
'Currently showing common preset models'
),
modelNamePlaceholder: get(
settingsAiModel,
'providerSelection.inputModelName',
get(settingsAiModel, 'form.modelName', 'Enter model name...')
),
modelNameSelectPlaceholder: get(settingsAiModel, 'providerSelection.selectModel', 'Select a model...'),
modelNoResults: isZh ? '没有匹配的模型' : 'No matching models',
customModel: get(onboarding, 'model.modelName.customHint', 'Use custom model name'),
baseUrlPlaceholder: get(onboarding, 'model.baseUrl.placeholder', 'Enter API URL'),
/** Installer: use addCustomModel (not useCustomModel / "Press Enter") for the extra dropdown option */
addCustomModel: get(settingsAiModel, 'providerSelection.addCustomModel', 'Add Custom Model'),
form: buildFormPatch(form),
formats: buildFormatsPatch(formats),
showSecret: get(input, 'show', 'Show'),
hideSecret: get(input, 'hide', 'Hide'),
baseUrlPlaceholder: isZh
? '示例:https://open.bigmodel.cn/api/paas/v4/chat/completions'
: 'e.g., https://open.bigmodel.cn/api/paas/v4/chat/completions',
customRequestBodyPlaceholder: get(
onboarding,
'model.advanced.customRequestBodyPlaceholder',
settingsAiModel,
'advancedSettings.customRequestBody.placeholder',
'{\n "temperature": 0.8,\n "top_p": 0.9\n}'
),
jsonValid: get(onboarding, 'model.advanced.jsonValid', 'Valid JSON format'),
jsonInvalid: get(onboarding, 'model.advanced.jsonInvalid', 'Invalid JSON format'),
jsonValid: get(settingsAiModel, 'advancedSettings.customRequestBody.validJson', 'Valid JSON format'),
jsonInvalid: get(
settingsAiModel,
'advancedSettings.customRequestBody.invalidJson',
'Invalid JSON format'
),
skipSslVerify: get(
settingsAiModel,
'advancedSettings.skipSslVerify.label',
Expand All @@ -105,10 +159,10 @@ function buildModelPatch(onboarding, settingsAiModel, languageTag) {
addHeader: get(settingsAiModel, 'advancedSettings.customHeaders.addHeader', 'Add Field'),
headerKey: get(settingsAiModel, 'advancedSettings.customHeaders.keyPlaceholder', 'key'),
headerValue: get(settingsAiModel, 'advancedSettings.customHeaders.valuePlaceholder', 'value'),
testConnection: get(onboarding, 'model.testConnection', 'Test Connection'),
testing: get(onboarding, 'model.testing', 'Testing...'),
testSuccess: get(onboarding, 'model.testSuccess', 'Connection successful'),
testFailed: get(onboarding, 'model.testFailed', 'Connection failed'),
testConnection: get(settingsAiModel, 'actions.test', 'Test Connection'),
testing: isZh ? '测试中...' : 'Testing...',
testSuccess: get(settingsAiModel, 'messages.testSuccess', 'Connection successful'),
testFailed: get(settingsAiModel, 'messages.testFailed', 'Connection failed'),
advancedShow: 'Show advanced settings',
advancedHide: 'Hide advanced settings',
providers: buildProviderPatch(settingsAiModel),
Expand All @@ -119,34 +173,38 @@ function syncOne(languageTag) {
const localeDir = languageTag === 'zh' ? 'zh-CN' : 'en-US';
const installerLocale = languageTag === 'zh' ? 'zh.json' : 'en.json';

const sourceOnboardingPath = path.join(
const sourceAiModelPath = path.join(
PROJECT_ROOT,
'src',
'web-ui',
'src',
'locales',
localeDir,
'onboarding.json'
'settings',
'ai-model.json'
);

const sourceAiModelPath = path.join(
const sourceComponentsPath = path.join(
PROJECT_ROOT,
'src',
'web-ui',
'src',
'locales',
localeDir,
'settings',
'ai-model.json'
'components.json'
);

const targetPath = path.join(INSTALLER_ROOT, 'src', 'i18n', 'locales', installerLocale);

const onboarding = readJson(sourceOnboardingPath);
const settingsAiModel = readJson(sourceAiModelPath);
let components = {};
try {
components = readJson(sourceComponentsPath);
} catch {
// optional
}
const target = readJson(targetPath);

const patch = buildModelPatch(onboarding, settingsAiModel, languageTag);
const patch = buildModelPatch(settingsAiModel, languageTag, components);
target.model = mergeDeep(target.model || {}, patch);

writeJson(targetPath, target);
Expand Down
9 changes: 5 additions & 4 deletions BitFun-Installer/scripts/sync-theme-i18n.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ function writeJson(filePath, data) {
}

function extractThemeNames(source, sourceLabel) {
const presets = source?.theme?.presets;
// Theme preset names live under settings/basics.json → appearance.presets (formerly theme.json → theme.presets).
const presets = source?.appearance?.presets;
if (!presets || typeof presets !== "object") {
throw new Error(`Invalid theme presets in ${sourceLabel}`);
throw new Error(`Invalid appearance.presets in ${sourceLabel}`);
}

const result = {};
Expand Down Expand Up @@ -61,7 +62,7 @@ function main() {
"locales",
"en-US",
"settings",
"theme.json"
"basics.json"
);
const sourceZhPath = path.join(
PROJECT_ROOT,
Expand All @@ -71,7 +72,7 @@ function main() {
"locales",
"zh-CN",
"settings",
"theme.json"
"basics.json"
);

const targetEnPath = path.join(
Expand Down
1 change: 1 addition & 0 deletions BitFun-Installer/src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ flate2 = "1.0"
tar = "0.4"
chrono = "0.4"
reqwest = { version = "0.12", default-features = false, features = ["json", "rustls-tls"] }
urlencoding = "2"

[target.'cfg(windows)'.dependencies]
winreg = "0.52"
Expand Down
Loading
Loading