mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-08-28 05:27:24 +00:00
i18n Add translations for task pinning and unpinning (#2109)
Signed-off-by: feifei <liuyansheng1121@gmail.com>
This commit is contained in:
parent
2303f67afb
commit
cf487fbfae
18 changed files with 87 additions and 29 deletions
|
|
@ -34,9 +34,17 @@ Output:
|
|||
process.exit(0)
|
||||
}
|
||||
|
||||
// Directory to traverse
|
||||
const TARGET_DIR = path.join(__dirname, "../webview-ui/src/components")
|
||||
const LOCALES_DIR = path.join(__dirname, "../webview-ui/src/i18n/locales")
|
||||
// Directories to traverse and their corresponding locales
|
||||
const DIRS = {
|
||||
components: {
|
||||
path: path.join(__dirname, "../webview-ui/src/components"),
|
||||
localesDir: path.join(__dirname, "../webview-ui/src/i18n/locales"),
|
||||
},
|
||||
src: {
|
||||
path: path.join(__dirname, "../src"),
|
||||
localesDir: path.join(__dirname, "../src/i18n/locales"),
|
||||
},
|
||||
}
|
||||
|
||||
// Regular expressions to match i18n keys
|
||||
const i18nPatterns = [
|
||||
|
|
@ -45,15 +53,23 @@ const i18nPatterns = [
|
|||
/t\("([a-zA-Z][a-zA-Z0-9_]*[:.][a-zA-Z0-9_.]+)"\)/g, // Match t("key") format, where key contains a colon or dot
|
||||
]
|
||||
|
||||
// Get all language directories
|
||||
function getLocaleDirs() {
|
||||
const allLocales = fs.readdirSync(LOCALES_DIR).filter((file) => {
|
||||
const stats = fs.statSync(path.join(LOCALES_DIR, file))
|
||||
return stats.isDirectory() // Do not exclude any language directories
|
||||
})
|
||||
// Get all language directories for a specific locales directory
|
||||
function getLocaleDirs(localesDir) {
|
||||
try {
|
||||
const allLocales = fs.readdirSync(localesDir).filter((file) => {
|
||||
const stats = fs.statSync(path.join(localesDir, file))
|
||||
return stats.isDirectory() // Do not exclude any language directories
|
||||
})
|
||||
|
||||
// Filter to a specific language if specified
|
||||
return args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
|
||||
// Filter to a specific language if specified
|
||||
return args.locale ? allLocales.filter((locale) => locale === args.locale) : allLocales
|
||||
} catch (error) {
|
||||
if (error.code === "ENOENT") {
|
||||
console.warn(`Warning: Locales directory not found: ${localesDir}`)
|
||||
return []
|
||||
}
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// Get the value from JSON by path
|
||||
|
|
@ -72,14 +88,14 @@ function getValueByPath(obj, path) {
|
|||
}
|
||||
|
||||
// Check if the key exists in all language files, return a list of missing language files
|
||||
function checkKeyInLocales(key, localeDirs) {
|
||||
function checkKeyInLocales(key, localeDirs, localesDir) {
|
||||
const [file, ...pathParts] = key.split(":")
|
||||
const jsonPath = pathParts.join(".")
|
||||
|
||||
const missingLocales = []
|
||||
|
||||
localeDirs.forEach((locale) => {
|
||||
const filePath = path.join(LOCALES_DIR, locale, `${file}.json`)
|
||||
const filePath = path.join(localesDir, locale, `${file}.json`)
|
||||
if (!fs.existsSync(filePath)) {
|
||||
missingLocales.push(`${locale}/${file}.json`)
|
||||
return
|
||||
|
|
@ -96,21 +112,20 @@ function checkKeyInLocales(key, localeDirs) {
|
|||
|
||||
// Recursively traverse the directory
|
||||
function findMissingI18nKeys() {
|
||||
const localeDirs = getLocaleDirs()
|
||||
const results = []
|
||||
|
||||
function walk(dir) {
|
||||
function walk(dir, baseDir, localeDirs, localesDir) {
|
||||
const files = fs.readdirSync(dir)
|
||||
|
||||
for (const file of files) {
|
||||
const filePath = path.join(dir, file)
|
||||
const stat = fs.statSync(filePath)
|
||||
|
||||
// Exclude test files
|
||||
if (filePath.includes(".test.")) continue
|
||||
// Exclude test files and __mocks__ directory
|
||||
if (filePath.includes(".test.") || filePath.includes("__mocks__")) continue
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
walk(filePath) // Recursively traverse subdirectories
|
||||
walk(filePath, baseDir, localeDirs, localesDir) // Recursively traverse subdirectories
|
||||
} else if (stat.isFile() && [".ts", ".tsx", ".js", ".jsx"].includes(path.extname(filePath))) {
|
||||
const content = fs.readFileSync(filePath, "utf8")
|
||||
|
||||
|
|
@ -119,12 +134,12 @@ function findMissingI18nKeys() {
|
|||
let match
|
||||
while ((match = pattern.exec(content)) !== null) {
|
||||
const key = match[1]
|
||||
const missingLocales = checkKeyInLocales(key, localeDirs)
|
||||
const missingLocales = checkKeyInLocales(key, localeDirs, localesDir)
|
||||
if (missingLocales.length > 0) {
|
||||
results.push({
|
||||
key,
|
||||
missingLocales,
|
||||
file: path.relative(TARGET_DIR, filePath),
|
||||
file: path.relative(baseDir, filePath),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -133,20 +148,33 @@ function findMissingI18nKeys() {
|
|||
}
|
||||
}
|
||||
|
||||
walk(TARGET_DIR)
|
||||
// Walk through all directories
|
||||
Object.entries(DIRS).forEach(([name, config]) => {
|
||||
const localeDirs = getLocaleDirs(config.localesDir)
|
||||
if (localeDirs.length > 0) {
|
||||
console.log(`\nChecking ${name} directory with ${localeDirs.length} languages: ${localeDirs.join(", ")}`)
|
||||
walk(config.path, config.path, localeDirs, config.localesDir)
|
||||
}
|
||||
})
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
// Execute and output the results
|
||||
function main() {
|
||||
try {
|
||||
const localeDirs = getLocaleDirs()
|
||||
if (args.locale && localeDirs.length === 0) {
|
||||
console.error(`Error: Language '${args.locale}' not found in ${LOCALES_DIR}`)
|
||||
process.exit(1)
|
||||
}
|
||||
if (args.locale) {
|
||||
// Check if the specified locale exists in any of the locales directories
|
||||
const localeExists = Object.values(DIRS).some((config) => {
|
||||
const localeDirs = getLocaleDirs(config.localesDir)
|
||||
return localeDirs.includes(args.locale)
|
||||
})
|
||||
|
||||
console.log(`Checking ${localeDirs.length} non-English languages: ${localeDirs.join(", ")}`)
|
||||
if (!localeExists) {
|
||||
console.error(`Error: Language '${args.locale}' not found in any locales directory`)
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
const missingKeys = findMissingI18nKeys()
|
||||
|
||||
|
|
|
|||
|
|
@ -1250,7 +1250,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
|
|||
}
|
||||
case "openProjectMcpSettings": {
|
||||
if (!vscode.workspace.workspaceFolders?.length) {
|
||||
vscode.window.showErrorMessage(t("common:no_workspace"))
|
||||
vscode.window.showErrorMessage(t("common:errors.no_workspace"))
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2031,7 +2031,7 @@ describe("Project MCP Settings", () => {
|
|||
await messageHandler({ type: "openProjectMcpSettings" })
|
||||
|
||||
// Verify error message was shown
|
||||
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("no_workspace")
|
||||
expect(vscode.window.showErrorMessage).toHaveBeenCalledWith("errors.no_workspace")
|
||||
})
|
||||
|
||||
test.skip("handles openProjectMcpSettings file creation error", async () => {
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Exportar historial de tasques",
|
||||
"delete": "Eliminar tasca (Shift + Clic per ometre confirmació)"
|
||||
},
|
||||
"unpin": "desancorar",
|
||||
"pin": "ancorar",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Espai disponible: {{amount}} tokens",
|
||||
"tokensUsed": "Tokens utilitzats: {{used}} de {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Aufgabenverlauf exportieren",
|
||||
"delete": "Aufgabe löschen (Shift + Klick zum Überspringen der Bestätigung)"
|
||||
},
|
||||
"unpin": "lösen",
|
||||
"pin": "anheften",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Verfügbarer Speicher: {{amount}} Tokens",
|
||||
"tokensUsed": "Verwendete Tokens: {{used}} von {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Export task history",
|
||||
"delete": "Delete Task (Shift + Click to skip confirmation)"
|
||||
},
|
||||
"unpin": "unpin",
|
||||
"pin": "pin",
|
||||
"retry": {
|
||||
"title": "Retry",
|
||||
"tooltip": "Try the operation again"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Exportar historial de tareas",
|
||||
"delete": "Eliminar tarea (Shift + Clic para omitir confirmación)"
|
||||
},
|
||||
"unpin": "desanclar",
|
||||
"pin": "anclar",
|
||||
"retry": {
|
||||
"title": "Reintentar",
|
||||
"tooltip": "Intenta la operación de nuevo"
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Exporter l'historique des tâches",
|
||||
"delete": "Supprimer la tâche (Shift + Clic pour ignorer la confirmation)"
|
||||
},
|
||||
"unpin": "détacher",
|
||||
"pin": "épingler",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Espace disponible : {{amount}} tokens",
|
||||
"tokensUsed": "Tokens utilisés : {{used}} sur {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "कार्य इतिहास निर्यात करें",
|
||||
"delete": "कार्य हटाएं (पुष्टि को छोड़ने के लिए Shift + क्लिक)"
|
||||
},
|
||||
"unpin": "पिन हटाएं",
|
||||
"pin": "पिन करें",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "उपलब्ध स्थान: {{amount}} tokens",
|
||||
"tokensUsed": "प्रयुक्त tokens: {{used}} / {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Esporta cronologia attività",
|
||||
"delete": "Elimina attività (Shift + Clic per saltare la conferma)"
|
||||
},
|
||||
"unpin": "sblocca",
|
||||
"pin": "blocca",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Spazio disponibile: {{amount}} tokens",
|
||||
"tokensUsed": "Tokens utilizzati: {{used}} di {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "タスク履歴をエクスポート",
|
||||
"delete": "タスクを削除(Shift + クリックで確認をスキップ)"
|
||||
},
|
||||
"unpin": "固定解除",
|
||||
"pin": "固定",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "利用可能な空き容量: {{amount}} トークン",
|
||||
"tokensUsed": "使用トークン: {{used}} / {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "작업 기록 내보내기",
|
||||
"delete": "작업 삭제 (Shift + 클릭으로 확인 생략)"
|
||||
},
|
||||
"unpin": "고정 해제",
|
||||
"pin": "고정",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "사용 가능한 공간: {{amount}} 토큰",
|
||||
"tokensUsed": "사용된 토큰: {{used}} / {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Eksportuj historię zadań",
|
||||
"delete": "Usuń zadanie (Shift + Kliknięcie, aby pominąć potwierdzenie)"
|
||||
},
|
||||
"unpin": "odepnij",
|
||||
"pin": "przypnij",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Dostępne miejsce: {{amount}} tokenów",
|
||||
"tokensUsed": "Wykorzystane tokeny: {{used}} z {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Exportar histórico de tarefas",
|
||||
"delete": "Excluir tarefa (Shift + Clique para pular confirmação)"
|
||||
},
|
||||
"unpin": "desafixar",
|
||||
"pin": "fixar",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Espaço disponível: {{amount}} tokens",
|
||||
"tokensUsed": "Tokens usados: {{used}} de {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Görev geçmişini dışa aktar",
|
||||
"delete": "Görevi sil (Onayı atlamak için Shift + Tıkla)"
|
||||
},
|
||||
"unpin": "sabitlemeyi kaldır",
|
||||
"pin": "sabitle",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Kullanılabilir alan: {{amount}} token",
|
||||
"tokensUsed": "Kullanılan tokenlar: {{used}} / {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "Xuất lịch sử nhiệm vụ",
|
||||
"delete": "Xóa nhiệm vụ (Shift + Click để bỏ qua xác nhận)"
|
||||
},
|
||||
"unpin": "bỏ ghim",
|
||||
"pin": "ghim",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "Không gian khả dụng: {{amount}} tokens",
|
||||
"tokensUsed": "Tokens đã sử dụng: {{used}} trong {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "导出任务历史",
|
||||
"delete": "删除任务(Shift + 点击跳过确认)"
|
||||
},
|
||||
"unpin": "取消置顶",
|
||||
"pin": "置顶",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "可用空间: {{amount}} tokens",
|
||||
"tokensUsed": "已使用tokens: {{used}} / {{total}}",
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
"export": "匯出任務歷史",
|
||||
"delete": "刪除任務(Shift + 點擊跳過確認)"
|
||||
},
|
||||
"unpin": "取消置頂",
|
||||
"pin": "置頂",
|
||||
"tokenProgress": {
|
||||
"availableSpace": "可用空間: {{amount}} tokens",
|
||||
"tokensUsed": "已使用tokens: {{used}} / {{total}}",
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue