mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2025-12-23 10:00:08 +08:00
ci(auto-i18n): disable package manager cache for node setup (#10957)
* ci(github): disable package manager cache for node setup * refactor(i18n): translate sync script comments to english Update all Chinese comments and log messages in sync-i18n.ts to English for better international collaboration * style(scripts): format error message string in sync-i18n.ts
This commit is contained in:
parent
1f0fd8215a
commit
dedfc79406
1
.github/workflows/auto-i18n.yml
vendored
1
.github/workflows/auto-i18n.yml
vendored
@ -29,6 +29,7 @@ jobs:
|
|||||||
uses: actions/setup-node@v5
|
uses: actions/setup-node@v5
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
|
package-manager-cache: false
|
||||||
|
|
||||||
- name: 📦 Install dependencies in isolated directory
|
- name: 📦 Install dependencies in isolated directory
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@ -13,45 +13,45 @@ type I18NValue = string | { [key: string]: I18NValue }
|
|||||||
type I18N = { [key: string]: I18NValue }
|
type I18N = { [key: string]: I18NValue }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 递归同步 target 对象,使其与 template 对象保持一致
|
* Recursively sync target object to match template object structure
|
||||||
* 1. 如果 template 中存在 target 中缺少的 key,则添加('[to be translated]')
|
* 1. Add keys that exist in template but missing in target (with '[to be translated]')
|
||||||
* 2. 如果 target 中存在 template 中不存在的 key,则删除
|
* 2. Remove keys that exist in target but not in template
|
||||||
* 3. 对于子对象,递归同步
|
* 3. Recursively sync nested objects
|
||||||
*
|
*
|
||||||
* @param target 目标对象(需要更新的语言对象)
|
* @param target Target object (language object to be updated)
|
||||||
* @param template 主模板对象(中文)
|
* @param template Base locale object (Chinese)
|
||||||
* @returns 返回是否对 target 进行了更新
|
* @returns Returns whether target was updated
|
||||||
*/
|
*/
|
||||||
function syncRecursively(target: I18N, template: I18N): void {
|
function syncRecursively(target: I18N, template: I18N): void {
|
||||||
// 添加 template 中存在但 target 中缺少的 key
|
// Add keys that exist in template but missing in target
|
||||||
for (const key in template) {
|
for (const key in template) {
|
||||||
if (!(key in target)) {
|
if (!(key in target)) {
|
||||||
target[key] =
|
target[key] =
|
||||||
typeof template[key] === 'object' && template[key] !== null ? {} : `[to be translated]:${template[key]}`
|
typeof template[key] === 'object' && template[key] !== null ? {} : `[to be translated]:${template[key]}`
|
||||||
console.log(`添加新属性:${key}`)
|
console.log(`Added new property: ${key}`)
|
||||||
}
|
}
|
||||||
if (typeof template[key] === 'object' && template[key] !== null) {
|
if (typeof template[key] === 'object' && template[key] !== null) {
|
||||||
if (typeof target[key] !== 'object' || target[key] === null) {
|
if (typeof target[key] !== 'object' || target[key] === null) {
|
||||||
target[key] = {}
|
target[key] = {}
|
||||||
}
|
}
|
||||||
// 递归同步子对象
|
// Recursively sync nested objects
|
||||||
syncRecursively(target[key], template[key])
|
syncRecursively(target[key], template[key])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 删除 target 中存在但 template 中没有的 key
|
// Remove keys that exist in target but not in template
|
||||||
for (const targetKey in target) {
|
for (const targetKey in target) {
|
||||||
if (!(targetKey in template)) {
|
if (!(targetKey in template)) {
|
||||||
console.log(`移除多余属性:${targetKey}`)
|
console.log(`Removed excess property: ${targetKey}`)
|
||||||
delete target[targetKey]
|
delete target[targetKey]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查 JSON 对象中是否存在重复键,并收集所有重复键
|
* Check JSON object for duplicate keys and collect all duplicates
|
||||||
* @param obj 要检查的对象
|
* @param obj Object to check
|
||||||
* @returns 返回重复键的数组(若无重复则返回空数组)
|
* @returns Returns array of duplicate keys (empty array if no duplicates)
|
||||||
*/
|
*/
|
||||||
function checkDuplicateKeys(obj: I18N): string[] {
|
function checkDuplicateKeys(obj: I18N): string[] {
|
||||||
const keys = new Set<string>()
|
const keys = new Set<string>()
|
||||||
@ -62,7 +62,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
|
|||||||
const fullPath = path ? `${path}.${key}` : key
|
const fullPath = path ? `${path}.${key}` : key
|
||||||
|
|
||||||
if (keys.has(fullPath)) {
|
if (keys.has(fullPath)) {
|
||||||
// 发现重复键时,添加到数组中(避免重复添加)
|
// When duplicate key found, add to array (avoid duplicate additions)
|
||||||
if (!duplicateKeys.includes(fullPath)) {
|
if (!duplicateKeys.includes(fullPath)) {
|
||||||
duplicateKeys.push(fullPath)
|
duplicateKeys.push(fullPath)
|
||||||
}
|
}
|
||||||
@ -70,7 +70,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
|
|||||||
keys.add(fullPath)
|
keys.add(fullPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 递归检查子对象
|
// Recursively check nested objects
|
||||||
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
if (typeof obj[key] === 'object' && obj[key] !== null) {
|
||||||
checkObject(obj[key], fullPath)
|
checkObject(obj[key], fullPath)
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ function checkDuplicateKeys(obj: I18N): string[] {
|
|||||||
|
|
||||||
function syncTranslations() {
|
function syncTranslations() {
|
||||||
if (!fs.existsSync(baseFilePath)) {
|
if (!fs.existsSync(baseFilePath)) {
|
||||||
console.error(`主模板文件 ${baseFileName} 不存在,请检查路径或文件名`)
|
console.error(`Base locale file ${baseFileName} does not exist, please check path or filename`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,24 +92,24 @@ function syncTranslations() {
|
|||||||
try {
|
try {
|
||||||
baseJson = JSON.parse(baseContent)
|
baseJson = JSON.parse(baseContent)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`解析 ${baseFileName} 出错。${error}`)
|
console.error(`Error parsing ${baseFileName}. ${error}`)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查主模板是否存在重复键
|
// Check if base locale has duplicate keys
|
||||||
const duplicateKeys = checkDuplicateKeys(baseJson)
|
const duplicateKeys = checkDuplicateKeys(baseJson)
|
||||||
if (duplicateKeys.length > 0) {
|
if (duplicateKeys.length > 0) {
|
||||||
throw new Error(`主模板文件 ${baseFileName} 存在以下重复键:\n${duplicateKeys.join('\n')}`)
|
throw new Error(`Base locale file ${baseFileName} has the following duplicate keys:\n${duplicateKeys.join('\n')}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为主模板排序
|
// Sort base locale
|
||||||
const sortedJson = sortedObjectByKeys(baseJson)
|
const sortedJson = sortedObjectByKeys(baseJson)
|
||||||
if (JSON.stringify(baseJson) !== JSON.stringify(sortedJson)) {
|
if (JSON.stringify(baseJson) !== JSON.stringify(sortedJson)) {
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(baseFilePath, JSON.stringify(sortedJson, null, 2) + '\n', 'utf-8')
|
fs.writeFileSync(baseFilePath, JSON.stringify(sortedJson, null, 2) + '\n', 'utf-8')
|
||||||
console.log(`主模板已排序`)
|
console.log(`Base locale has been sorted`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`写入 ${baseFilePath} 出错。`, error)
|
console.error(`Error writing ${baseFilePath}.`, error)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,7 +124,7 @@ function syncTranslations() {
|
|||||||
.map((filename) => path.join(translateDir, filename))
|
.map((filename) => path.join(translateDir, filename))
|
||||||
const files = [...localeFiles, ...translateFiles]
|
const files = [...localeFiles, ...translateFiles]
|
||||||
|
|
||||||
// 同步键
|
// Sync keys
|
||||||
for (const filePath of files) {
|
for (const filePath of files) {
|
||||||
const filename = path.basename(filePath)
|
const filename = path.basename(filePath)
|
||||||
let targetJson: I18N = {}
|
let targetJson: I18N = {}
|
||||||
@ -132,7 +132,7 @@ function syncTranslations() {
|
|||||||
const fileContent = fs.readFileSync(filePath, 'utf-8')
|
const fileContent = fs.readFileSync(filePath, 'utf-8')
|
||||||
targetJson = JSON.parse(fileContent)
|
targetJson = JSON.parse(fileContent)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`解析 ${filename} 出错,跳过此文件。`, error)
|
console.error(`Error parsing ${filename}, skipping this file.`, error)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,9 +142,9 @@ function syncTranslations() {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(filePath, JSON.stringify(sortedJson, null, 2) + '\n', 'utf-8')
|
fs.writeFileSync(filePath, JSON.stringify(sortedJson, null, 2) + '\n', 'utf-8')
|
||||||
console.log(`文件 ${filename} 已排序并同步更新为主模板的内容`)
|
console.log(`File ${filename} has been sorted and synced to match base locale content`)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(`写入 ${filename} 出错。${error}`)
|
console.error(`Error writing ${filename}. ${error}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user