mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-19 14:41:24 +08:00
* feat: 新增文件写入功能,支持通过 ID 写入文件并加载自定义小应用配置。 * feat(i18n): 添加自定义小程序配置的多语言支持,包括英文、简体中文和繁体中文。 * fix(minapps): 使用 await 加载自定义小应用并合并到默认应用中,同时添加日志输出以便调试 * fix(minapps): 在开发环境中添加条件日志输出,以便调试加载的默认小应用。 * refactor(miniappSettings): 移动自定义小应用编辑区域的位置,优化界面布局。 * refactor(miniappSettings): 修改自定义小应用保存逻辑,优化应用列表重新加载方式。 * feat(i18n): 修复在merge过程中丢失的语言设置。 * fix(bug_risk): Consider adding stricter validation for the JSON config on load. Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> * feat(miniapp): 添加自定义小应用功能,优化应用列表展示,支持通过模态框添加新应用。 * feat(App): enhance custom app modal to support logo upload via URL. * feat(miniapp): add application logo support and update mini app list reloading logic. * feat(i18n): update mini app custom settings translations for multiple languages. * feat(miniapp): add updateDefaultMinApps function and refactor mini app list reloading logic. * feat(miniapp): add removeCustom functionality to handle custom mini app deletion * feat(miniapp): add duplicate ID check when adding custom mini apps. * feat(i18n): 重构侧边栏相关翻译为结构化格式,增加删除自定义应用的翻译支持。 * feat(miniapp): 优化删除自定义应用的逻辑,使用条件渲染简化代码结构。 * feat(miniapp): 添加自定义小应用内容的空值处理,确保 JSON 格式有效。 * feat(i18n): 更新默认语言为英语,并移除多个语言文件中的默认代理字段。 * feat(i18n): 为多个语言文件添加自定义小应用配置编辑描述翻译。 * feat(i18n): add success and error messages for deleting custom mini apps in multiple language files. * feat(i18n): update success and error messages for custom mini app operations and add placeholder text in multiple language files. * feat(i18n): 为多个语言文件添加重复ID和冲突ID的错误信息翻译,并在自定义小应用设置中实现相关检查逻辑。 * feat(miniapp): 在添加自定义小应用时,增加对默认最小应用ID的重复检查逻辑。 * feat(i18n): update edit description for custom mini app configuration in Traditional Chinese locale * fix(miniapp): enhance error messages for duplicate and conflicting IDs in custom mini app configuration --------- Co-authored-by: George Zhao <georgezhao@SKJLAB> Co-authored-by: sourcery-ai[bot] <58596630+sourcery-ai[bot]@users.noreply.github.com> Co-authored-by: suyao <sy20010504@gmail.com>
105 lines
3.5 KiB
JavaScript
105 lines
3.5 KiB
JavaScript
'use strict'
|
||
Object.defineProperty(exports, '__esModule', { value: true })
|
||
var fs = require('fs')
|
||
var path = require('path')
|
||
var translationsDir = path.join(__dirname, '../src/renderer/src/i18n/locales')
|
||
var baseLocale = 'en-us'
|
||
var baseFileName = ''.concat(baseLocale, '.json')
|
||
var baseFilePath = path.join(translationsDir, baseFileName)
|
||
/**
|
||
* 递归同步 target 对象,使其与 template 对象保持一致
|
||
* 1. 如果 template 中存在 target 中缺少的 key,则添加('[to be translated]')
|
||
* 2. 如果 target 中存在 template 中不存在的 key,则删除
|
||
* 3. 对于子对象,递归同步
|
||
*
|
||
* @param target 目标对象(需要更新的语言对象)
|
||
* @param template 主模板对象(中文)
|
||
* @returns 返回是否对 target 进行了更新
|
||
*/
|
||
function syncRecursively(target, template) {
|
||
var isUpdated = false
|
||
// 添加 template 中存在但 target 中缺少的 key
|
||
for (var key in template) {
|
||
if (!(key in target)) {
|
||
target[key] =
|
||
typeof template[key] === 'object' && template[key] !== null ? {} : '[to be translated]:'.concat(template[key])
|
||
console.log('\u6DFB\u52A0\u65B0\u5C5E\u6027\uFF1A'.concat(key))
|
||
isUpdated = true
|
||
}
|
||
if (typeof template[key] === 'object' && template[key] !== null) {
|
||
if (typeof target[key] !== 'object' || target[key] === null) {
|
||
target[key] = {}
|
||
isUpdated = true
|
||
}
|
||
// 递归同步子对象
|
||
var childUpdated = syncRecursively(target[key], template[key])
|
||
if (childUpdated) {
|
||
isUpdated = true
|
||
}
|
||
}
|
||
}
|
||
// 删除 target 中存在但 template 中没有的 key
|
||
for (var targetKey in target) {
|
||
if (!(targetKey in template)) {
|
||
console.log('\u79FB\u9664\u591A\u4F59\u5C5E\u6027\uFF1A'.concat(targetKey))
|
||
delete target[targetKey]
|
||
isUpdated = true
|
||
}
|
||
}
|
||
return isUpdated
|
||
}
|
||
function syncTranslations() {
|
||
if (!fs.existsSync(baseFilePath)) {
|
||
console.error(
|
||
'\u4E3B\u6A21\u677F\u6587\u4EF6 '.concat(
|
||
baseFileName,
|
||
' \u4E0D\u5B58\u5728\uFF0C\u8BF7\u68C0\u67E5\u8DEF\u5F84\u6216\u6587\u4EF6\u540D\u3002'
|
||
)
|
||
)
|
||
return
|
||
}
|
||
var baseContent = fs.readFileSync(baseFilePath, 'utf-8')
|
||
var baseJson = {}
|
||
try {
|
||
baseJson = JSON.parse(baseContent)
|
||
} catch (error) {
|
||
console.error('\u89E3\u6790 '.concat(baseFileName, ' \u51FA\u9519:'), error)
|
||
return
|
||
}
|
||
var files = fs.readdirSync(translationsDir).filter(function (file) {
|
||
return file.endsWith('.json') && file !== baseFileName
|
||
})
|
||
for (var _i = 0, files_1 = files; _i < files_1.length; _i++) {
|
||
var file = files_1[_i]
|
||
var filePath = path.join(translationsDir, file)
|
||
var targetJson = {}
|
||
try {
|
||
var fileContent = fs.readFileSync(filePath, 'utf-8')
|
||
targetJson = JSON.parse(fileContent)
|
||
} catch (error) {
|
||
console.error(
|
||
'\u89E3\u6790 '.concat(
|
||
file,
|
||
' \u51FA\u9519\uFF0C\u8DF3\u8FC7\u6B64\u6587\u4EF6\u3002\u9519\u8BEF\u4FE1\u606F:'
|
||
),
|
||
error
|
||
)
|
||
continue
|
||
}
|
||
var isUpdated = syncRecursively(targetJson, baseJson)
|
||
if (isUpdated) {
|
||
try {
|
||
fs.writeFileSync(filePath, JSON.stringify(targetJson, null, 2), 'utf-8')
|
||
console.log(
|
||
'\u6587\u4EF6 '.concat(file, ' \u5DF2\u66F4\u65B0\u540C\u6B65\u4E3B\u6A21\u677F\u7684\u5185\u5BB9\u3002')
|
||
)
|
||
} catch (error) {
|
||
console.error('\u5199\u5165 '.concat(file, ' \u51FA\u9519:'), error)
|
||
}
|
||
} else {
|
||
console.log('\u6587\u4EF6 '.concat(file, ' \u65E0\u9700\u66F4\u65B0\u3002'))
|
||
}
|
||
}
|
||
}
|
||
syncTranslations()
|