diff --git a/.changeset/few-foxes-lick.md b/.changeset/few-foxes-lick.md new file mode 100644 index 000000000..ed06bb750 --- /dev/null +++ b/.changeset/few-foxes-lick.md @@ -0,0 +1,6 @@ +--- +"lingo.dev": minor +--- + +treat keys w/ empty nodes as values in `Localizable.xcstrings` +skip keys w/ `shouldTranslate: false` in `Localizable.xcstrings` diff --git a/.husky/commit-msg b/.husky/commit-msg index 0a4b97de5..cfe751017 100644 --- a/.husky/commit-msg +++ b/.husky/commit-msg @@ -1 +1 @@ -npx --no -- commitlint --edit $1 +pnpm commitlint --edit $1 diff --git a/package.json b/package.json index ddfb139c4..9de2822d6 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "devDependencies": { "@commitlint/cli": "^19.6.1", "@commitlint/config-conventional": "^19.6.0", + "commitlint": "^19.7.1", "husky": "^9.1.7", "turbo": "^2.3.3" }, diff --git a/packages/cli/demo/xcode-xcstrings/Localizable.xcstrings b/packages/cli/demo/xcode-xcstrings/Localizable.xcstrings index 81384b83a..64d81cebe 100644 --- a/packages/cli/demo/xcode-xcstrings/Localizable.xcstrings +++ b/packages/cli/demo/xcode-xcstrings/Localizable.xcstrings @@ -2,80 +2,4453 @@ "sourceLanguage" : "en", "strings" : { "" : { - - }, - " " : { - + "shouldTranslate" : false }, " and " : { "extractionState" : "manual", "localizations" : { - "ar" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : " y " + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : " 和 " + } + } + } + }, + "- " : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "- " + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "-" + } + } + } + }, + "." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "。" + } + } + } + }, + "·" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "·" + } + } + } + }, + "/mo" : { + "extractionState" : "manual", + "localizations" : { + "es" : { "stringUnit" : { "state" : "translated", - "value" : " و " + "value" : "/mes" } }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "/月" + } + } + } + }, + "#%@ - %@" : { + "extractionState" : "manual", + "localizations" : { "en" : { + "stringUnit" : { + "state" : "new", + "value" : "#%1$@ - %2$@" + } + }, + "es" : { "stringUnit" : { "state" : "translated", - "value" : " and " + "value" : "#%1$@ - %2$@" + } + } + } + }, + "#%lld - %@" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "#%1$lld - %2$@" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : " y " + "value" : "#%1$lld - %2$@" } } } }, - "25" : { + "%@" : { "extractionState" : "manual", "localizations" : { - "ar" : { + "es" : { "stringUnit" : { "state" : "translated", - "value" : "25" + "value" : "%@" } }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@" + } + } + } + }, + "%@ not connected" : { + + }, + "%@%@" : { + "extractionState" : "manual", + "localizations" : { "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@%2$@" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@%2$@" + } + } + } + }, + "%lf" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lf" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lf" + } + } + } + }, + "%lld" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld" + } + }, + "zh-Hans" : { "stringUnit" : { "state" : "translated", - "value" : "25" + "value" : "%lld" + } + } + } + }, + "%lld / %lld" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$lld / %2$lld" } }, "es" : { "stringUnit" : { "state" : "translated", - "value" : "25" + "value" : "%1$lld / %2$lld" } } } }, - "apple" : { + "%lld files" : { "extractionState" : "manual", "localizations" : { - "ar" : { + "es" : { "stringUnit" : { "state" : "translated", - "value" : "تفاحة" + "value" : "%lld archivos" } }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld 个文件" + } + } + } + }, + "%lld Labels" : { + + }, + "%lld/%lld files" : { + "extractionState" : "manual", + "localizations" : { "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$lld/%2$lld files" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld/%2$lld archivos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld/%2$lld 个文件" + } + } + } + }, + "%lld%%" : { + + }, + "+ " : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ " + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ " + } + } + } + }, + "+ Everything from Pro" : { + + }, + "+ Make \"%@.swift\"" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ Crear \"%@.swift\"" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ 创建 “%@.swift”" + } + } + } + }, + "+ top-up for $9 / 250 messages" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ recarga por $9 / 250 mensajes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "+ 充值 $9 / 250 条消息" + } + } + } + }, + "+ top-up for $9 / 250 Sonnet messages" : { + + }, + "⌘⌫ stop" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "⌘⌫ detener" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "⌘⌫ 停止" + } + } + } + }, + "⌘⏎" : { + + }, + "⌘⏎ codebase" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "⌘⏎ base de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "⌘⏎ 代码库" + } + } + } + }, + "⏎ chat" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "⏎ chat" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "⏎ 对话" + } + } + } + }, + "$0/mo" : { + "extractionState" : "manual", + "localizations" : { + "es" : { "stringUnit" : { "state" : "translated", - "value" : "apple" + "value" : "$0/mes" } }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "$0/月" + } + } + } + }, + "5 Code Applies" : { + "extractionState" : "manual", + "localizations" : { "es" : { "stringUnit" : { "state" : "translated", - "value" : "manzana" + "value" : "5 aplicaciones de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 次代码应用" + } + } + } + }, + "5 Git Commit Generations" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 generaciones de commits de Git" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 次 Git 提交信息生成" + } + } + } + }, + "5 Voice Inputs" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 entradas de voz" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 次语音输入" + } + } + } + }, + "50 Chat Messages" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "50 mensajes de chat" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "50 条对话消息" + } + } + } + }, + "50 Tab-to-Completes" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "50 autocompletados con tabulación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "50 次 Tab 自动补全" + } + } + } + }, + "500 Sonnet Messages / month" : { + + }, + "750 Chat Messages / month" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "750 mensajes de chat / mes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "750 条对话消息/月" + } + } + } + }, + "1000 Fast Sonnet Messages / month" : { + + }, + "Accept and Commit" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aceptar y confirmar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "接受并提交" + } + } + } + }, + "Account" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cuenta" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "账户" + } + } + } + }, + "Account View" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vista de cuenta" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "账户视图" + } + } + } + }, + "Add" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加" + } + } + } + }, + "Add File" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir archivo" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加文件" + } + } + } + }, + "Add File Errors" : { + + }, + "Add File to Xcode" : { + + }, + "Add File Warnings" : { + + }, + "Add files and docs (use @ for shortcut)" : { + + }, + "Add files errors to the chat" : { + + }, + "Add New Model" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir nuevo modelo" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加新模型" + } + } + } + }, + "Add New Prompt" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir nuevo prompt" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "添加新提示" + } + } + } + }, + "Add Selected" : { + + }, + "Add selected lines to context" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir líneas seleccionadas al contexto" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将所选行添加到上下文" + } + } + } + }, + "Add suggested file" : { + + }, + "Add web page from browser (Cmd+L)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Añadir página web desde el navegador (Cmd+L)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "从浏览器添加网页 (Cmd+L)" + } + } + } + }, + "Admin" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Administrador" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "管理员" + } + } + } + }, + "Admin Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes de administrador" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "管理员设置" + } + } + } + }, + "Advanced Search Panel" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Panel de búsqueda avanzada" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "高级搜索面板" + } + } + } + }, + "Agent (Sonnet)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Agente (Sonnet)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "智能体(Sonnet)" + } + } + } + }, + "Agent Mode" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo agente" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "智能体模式" + } + } + } + }, + "Agent Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes del agente" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "智能体" + } + } + } + }, + "Alex" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alex" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alex" + } + } + } + }, + "All" : { + + }, + "Alpha" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alfa" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alpha" + } + } + } + }, + "Already have an account?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Ya tienes una cuenta?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已经有账户?" + } + } + } + }, + "And %lld more…" : { + + }, + "Anthropic Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave de Anthropic" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anthropic 密钥" + } + } + } + }, + "API Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave API" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "API 密钥" + } + } + } + }, + "Apple Docs" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Documentación de Apple" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "苹果文档" + } + } + } + }, + "Apple Docs (Individual)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Documentación de Apple (Individual)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "苹果文档(单个)" + } + } + } + }, + "Apply" : { + + }, + "Apply Changes (without seeing the preview)" : { + + }, + "Apply Code Suggestions" : { + + }, + "Apply Panel" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Panel de aplicación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "应用面板" + } + } + } + }, + "Are you sure you want to delete this chat?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Estás seguro de que quieres eliminar este chat?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确定要删除此对话吗?" + } + } + } + }, + "Are you sure you want to delete this memory? This action cannot be undone." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Estás seguro de que quieres eliminar esta memoria? Esta acción no se puede deshacer." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确定要删除此上下文吗?此操作无法撤销。" + } + } + } + }, + "Are you sure you want to disconnect?" : { + + }, + "Are you sure you want to log out?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Estás seguro de que quieres cerrar sesión?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确定要退出登录吗?" + } + } + } + }, + "Assigned to: %@" : { + + }, + "Assignee" : { + + }, + "Assignees: %@" : { + + }, + "Attach image" : { + + }, + "Auto context" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Contexto automático" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自动关联上下文" + } + } + } + }, + "Auto-activate sidebar on hover" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activar automáticamente la barra lateral al pasar el cursor" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "鼠标悬停时自动激活侧栏" + } + } + } + }, + "Auto-activate sidebar when Xcode is activated" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activar automáticamente la barra lateral cuando se active Xcode" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "跟随 Xcode 显示侧栏" + } + } + } + }, + "Auto-position window next to Xcode" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Posicionar automáticamente la ventana junto a Xcode" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "窗口自动对齐 Xcode" + } + } + } + }, + "Auto-send voice transcriptions" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enviar automáticamente transcripciones de voz" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自动发送语音转录" + } + } + } + }, + "Autocomplete Settings" : { + + }, + "Autocomplete Text Opacity" : { + + }, + "Autofix Issues" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Corregir problemas automáticamente" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自动修复问题" + } + } + } + }, + "Base URL" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "URL base" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "基础 URL" + } + } + } + }, + "Billing & Usage" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Facturación y uso" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "账单与使用情况" + } + } + } + }, + "Billing History" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Historial de facturación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "账单历史" + } + } + } + }, + "Branch: %@" : { + + }, + "Buy More" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comprar más" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "购买更多" + } + } + } + }, + "By signing in, Alex will be happy again." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Al iniciar sesión, Alex volverá a estar feliz." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "登录后,Alex 将再次正常工作。" + } + } + } + }, + "By signing up, you agree to our " : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Al registrarte, aceptas nuestros " + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "注册即表示您同意我们的" + } + } + } + }, + "Can send images" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puede enviar imágenes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "可以发送图片" + } + } + } + }, + "Can't send images in thinking mode" : { + + }, + "Cancel" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancelar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "取消" + } + } + } + }, + "Category" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Categoría" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "类别" + } + } + } + }, + "Change model" : { + + }, + "Changes committed successfully!" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Cambios confirmados con éxito!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "更改提交成功!" + } + } + } + }, + "Chat History" : { + + }, + "Chat Models" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelos de chat" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "对话模型" + } + } + } + }, + "Chat Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes de chat" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "对话设置" + } + } + } + }, + "Check for Updates" : { + + }, + "Check for Updates…" : { + + }, + "Check Plan Options" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ver opciones de plan" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "查看方案选项" + } + } + } + }, + "Clear" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Limpiar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "清除" + } + } + } + }, + "Closed" : { + + }, + "Code Applies" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aplicaciones de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "代码应用" + } + } + } + }, + "Code Apply failed: %@" : { + + }, + "Code Apply is running..." : { + + }, + "Codebase" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Base de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "代码库" + } + } + } + }, + "Color Scheme" : { + + }, + "Commit" : { + + }, + "Commit & Push" : { + + }, + "Confirm override path" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Confirmar ruta de anulación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确认覆盖路径" + } + } + } + }, + "Connect" : { + + }, + "Copy" : { + + }, + "Copy Code" : { + + }, + "Copy Message" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Copiar mensaje" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "复制消息" + } + } + } + }, + "Create Issue" : { + + }, + "Create new chat with selected lines" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Crear nuevo chat con las líneas seleccionadas" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用所选行创建新对话" + } + } + } + }, + "Create New Issue" : { + + }, + "Current Directory:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Directorio actual:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "当前目录:" + } + } + } + }, + "Custom Models" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelos personalizados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自定义模型" + } + } + } + }, + "Custom Prompts" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompts personalizados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自定义提示" + } + } + } + }, + "Debug Support" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Soporte de depuración" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "调试支持" + } + } + } + }, + "Default Status" : { + + }, + "Delete" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除" + } + } + } + }, + "Delete Chat" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar chat" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除对话" + } + } + } + }, + "Delete Index" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar índice" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除索引" + } + } + } + }, + "Delete Memory" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar memoria" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "删除上下文" + } + } + } + }, + "Description" : { + + }, + "Diff" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diferencias" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Diff 差异" + } + } + } + }, + "Disconnect" : { + + }, + "Discord Support" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Soporte en Discord" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Discord 支持" + } + } + } + }, + "Dismiss" : { + + }, + "Display Name" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nombre para mostrar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示名称" + } + } + } + }, + "Docs" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Documentación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文档" + } + } + } + }, + "Don't have an account?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿No tienes una cuenta?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "还没有账户?" + } + } + } + }, + "Edit Issue" : { + + }, + "Edit Issue #%lld" : { + + }, + "Email" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Correo electrónico" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "电子邮件" + } + } + } + }, + "Email Us" : { + + }, + "Enable Autocomplete" : { + + }, + "Enable Memory" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activar memoria" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用上下文" + } + } + } + }, + "Enable Voice Mode (Shift + Cmd + V)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Activar modo de voz (Mayús + Cmd + V)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用语音模式(Shift + Cmd + V)" + } + } + } + }, + "Ending %@" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Finalizando %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "结束于 %@" + } + } + } + }, + "Enter debug token" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introducir token de depuración" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入调试令牌" + } + } + } + }, + "Enter ID" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introducir ID" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入 ID" + } + } + } + }, + "Enter Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introducir clave" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入密钥" + } + } + } + }, + "Enter override path" : { + + }, + "Enter prompt here" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introduce el prompt aquí" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在此输入提示" + } + } + } + }, + "Enter the name and value for the new prompt" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introduce el nombre y valor para el nuevo prompt" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入新提示的名称和值" + } + } + } + }, + "Enter URL" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introducir URL" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入 URL" + } + } + } + }, + "Enter your query" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Introduce tu consulta" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "输入您的查询" + } + } + } + }, + "Error Applying Code" : { + + }, + "Expand %lld more lines" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Expandir %lld líneas más" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "展开 %lld 行更多内容" + } + } + } + }, + "Failed to load issues" : { + + }, + "Feature Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes de funciones" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "功能设置" + } + } + } + }, + "Features and Keybindings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Funciones y atajos de teclado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "功能和快捷键" + } + } + } + }, + "Files" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Archivos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "文件" + } + } + } + }, + "Fill to expand available width" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Rellenar para expandir el ancho disponible" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "自适应宽度" + } + } + } + }, + "Find relevant code from your codebase" : { + + }, + "Fix Swift 6 Issues" : { + + }, + "Fix Swift 6 issues automatically" : { + + }, + "FloatingPanel" : { + + }, + "Forgot Password?" : { + + }, + "Free Beta" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beta gratuita" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "公测版" + } + } + } + }, + "Free Plan" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plan gratuito" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "免费方案" + } + } + } + }, + "Gemini Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave de Gemini" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gemini 密钥" + } + } + } + }, + "Generate Commit Message" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generar mensaje de commit" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "生成提交信息" + } + } + } + }, + "Generate Git Message" : { + + }, + "Get Receipt" : { + + }, + "Git Commit Generation" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Generación de commit de Git" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git 提交信息生成" + } + } + } + }, + "Git Commits" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Commits de Git" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git 提交" + } + } + } + }, + "Git Status" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estado de Git" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Git 状态" + } + } + } + }, + "GitHub Issues" : { + + }, + "Github Issues Integration" : { + + }, + "Go to Integrations" : { + + }, + "Go to Settings" : { + + }, + "Hello, World!" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¡Hola, mundo!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "你好,世界!" + } + } + } + }, + "How is my data used?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Cómo se usa mi información?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "我的数据是如何被使用的?" + } + } + } + }, + "I've applied the code" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "He aplicado el código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "我已应用了这段代码" + } + } + } + }, + "If we request a remote debugging session with you through Discord, please enter the token here and click on \"Start Debug Session\"." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Si solicitamos una sesión de depuración remota contigo a través de Discord, por favor introduce el token aquí y haz clic en \"Iniciar sesión de depuración\"." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "如果我们通过 Discord 请求与您进行远程调试,请在此输入令牌并点击“Start Debug Session”。" + } + } + } + }, + "Important: Please update to version %@. %@" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Important: Please update to version %1$@. %2$@" + } + }, + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importante: Por favor, actualiza a la versión %1$@. %2$@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重要:请更新到版本 %1$@。%2$@" + } + } + } + }, + "In agent mode, Claude 3.5 Sonnet is used by default because it is the best model for code generation. If you'd like to switch to a different model, disable agent mode.\n\n(You can always turn it back on in the Agent Settings dropdown.)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "En modo agente, Claude 3.5 Sonnet se usa por defecto porque es el mejor modelo para generación de código. Si quieres cambiar a un modelo diferente, desactiva el modo agente.\n\n(Siempre puedes volver a activarlo en el menú desplegable de Ajustes del Agente.)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在智能体模式下,默认使用 Claude 3.5 Sonnet,因为它是最适合代码生成的模型。如果您想切换到其他模型,请禁用智能体模式。\n\n(您随时可以在智能体设置下拉菜单中重新启用它。)" + } + } + } + }, + "Indexed" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Indexado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已索引" + } + } + } + }, + "Indexed Files" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Archivos indexados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已索引文件" + } + } + } + }, + "Inline completion" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autocompletado en línea" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "行内代码补全" + } + } + } + }, + "Integration" : { + + }, + "Integrations" : { + + }, + "Issue title" : { + + }, + "Join Discord" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Unirse a Discord" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加入 Discord" + } + } + } + }, + "Labels: %@" : { + + }, + "Learn more about Agent best practices here:\n\n[https://docs.alexcodes.app/chat/context/agents](https://docs.alexcodes.app/chat/context/agents)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aprende más sobre las mejores prácticas del Agente aquí:\n\n[https://docs.alexcodes.app/chat/context/agents](https://docs.alexcodes.app/chat/context/agents)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在此了解更多关于智能体最佳实践:\n\n[https://docs.alexcodes.app/chat/context/agents](https://docs.alexcodes.app/chat/context/agents)" + } + } + } + }, + "Line %lld" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Línea %lld" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "第 %lld 行" + } + } + } + }, + "Linear" : { + + }, + "Linear Integration" : { + + }, + "listening (press ⏎ to send)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "escuchando (presiona ⏎ para enviar)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在聆听(按 ⏎ 发送)" + } + } + } + }, + "listening (press ⏎ to stop)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "escuchando (presiona ⏎ para detener)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在聆听(按 ⏎ 停止)" + } + } + } + }, + "Load Index" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cargar índice" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "加载索引" + } + } + } + }, + "Loading assignees..." : { + + }, + "Loading billing information..." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cargando información de facturación..." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在加载账单信息..." + } + } + } + }, + "Loading Documentation..." : { + + }, + "Loading issues..." : { + + }, + "Loading repositories..." : { + + }, + "Loading..." : { + + }, + "Log Out" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cerrar sesión" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "退出登录" + } + } + } + }, + "Logout" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cerrar sesión" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "退出登录" + } + } + } + }, + "Made in SwiftUI" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hecho en SwiftUI" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用 SwiftUI 构建" + } + } + } + }, + "Manage Subscription" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gestionar suscripción" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "管理订阅" + } + } + } + }, + "Manage Trial Subscription" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gestionar suscripción de prueba" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "管理试用订阅" + } + } + } + }, + "Managed Billing Option (Team Plan)" : { + + }, + "Match height with Xcode" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Igualar altura con Xcode" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "与 Xcode 高度匹配" + } + } + } + }, + "Memory" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Memoria" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上下文" + } + } + } + }, + "Memory Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes de memoria" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "上下文设置" + } + } + } + }, + "Message Top Ups" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recargas de mensajes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "消息充值" + } + } + } + }, + "Model ID" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "ID del modelo" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模型 ID" + } + } + } + }, + "Model Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes del modelo" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模型设置" + } + } + } + }, + "Models" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modelos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "模型" + } + } + } + }, + "Monthly Messages" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mensajes mensuales" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "每月消息数" + } + } + } + }, + "Name" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nombre" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "名称" + } + } + } + }, + "New Chat" : { + + }, + "New GitHub Issue" : { + + }, + "New Issue" : { + + }, + "No" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "否" + } + } + } + }, + "No Assignees" : { + + }, + "No billing history available" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No hay historial de facturación disponible" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无可用账单历史" + } + } + } + }, + "No context selected" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ningún contexto seleccionado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未选择任何上下文" + } + } + } + }, + "No issues found" : { + + }, + "No Labels" : { + + }, + "No matching issues" : { + + }, + "No memories found" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No se encontraron memorias" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未找到上下文" + } + } + } + }, + "No Project" : { + + }, + "No Project Focused" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ningún proyecto enfocado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有专注的项目" + } + } + } + }, + "No Repository Selected" : { + + }, + "No results found" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No se encontraron resultados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未找到结果" + } + } + } + }, + "No Team Selected" : { + + }, + "No userdata found" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No se encontraron datos de usuario" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未找到用户数据" + } + } + } + }, + "Not Indexed" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No indexado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未索引" + } + } + } + }, + "Not logged in" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No ha iniciado sesión" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未登录" + } + } + } + }, + "Note: This URL must be publicly available (not a localhost URL)." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nota: Esta URL debe estar disponible públicamente (no una URL de localhost)." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "注意:此 URL 必须可公开访问(不能是 localhost)。" + } + } + } + }, + "Notice an Issue?" : { + + }, + "o1 Credits" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Créditos o1" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "o1 额度" + } + } + } + }, + "O1-Preview Credits" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Créditos O1-Preview" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "O1-Preview 额度" + } + } + } + }, + "Only for this project, and will be used in combination with your custom system prompt." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Solo para este proyecto, y se usará en combinación con su prompt de sistema personalizado." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "仅适用于此项目,并将与您的自定义系统提示组合使用。" + } + } + } + }, + "Open" : { + + }, + "Open file in Xcode" : { + + }, + "Open in GitHub" : { + + }, + "Open in Linear" : { + + }, + "Open Permission Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Abrir ajustes de permisos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "打开权限设置" + } + } + } + }, + "OpenAI Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave de OpenAI" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "OpenAI 密钥" + } + } + } + }, + "Override Path:" : { + + }, + "Perplexity Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave de Perplexity" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Perplexity 密钥" + } + } + } + }, + "Pin chat input to bottom" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fijar entrada de chat en la parte inferior" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "将对话输入固定在底部" + } + } + } + }, + "Plan" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Plan" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "方案" + } + } + } + }, + "Please grant accessibility permissions so Alex can work with Xcode." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Por favor, conceda permisos de accesibilidad para que Alex pueda trabajar con Xcode." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "请授予辅助功能权限,以便 Alex 可以与 Xcode 协同工作。" + } + } + } + }, + "Please select a repository in GitHub settings first" : { + + }, + "Please select a team in Linear settings first" : { + + }, + "Popular" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Popular" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "热门" + } + } + } + }, + "Premium" : { + + }, + "Preview:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Vista previa:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "预览:" + } + } + } + }, + "Privacy" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Privacidad" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "隐私" + } + } + } + }, + "Privacy Policy" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Política de privacidad" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "隐私政策" + } + } + } + }, + "Project-Specific Prompt" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt específico del proyecto" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "项目特定提示" + } + } + } + }, + "Prompt Name" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nombre del prompt" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "提示名称" + } + } + } + }, + "Purchase Subscription" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Comprar suscripción" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "购买订阅" + } + } + } + }, + "Quick Actions:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Acciones rápidas:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "快捷操作:" + } + } + } + }, + "record" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "grabar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "录制" + } + } + } + }, + "Refresh" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualizar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "刷新" + } + } + } + }, + "Refresh Issues" : { + + }, + "Related Files:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Archivos relacionados:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "相关文件:" + } + } + } + }, + "Reload Index" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recargar índice" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新加载索引" + } + } + } + }, + "Remote Debugging Session" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sesión de depuración remota" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "远程调试会话" + } + } + } + }, + "Remove" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eliminar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "移除" + } + } + } + }, + "Repository is clean" : { + + }, + "Rerank" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reordenar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "重新排序" + } + } + } + }, + "Retry" : { + + }, + "Save Issue" : { + + }, + "Search Apple Documentation..." : { + + }, + "Search chats..." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Buscar chats..." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索对话..." + } + } + } + }, + "Search files" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Buscar archivos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索文件" + } + } + } + }, + "Search issues..." : { + + }, + "Search memories..." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Buscar recuerdos..." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "搜索上下文..." + } + } + } + }, + "Search the web for answers" : { + + }, + "Select a member" : { + + }, + "Select a project" : { + + }, + "Select a repository" : { + + }, + "Select All" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Seleccionar todo" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "全选" + } + } + } + }, + "Select an assignee" : { + + }, + "Select Assignee" : { + + }, + "Select Member" : { + + }, + "Select Project" : { + + }, + "Select Repository" : { + + }, + "Select Team" : { + + }, + "Semantic" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Semántico" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语义搜索" + } + } + } + }, + "Send message" : { + + }, + "Send voice message" : { + + }, + "Set override path" : { + + }, + "Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设置" + } + } + } + }, + "Show code apply view at bottom" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostrar vista de aplicación de código en la parte inferior" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在底部显示代码应用视图" + } + } + } + }, + "Show Hints" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostrar pistas" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示提示" + } + } + } + }, + "Show less" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostrar menos" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示更少" + } + } + } + }, + "Show less…" : { + + }, + "Show suggestion details" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mostrar detalles de sugerencia" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "显示建议详情" + } + } + } + }, + "Shrink code view sections" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reducir secciones de vista de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "收缩代码视图部分" + } + } + } + }, + "Sign in" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar sesión" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "登录" + } + } + } + }, + "Sign In" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar sesión" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "登录" + } + } + } + }, + "Sign in with Google" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar sesión con Google" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用 Google 登录" + } + } + } + }, + "Sign up" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Registrarse" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "注册" + } + } + } + }, + "Sign Up" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Registrarse" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "注册" + } + } + } + }, + "Sign up with Google" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Registrarse con Google" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用 Google 注册" + } + } + } + }, + "Staged Changes" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cambios preparados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已暂存更改" + } + } + } + }, + "Standard" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estándar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "标准" + } + } + } + }, + "Start Debug Session" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar sesión de depuración" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "开始调试会话" + } + } + } + }, + "Start Free Trial (7 days)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar prueba gratuita (7 días)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "开始免费试用(7天)" + } + } + } + }, + "Start Subscription" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar suscripción" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "开始订阅" + } + } + } + }, + "Start without context" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Iniciar sin contexto" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "直接开始" + } + } + } + }, + "Stop Debug Session" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Detener sesión de depuración" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "停止调试会话" + } + } + } + }, + "Submit" : { + + }, + "Suggestion Details" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Detalles de sugerencia" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "建议详情" + } + } + } + }, + "Suggestions" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sugerencias" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "建议" + } + } + } + }, + "Support" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Soporte" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "支持" + } + } + } + }, + "System Prompt" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Prompt del sistema" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "系统提示" + } + } + } + }, + "Tab-to-Complete suggestions (beta)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sugerencias de autocompletado con tabulación (beta)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tab 自动补全建议(测试版)" + } + } + } + }, + "Terms of Service" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Términos de servicio" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "服务条款" + } + } + } + }, + "Terms of Sevice" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Términos de servicio" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "服务条款" + } + } + } + }, + "Theme Settings" : { + + }, + "There are no changes to commit." : { + + }, + "These go as additional info with the default system prompt" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Estos van como información adicional con el prompt del sistema predeterminado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "这些将作为默认系统提示的附加信息" + } + } + } + }, + "Think before answering" : { + + }, + "This model doesn't support images" : { + + }, + "Top-K: %lld" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Top-K: %lld" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Top-K:%lld" + } + } + } + }, + "transcribing..." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "transcribiendo..." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "正在转录..." + } + } + } + }, + "Try adjusting your search criteria" : { + + }, + "Type something here (or ⌘+shift+v for voice)" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Escribe algo aquí (o ⌘+shift+v para voz)" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "在此输入内容(或按 ⌘+Shift+V 进行语音输入)" + } + } + } + }, + "Unlimited Code Applies" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aplicaciones de código ilimitadas" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无限代码应用" + } + } + } + }, + "Unlimited DeepSeek R1 Messages" : { + + }, + "Unlimited Slow Sonnet Messages" : { + + }, + "Unlimited Tab-to-Complete" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Autocompletado con tabulación ilimitado" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无限 Tab 自动补全" + } + } + } + }, + "Unstaged Changes" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cambios no preparados" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未暂存更改" + } + } + } + }, + "Update" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualizar" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "更新" + } + } + } + }, + "Update available" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualización disponible" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "有可用更新" + } + } + } + }, + "Update Issue" : { + + }, + "Update to %@" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actualizar a %@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "更新至 %@" + } + } + } + }, + "Upgrade To Premium" : { + + }, + "Usage" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Uso" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用情况" + } + } + } + }, + "Use Agent" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usar agente" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "智能体" + } + } + } + }, + "Use Agent Mode" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usar modo agente" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用智能体模式" + } + } + } + }, + "User Activities" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Actividades del usuario" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "用户活动" + } + } + } + }, + "Using Codebase Search" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usando búsqueda en la base de código" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用代码库搜索" + } + } + } + }, + "Using Docs" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usando documentación" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "使用文档" + } + } + } + }, + "Voice Inputs" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entradas de voz" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语音输入" + } + } + } + }, + "Voice Mode" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Modo de voz" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "语音模式" + } + } + } + }, + "Voice Settings" : { + + }, + "VoyageAI Key" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Clave de VoyageAI" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "VoyageAI 密钥" + } + } + } + }, + "Waiting for model%@" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Esperando el modelo%@" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "等待模型 %@" + } + } + } + }, + "Want to buy O1 credits? Join the Discord and message @DanielEdrisian" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Quieres comprar créditos O1? Únete al Discord y envía un mensaje a @DanielEdrisian" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "想要购买 O1 额度吗?加入 Discord 并联系 @DanielEdrisian" + } + } + } + }, + "We conduct all of our support through Discord. We also send new feature announcements there!" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Realizamos todo nuestro soporte a través de Discord. ¡También enviamos anuncios de nuevas funciones allí!" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "我们的所有支持都在 Discord 上进行。新功能公告也会在那里发布!" + } + } + } + }, + "We couldn't find an exact match for this snippet. Please select the file to apply to:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "No pudimos encontrar una coincidencia exacta para este fragmento. Por favor, selecciona el archivo al que aplicarlo:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "我们无法为此代码片段找到确切匹配。请选择要应用的文件:" + } + } + } + }, + "We recently migrated our billing, so if you notice a subscription missing, please contact us via email. We'll get back to you shortly." : { + + }, + "What's new:" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Novedades:" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "更新内容:" + } + } + } + }, + "When enabled, Alex will maintain context from your previous messages to provide more relevant responses." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cuando está activado, Alex mantendrá el contexto de tus mensajes anteriores para proporcionar respuestas más relevantes." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "启用后,Alex 将保留先前消息的上下文,以提供更相关的回答。" + } + } + } + }, + "Why?" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "¿Por qué?" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "为什么?" + } + } + } + }, + "Window Management" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gestión de ventanas" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "窗口管理" + } + } + } + }, + "Window Settings" : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ajustes de ventana" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "窗口设置" + } + } + } + }, + "You can add custom models that comply with the OpenAI API scheme. Just add the base url, model name, and api key." : { + "extractionState" : "manual", + "localizations" : { + "es" : { + "stringUnit" : { + "state" : "translated", + "value" : "Puedes añadir modelos personalizados que cumplan con el esquema de la API de OpenAI. Solo añade la url base, el nombre del modelo y la clave api." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "您可以添加符合 OpenAI API 规范的自定义模型。只需添加基础 URL、模型名称和 API 密钥即可。" } } } } }, "version" : "1.0" -} \ No newline at end of file +} diff --git a/packages/cli/i18n.lock b/packages/cli/i18n.lock index 5a7b48636..dea13d0e0 100644 --- a/packages/cli/i18n.lock +++ b/packages/cli/i18n.lock @@ -130,7 +130,243 @@ checksums: multiline_html: a2f5d47387c8011c0dccc58ceaa1cb8c 250a4a9b39c8b90557bd4f761e5f3cbb: "%20and%20": 05dc0a811ee5b04941c826293471367d - apple: 263c986f157e7e030f8a69693c158cb5 + -%20: 3d141bf89758137c7f02d30c7a5fd9e8 + .: f05f450fffcb17520c441ab9789f40ce + "%C2%B7": 26b80ae8a680de73667e096098aa69d8 + "%2Fmo": ed85f2a8ca60f479ded99b66261a808a + "%23%25%40%20-%20%25%40": 0bce3dc5932f2d59f7c22ed170aa56bb + "%23%25lld%20-%20%25%40": 0bce3dc5932f2d59f7c22ed170aa56bb + "%25%40": 7ba3db343a150b1789fd64ac7b9aeac3 + "%25%40%25%40": 6a19bfae7d93ea0bd310011c65b08613 + "%25lf": 7ba3db343a150b1789fd64ac7b9aeac3 + "%25lld": 7ba3db343a150b1789fd64ac7b9aeac3 + "%25lld%20%2F%20%25lld": bde1c7af473e2aceeef11cf059438ea4 + "%25lld%20files": 00933e82c654d27b84bba7e5a6c96f57 + "%25lld%2F%25lld%20files": 52b77ca35750ab16618308f572910100 + "%2B%20": 86628d7c943f0c1ee0a925c7055b55ee + "%2B%20Make%20%22%25%40.swift%22": 1469f5ec326516e29d195233eabead16 + "%2B%20top-up%20for%20%249%20%2F%20250%20messages": e0840237de18a97fa4e916be551a2c50 + "%E2%8C%98%E2%8C%AB%20stop": e0e6d2b9cf7d6daf2b65d7327a3baa35 + "%E2%8C%98%E2%8F%8E%20codebase": 4ae1e324fe5a5ba3ec3ecd3331c70492 + "%E2%8F%8E%20chat": d321cb7fd6d6a07dc03f670366fd1b0e + "%240%2Fmo": f6518ef7e5e1cd98fe39835d0b5a86ce + 5%20Code%20Applies: b46a24d26a094172f3ca6c941009f01d + 5%20Git%20Commit%20Generations: bd206ff2a569ff9a6e121d75c50c77f3 + 5%20Voice%20Inputs: 9e249eb56d7774e84d255f25d7f0f79b + 50%20Chat%20Messages: 3496f8de34bacb1022de4f307a2d9868 + 50%20Tab-to-Completes: 1f1e3465a890456a1e3aa1ca60bec445 + 750%20Chat%20Messages%20%2F%20month: e7412e04760c79505fb25ab78ecefb08 + Accept%20and%20Commit: 15e3988c501ab812867b5a7274935c9d + Account: 01215c12fb1cdb93bd0c84c1382bef56 + Account%20View: 5c142f607d94c101c0bda433e84c85cc + Add: 87c4a663507f2bcbbf79934af8164e13 + Add%20File: 5eb02c999266fe3914905f27f3ca771a + Add%20New%20Model: 999389055199eef548d4c7fb2ebc8431 + Add%20New%20Prompt: 95b69b004adec52b70f7267ecf6d06dd + Add%20selected%20lines%20to%20context: 4f25c044b92870dbd12fc2fd489c2d47 + Add%20web%20page%20from%20browser%20(Cmd%2BL): 83e7afdd2353141627c65037307f4f08 + Admin: 90eb20f1400db82ab874744e47836dc6 + Admin%20Settings: 0a891c3a956e84f97e657e2d420842c4 + Advanced%20Search%20Panel: a7922b93602e82d29689c79216a0d624 + Agent%20(Sonnet): 8ae5d4983c5324e8faeefcad8a61ffd3 + Agent%20Mode: 34344690a365687daa63c2e4ff868fa0 + Agent%20Settings: 5920237090cf08ff3d55d3b7c8ec0f18 + Alex: 7a1dc502d31e71031d33ca235f9ecfa5 + Alpha: c3d37590e52c74260dd51aa5f25e29b3 + Already%20have%20an%20account%3F: 699043a787e26ec2ecad53f52df28d5b + Anthropic%20Key: 258e7b7b475205e08742ff441086cc59 + API%20Key: ce825fec5b3e1f8e27c45b1a63619985 + Apple%20Docs: 8c6951442f0a663c834800df1a56acea + Apple%20Docs%20(Individual): 05e3707fcda27e2fc82dae69639363ea + Apply%20Panel: 8ef1c03a4cefa76973898d6cbc6be2d5 + Are%20you%20sure%20you%20want%20to%20delete%20this%20chat%3F: f24abe5f3cfad07d6038f038e24681a6 + Are%20you%20sure%20you%20want%20to%20delete%20this%20memory%3F%20This%20action%20cannot%20be%20undone.: d2aae6d8c5d3b83d86300ad885ff9a8a + Are%20you%20sure%20you%20want%20to%20log%20out%3F: 94ba30f4f17f4eed2aa5b67ebc27c8a4 + Auto%20context: f33d23c13b498c635ae00ff5ace4f03c + Auto-activate%20sidebar%20on%20hover: bd48a90b141455681d67ee89f90578ae + Auto-activate%20sidebar%20when%20Xcode%20is%20activated: 507ee7afcf8d1f8e5abc452358776bfc + Auto-position%20window%20next%20to%20Xcode: 4f692ad1a1951e21bcc68b17775e9a4d + Auto-send%20voice%20transcriptions: 957271b637c99f7b969f6b34cd32aec9 + Autofix%20Issues: c7453f3d66d09ebf9a782bb039c539d7 + Base%20URL: 3af3ef926c3531a2fb49de3afd8c6007 + Billing%20%26%20Usage: 348175fbad7a080095bba8f3e2e7c19d + Billing%20History: 2c2802bfaca8774325efb30773ab89a1 + Buy%20More: d7e27dfdf8a3ea59906e9a8e57844289 + By%20signing%20in%2C%20Alex%20will%20be%20happy%20again.: b2c7ce79d1c6e3e4e7ed8a797347304f + By%20signing%20up%2C%20you%20agree%20to%20our%20: 0a7d4d4f37a7b26c01f739abd8f9ed50 + Can%20send%20images: 76418f92799a0a87be624b07a5985538 + Cancel: 2e2a849c2223911717de8caa2c71bade + Category: 1b0340cd175aa5a2be745a0d54908466 + Changes%20committed%20successfully!: 328e36a570da2bcf181232099d1970b7 + Chat%20Models: bc87f0df58aaf6f73197520254c21534 + Chat%20Settings: aadfd5ac7f8b7ab68729ca32d9b26516 + Check%20Plan%20Options: 0c72c7a69e7288fb477fb27e52d4f9ca + Clear: d4c069de3111b7a5df96f3703f199f2f + Code%20Applies: 4791ba1d803a96181af532313dc29e90 + Codebase: c3d7349ae10dc661580f89ed44ed20c5 + Confirm%20override%20path: 613004f4428d11a073405b41f2d639d5 + Copy%20Message: a40bc6b89ccd3b28c0a80d5d563b373c + Create%20new%20chat%20with%20selected%20lines: afe4ddd1bc8bba0291c4e72bc1bd2825 + Current%20Directory%3A: 1a6133104bd6f11743ab43580c10031a + Custom%20Models: c90a845c7013d5e0e7458e2a6cf77d1a + Custom%20Prompts: 8d867142ed116ef2c19d469d3e717e42 + Debug%20Support: c129c695c3a581354273b9811b326267 + Delete: 8bcf303dd10a645b5baacb02b47d72c9 + Delete%20Chat: 38f623dc2fe274087d6dfbcae8700202 + Delete%20Index: 415d6d6981e10443a7581b1b55cdef5a + Delete%20Memory: bc1d517e32cc0316d7507aa873c57725 + Diff: df5791459ade7e949d2cc1fc073528ff + Discord%20Support: 6d0a6228a6783bff376fd579eccd43f8 + Display%20Name: 5b5f99a8bf61d1b1c5a0383feb909fae + Docs: 55fea190a0c0fb32acd3dc986cd3cc91 + Don't%20have%20an%20account%3F: 613efdc05ae6d04b7136d199645c56ac + Email: e7f34943a0c2fb849db1839ff6ef5cb5 + Enable%20Memory: 377c3b268a15a7dfcfb3944928b4cb25 + Enable%20Voice%20Mode%20(Shift%20%2B%20Cmd%20%2B%20V): 287e5f81c34e9a40d8a06e11a7ed183f + Ending%20%25%40: 15c7f0bd7f8352a7a2aaf593189a64cc + Enter%20debug%20token: 2ff92be0a6abbd2c003502b1bcab5092 + Enter%20ID: 598e7bc7d051b33faf0cd437c81f4d2b + Enter%20Key: eef254b4299007352ce4a698309c1305 + Enter%20prompt%20here: d1ec584170f41dd948bfecab8969e0fe + Enter%20the%20name%20and%20value%20for%20the%20new%20prompt: 336f1a692287009d7e6a96a8eef09a44 + Enter%20URL: 468c2276d0f2cb971ff5a47a20fa4b97 + Enter%20your%20query: 56b3e1178b373a6044896e356b5199a8 + Expand%20%25lld%20more%20lines: 6e7d0ce1be1df42550ccb8f3c34c0a4f + Feature%20Settings: 0f8161bd3d9b46864d6c5cbaa0a7eea4 + Features%20and%20Keybindings: 7b3a1d275b686e9a3f712cf20c67e6c8 + Files: aee803d2f576ac1200c73b691191a916 + Fill%20to%20expand%20available%20width: e82251a18a395ca967243cb95b884981 + Free%20Beta: dd32315cb382d3c5990d11d46e609755 + Free%20Plan: c995acccc1e3cba379786892a5b4d4e5 + Gemini%20Key: 885a9c57c173f2edbe834022a69ea9fe + Generate%20Commit%20Message: f08fba2b3c257f082a8d0e5e497e4893 + Git%20Commit%20Generation: aa899626fd778f23a1882efa80d4a88b + Git%20Commits: a2908535f758431c697d33ffcdfc5d7f + Git%20Status: 92437bdfa47180761e0d7915644baf8b + Hello%2C%20World!: df22d840000cd8359a131fcd18f085b5 + How%20is%20my%20data%20used%3F: 8c4620d5c2284867719d4365c00f9df2 + I've%20applied%20the%20code: faaa710252f7e3e7593f2b2d3e4302d3 + If%20we%20request%20a%20remote%20debugging%20session%20with%20you%20through%20Discord%2C%20please%20enter%20the%20token%20here%20and%20click%20on%20%22Start%20Debug%20Session%22.: 139536edd9acb1dd9d782ec4abaf4ce7 + Important%3A%20Please%20update%20to%20version%20%25%40.%20%25%40: 94aea3656aeda8e4bd1ec284a376cc96 + In%20agent%20mode%2C%20Claude%203.5%20Sonnet%20is%20used%20by%20default%20because%20it%20is%20the%20best%20model%20for%20code%20generation.%20If%20you'd%20like%20to%20switch%20to%20a%20different%20model%2C%20disable%20agent%20mode.%0A%0A(You%20can%20always%20turn%20it%20back%20on%20in%20the%20Agent%20Settings%20dropdown.): 673b7f4e839a510c15a36f88a73d99d2 + Indexed: cf4399bfb7c957babc54190d362bdd84 + Indexed%20Files: f18424f6b67b9f98ab5fea5951edb8c7 + Inline%20completion: f2aa9da8c8152b788c064956e7209054 + Join%20Discord: e08eae264d85751753a88b7796aeda77 + Learn%20more%20about%20Agent%20best%20practices%20here%3A%0A%0A%5Bhttps%3A%2F%2Fdocs.alexcodes.app%2Fchat%2Fcontext%2Fagents%5D(https%3A%2F%2Fdocs.alexcodes.app%2Fchat%2Fcontext%2Fagents): 67467d537fbbb1cbf284c7293d7e415c + Line%20%25lld: e4dc04b609d8343818d4d92dabb99e37 + listening%20(press%20%E2%8F%8E%20to%20send): 3e349c36e20f2acf08d9b48d0947d405 + listening%20(press%20%E2%8F%8E%20to%20stop): ceb1eb93d17a548fd184142a285035b8 + Load%20Index: 8e45623766c72c3d98c0cfc44302c3ff + Loading%20billing%20information...: 66de6f9ba74841e0785eceb9d026ab49 + Log%20Out: 0a29c741e0a1f63184ee7b85ce2da68c + Logout: 07948fdf20705e04a7bf68ab197512bf + Made%20in%20SwiftUI: 9d28ae71541b6c55f99cc300a78ffb26 + Manage%20Subscription: 31cafd367fc70d656d8dd979d537dc96 + Manage%20Trial%20Subscription: e028ce5edba2ff085977055ca1b3a25d + Match%20height%20with%20Xcode: a845ac29266dd0dfa0eb4ad4998834b2 + Memory: 7e91fe4b762eaa7410fa882788e1504b + Memory%20Settings: 05dba59a1b919e5bfcc6bb0f6a251cba + Message%20Top%20Ups: 4e82c9b94b797d350f83285e48e18296 + Model%20ID: 731e9d41baefa732a4547fd64144c883 + Model%20Settings: 867d7f455466583933336a993edc63a9 + Models: d7687c91fa3ba81da866dee3becc5b5b + Monthly%20Messages: 037c285835f77ae8a634b4910ec7509d + Name: 9368b5a047572b6051f334af5aa76819 + No: 8c708225830b06df2d1141c536f2a0d6 + No%20billing%20history%20available: 3b60ca00d0183088d3eb2928b254053a + No%20context%20selected: 52c822c860f65c172ecff9b1cf318177 + No%20memories%20found: 6b863b6986769a5743d8d63afcbc165c + No%20Project%20Focused: ebaa294dba776d9366eb154d58e1db30 + No%20results%20found: 5518f2865757dc73900aa03ef8be6934 + No%20userdata%20found: 24676d4e8900ceb23f8bfc1ec46d27ec + Not%20Indexed: cd9d82ed479704d6157cb0f8c7638d6d + Not%20logged%20in: bb319f3116b5316a6a1452af9d4e4022 + Note%3A%20This%20URL%20must%20be%20publicly%20available%20(not%20a%20localhost%20URL).: c3d8e6cdead98d13c54d8093a6388ede + o1%20Credits: 1fb4903ddfe8befd1776d5a49dcc2e61 + O1-Preview%20Credits: 3990119c72701cf9f1a789b0900d33cf + Only%20for%20this%20project%2C%20and%20will%20be%20used%20in%20combination%20with%20your%20custom%20system%20prompt.: bc439e100698a8a9f15fa31854dddbdd + Open%20Permission%20Settings: 214c443ddcd7b6f60b91aff264899cc5 + OpenAI%20Key: f9130b13ee8e42724ae1f6a243180b99 + Perplexity%20Key: d6419bcbf95589aca1b314f150f79c40 + Pin%20chat%20input%20to%20bottom: 758f65861bb3d2b63e60cf17eac09fdc + Plan: c6a08c771f97d86b02cf10d8f5f2d788 + Please%20grant%20accessibility%20permissions%20so%20Alex%20can%20work%20with%20Xcode.: 8c50d3e26239595e9e4c7c614560d98e + Popular: e580356112d688f2eab32e488eef07eb + Preview%3A: 5315010ff36d8f386c2fabf930f62083 + Privacy: 6007d5d5f6591c027b15bd49ab7a8c47 + Privacy%20Policy: 7459744a63ef8af4e517a09024bd7c08 + Project-Specific%20Prompt: 8a6efdcc5e87c5720661bc8eca521bff + Prompt%20Name: 8b35daaa7ef1b9b5a66cc64029c25130 + Purchase%20Subscription: e1060f146369cdc2d74b41e64423e9e9 + Quick%20Actions%3A: 1ccee54e9568833aea46ebeb17b2de06 + record: 176db9e8b4226009e473655bcb4cb38b + Refresh: c0aec3f31be4c984bae9a482572d2857 + Related%20Files%3A: e354b726ce14c3004e6e7badcc6d3f0a + Reload%20Index: 6041a2b394fe8cf4adaf81c5c039a358 + Remote%20Debugging%20Session: 140a38d4e5ebda4a8699e9d2bff49f9a + Remove: dba2fe5fe9f83f8078c687f28cba4b52 + Rerank: 6146721bf1c7d6083adbc044d141bb58 + Search%20chats...: 7dead413e5e7e09286f0aaa95a755d6a + Search%20files: 31575252153a32d2f4be17756e992a4b + Search%20memories...: 07733c9068a58a05122b94d1ee2f09eb + Select%20All: ef9e1f8aaf1fbbdf868934209c85aea2 + Semantic: 0bef06e64f9bdfb4b42cc74c0cf82f98 + Settings: 8df6777277469c1fd88cc18dde2f1cc3 + Show%20code%20apply%20view%20at%20bottom: 9e52cc0afde6fbdb6c32f1ab4e424fc2 + Show%20Hints: 7eb461e148cf3b6a853983a4a120e774 + Show%20less: 377af19e130feb94abe6fc3d281b55fd + Show%20suggestion%20details: 5491d75199859e2e3e27d8f694160cde + Shrink%20code%20view%20sections: 9436a49a5ea8d1b0fcee15e286d5d938 + Sign%20in: cb8757c7450e17de1e226e82fb0fa4a2 + Sign%20In: ec7b8f314fe9bc6591006707484ede61 + Sign%20in%20with%20Google: f84b1b8574fb23734c002b401cad49e2 + Sign%20up: a6a0b995463f62ce6a12e37f1d05a9bd + Sign%20Up: 0dd2ae69be4618c1f9e615774a4509ca + Sign%20up%20with%20Google: 6e48a32de87c09a7bd64a4c6a0babfa2 + Staged%20Changes: ee69ec9543ab05db1319bf1d45399737 + Standard: 455b063e1181932d8d3ae222583afe96 + Start%20Debug%20Session: dc55c26f944fad6ea27b75dcb9fc755f + Start%20Free%20Trial%20(7%20days): 21011e333883f488cb9a6844f8fb8d7a + Start%20Subscription: 4fa5d2444857063062c14eabf8e073b3 + Start%20without%20context: 64b249d79b828bcd42fda87d0fc6ae68 + Stop%20Debug%20Session: 3afbf313ed99e6f30df8ed1436ae3ba1 + Suggestion%20Details: 260795fb6914f447ba77179d3e64aa47 + Suggestions: d3e2e4d20f64514a3833ed3e8a7de675 + Support: 55aab5fd0f31a9cb055a2edeeedfaf63 + System%20Prompt: 3980ee4b3313840de80cdbeeb510a573 + Tab-to-Complete%20suggestions%20(beta): e6129a981cc48517f6fa97092d5aa6b0 + Terms%20of%20Service: 5add91f519e39025708e54a7eb7a9fc5 + Terms%20of%20Sevice: 9eebdae8a642e7e4788ca824d35d2ccc + These%20go%20as%20additional%20info%20with%20the%20default%20system%20prompt: 54a4463f7f0fdd6633b665b9df9ca742 + Top-K%3A%20%25lld: 46a63dbc5de55d3102dd5d9558dabfba + transcribing...: 8b5f006ac3100e0b34d33701b0c3784c + Type%20something%20here%20(or%20%E2%8C%98%2Bshift%2Bv%20for%20voice): b6206485d9ede4eba24eb8a8de8eb81a + Unlimited%20Code%20Applies: ee5f6dfa2e63bbc10b2a97eb6ca0c6e5 + Unlimited%20Tab-to-Complete: 266cb2f8d9cda1436c0bd44d7286e569 + Unstaged%20Changes: ed07d2cee3fb68d5e4e893ca15339f73 + Update: 079fc039262fd31b10532929685c2d1b + Update%20available: 1285697331e7232ea69104fdd69cd916 + Update%20to%20%25%40: 890a4ff4cd90931cd750e5c3faee6635 + Usage: 9ee126f9eeb9a2ecc83946e21c61eedb + Use%20Agent: 97108c484ee0b8a1884d0fada0d581f5 + Use%20Agent%20Mode: ecdcbcdf9e46e32a73ffbfb061a309d2 + User%20Activities: 0970c17be726cf3f5b2ffd25ca935953 + Using%20Codebase%20Search: 642d119bdf5c2afe1132ddced2f50b6c + Using%20Docs: c5d276a1ad4447ce9c4783f31bccd1e0 + Voice%20Inputs: f0d9f581a34cc5e0239c22d83c344655 + Voice%20Mode: dcfdbff49b200661897ff8b47af0e1e1 + VoyageAI%20Key: a1a499ed689a15b9ef1194450fed272a + Waiting%20for%20model%25%40: 9e6f2003bf67253845e68c5d2501e18d + Want%20to%20buy%20O1%20credits%3F%20Join%20the%20Discord%20and%20message%20%40DanielEdrisian: f5cdedaaffd884550d4033e4eecfc497 + We%20conduct%20all%20of%20our%20support%20through%20Discord.%20We%20also%20send%20new%20feature%20announcements%20there!: 211fe79d47ad859316395b5ab3c05689 + We%20couldn't%20find%20an%20exact%20match%20for%20this%20snippet.%20Please%20select%20the%20file%20to%20apply%20to%3A: d29b79af6c9d70bc5f374a63dbc44571 + What's%20new%3A: 809852808f545cfa22db7aee72f5136e + When%20enabled%2C%20Alex%20will%20maintain%20context%20from%20your%20previous%20messages%20to%20provide%20more%20relevant%20responses.: 4349054bce76079037b04f399fb071d2 + Why%3F: ed1fcb14e685f430ccf3381b2532f11f + Window%20Management: 1ff2ecbd83aeabf94c60bbed4a80b7ff + Window%20Settings: 0838b41c0bb710854b4c4df99f9d43b6 + You%20can%20add%20custom%20models%20that%20comply%20with%20the%20OpenAI%20API%20scheme.%20Just%20add%20the%20base%20url%2C%20model%20name%2C%20and%20api%20key.: a177ef903dc981c03b3d30a2d470aba9 b05b783b3d24ee943d83ccd8e274814d: home/title%2Fmain: ef1fb56b8dafd605fb267df2b0a8a91f home/description%2Fdev: b866f4d6b135451633de827fc20f4fdb diff --git a/packages/cli/src/cli/cmd/cleanup.ts b/packages/cli/src/cli/cmd/cleanup.ts index db9de5955..a73077883 100644 --- a/packages/cli/src/cli/cmd/cleanup.ts +++ b/packages/cli/src/cli/cmd/cleanup.ts @@ -40,7 +40,7 @@ export default new Command() for (const bucketConfig of bucket.config) { const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); const bucketOra = Ora({ indent: 2 }).info(`Processing path: ${bucketConfig.pathPattern}`); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { isCacheRestore: false, defaultLocale: sourceLocale }); bucketLoader.setDefaultLocale(sourceLocale); // Load source data diff --git a/packages/cli/src/cli/cmd/i18n.ts b/packages/cli/src/cli/cmd/i18n.ts index 0d597ffac..39eba5603 100644 --- a/packages/cli/src/cli/cmd/i18n.ts +++ b/packages/cli/src/cli/cmd/i18n.ts @@ -81,7 +81,10 @@ export default new Command() for (const bucketConfig of bucket.config) { const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { + isCacheRestore: false, + defaultLocale: sourceLocale, + }); bucketLoader.setDefaultLocale(sourceLocale); await bucketLoader.init(); @@ -108,7 +111,10 @@ export default new Command() bucketOra.info(`Processing path: ${bucketConfig.pathPattern}`); const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { isCacheRestore: true }); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { + isCacheRestore: true, + defaultLocale: sourceLocale, + }); bucketLoader.setDefaultLocale(sourceLocale); await bucketLoader.init(); const sourceData = await bucketLoader.pull(sourceLocale); @@ -150,7 +156,10 @@ export default new Command() for (const bucketConfig of bucket.config) { const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { + isCacheRestore: false, + defaultLocale: sourceLocale, + }); bucketLoader.setDefaultLocale(sourceLocale); await bucketLoader.init(); @@ -183,7 +192,10 @@ export default new Command() const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { + isCacheRestore: false, + defaultLocale: sourceLocale, + }); bucketLoader.setDefaultLocale(sourceLocale); await bucketLoader.init(); let sourceData = await bucketLoader.pull(sourceLocale); diff --git a/packages/cli/src/cli/cmd/lockfile.ts b/packages/cli/src/cli/cmd/lockfile.ts index 09940210c..d8be5a56c 100644 --- a/packages/cli/src/cli/cmd/lockfile.ts +++ b/packages/cli/src/cli/cmd/lockfile.ts @@ -26,7 +26,7 @@ export default new Command() for (const bucket of buckets) { for (const bucketConfig of bucket.config) { const sourceLocale = resolveOverridenLocale(i18nConfig!.locale.source, bucketConfig.delimiter); - const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern); + const bucketLoader = createBucketLoader(bucket.type, bucketConfig.pathPattern, { isCacheRestore: false, defaultLocale: sourceLocale }); bucketLoader.setDefaultLocale(sourceLocale); const sourceData = await bucketLoader.pull(sourceLocale); diff --git a/packages/cli/src/cli/loaders/index.spec.ts b/packages/cli/src/cli/loaders/index.spec.ts index 86d1374e8..c2d0853cb 100644 --- a/packages/cli/src/cli/loaders/index.spec.ts +++ b/packages/cli/src/cli/loaders/index.spec.ts @@ -23,7 +23,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml"); + const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml", { isCacheRestore: false, defaultLocale: "en" }); androidLoader.setDefaultLocale("en"); const data = await androidLoader.pull("en"); @@ -44,7 +44,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml"); + const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml", { isCacheRestore: false, defaultLocale: "en" }); androidLoader.setDefaultLocale("en"); const data = await androidLoader.pull("en"); @@ -64,7 +64,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml"); + const androidLoader = createBucketLoader("android", "values-[locale]/strings.xml", { isCacheRestore: false, defaultLocale: "en" }); androidLoader.setDefaultLocale("en"); await androidLoader.pull("en"); @@ -86,7 +86,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const csvLoader = createBucketLoader("csv", "i18n.csv"); + const csvLoader = createBucketLoader("csv", "i18n.csv", { isCacheRestore: false, defaultLocale: "en" }); csvLoader.setDefaultLocale("en"); const data = await csvLoader.pull("en"); @@ -102,7 +102,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const csvLoader = createBucketLoader("csv", "i18n.csv"); + const csvLoader = createBucketLoader("csv", "i18n.csv", { isCacheRestore: false, defaultLocale: "en" }); csvLoader.setDefaultLocale("en"); await csvLoader.pull("en"); @@ -136,7 +136,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const flutterLoader = createBucketLoader("flutter", "lib/l10n/app_[locale].arb"); + const flutterLoader = createBucketLoader("flutter", "lib/l10n/app_[locale].arb", { isCacheRestore: false, defaultLocale: "en" }); flutterLoader.setDefaultLocale("en"); const data = await flutterLoader.pull("en"); @@ -180,7 +180,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const flutterLoader = createBucketLoader("flutter", "lib/l10n/app_[locale].arb"); + const flutterLoader = createBucketLoader("flutter", "lib/l10n/app_[locale].arb", { isCacheRestore: false, defaultLocale: "en" }); flutterLoader.setDefaultLocale("en"); await flutterLoader.pull("en"); @@ -233,7 +233,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const htmlLoader = createBucketLoader("html", "i18n/[locale].html"); + const htmlLoader = createBucketLoader("html", "i18n/[locale].html", { isCacheRestore: false, defaultLocale: "en" }); htmlLoader.setDefaultLocale("en"); const data = await htmlLoader.pull("en"); @@ -291,7 +291,7 @@ describe("bucket loaders", () => { mockFileOperations(input); - const htmlLoader = createBucketLoader("html", "i18n/[locale].html"); + const htmlLoader = createBucketLoader("html", "i18n/[locale].html", { isCacheRestore: false, defaultLocale: "en" }); htmlLoader.setDefaultLocale("en"); await htmlLoader.pull("en"); @@ -308,7 +308,7 @@ describe("bucket loaders", () => { const input = { "button.title": "Submit" }; mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); const data = await jsonLoader.pull("en"); @@ -324,7 +324,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -342,7 +342,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -360,7 +360,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -378,7 +378,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -396,7 +396,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: true }); + const jsonLoader = createBucketLoader("json", "i18n/[locale].json", { isCacheRestore: true, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -414,7 +414,7 @@ describe("bucket loaders", () => { mockFileOperations(JSON.stringify(input)); - const jsonLoader = createBucketLoader("json", "i18n/[locale]/[locale].json"); + const jsonLoader = createBucketLoader("json", "i18n/[locale]/[locale].json", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); const data = await jsonLoader.pull("en"); @@ -452,7 +452,7 @@ Another paragraph with **bold** and *italic* text.`; mockFileOperations(input); - const markdownLoader = createBucketLoader("markdown", "i18n/[locale].md"); + const markdownLoader = createBucketLoader("markdown", "i18n/[locale].md", { isCacheRestore: false, defaultLocale: "en" }); markdownLoader.setDefaultLocale("en"); const data = await markdownLoader.pull("en"); @@ -498,7 +498,7 @@ Otro párrafo con texto en **negrita** y en _cursiva_. mockFileOperations(input); - const markdownLoader = createBucketLoader("markdown", "i18n/[locale].md"); + const markdownLoader = createBucketLoader("markdown", "i18n/[locale].md", { isCacheRestore: false, defaultLocale: "en" }); markdownLoader.setDefaultLocale("en"); await markdownLoader.pull("en"); @@ -535,7 +535,7 @@ user.password=Password mockFileOperations(input); - const propertiesLoader = createBucketLoader("properties", "i18n/[locale].properties"); + const propertiesLoader = createBucketLoader("properties", "i18n/[locale].properties", { isCacheRestore: false, defaultLocale: "en" }); propertiesLoader.setDefaultLocale("en"); const data = await propertiesLoader.pull("en"); @@ -572,7 +572,7 @@ user.password=Contraseña mockFileOperations(input); - const propertiesLoader = createBucketLoader("properties", "i18n/[locale].properties"); + const propertiesLoader = createBucketLoader("properties", "i18n/[locale].properties", { isCacheRestore: false, defaultLocale: "en" }); propertiesLoader.setDefaultLocale("en"); await propertiesLoader.pull("en"); @@ -599,7 +599,7 @@ user.password=Contraseña mockFileOperations(input); - const xcodeStringsLoader = createBucketLoader("xcode-strings", "i18n/[locale].strings"); + const xcodeStringsLoader = createBucketLoader("xcode-strings", "i18n/[locale].strings", { isCacheRestore: false, defaultLocale: "en" }); xcodeStringsLoader.setDefaultLocale("en"); const data = await xcodeStringsLoader.pull("en"); @@ -617,7 +617,7 @@ user.password=Contraseña mockFileOperations(input); - const xcodeStringsLoader = createBucketLoader("xcode-strings", "i18n/[locale].strings"); + const xcodeStringsLoader = createBucketLoader("xcode-strings", "i18n/[locale].strings", { isCacheRestore: false, defaultLocale: "en" }); xcodeStringsLoader.setDefaultLocale("en"); await xcodeStringsLoader.pull("en"); @@ -668,7 +668,7 @@ user.password=Contraseña mockFileOperations(input); - const xcodeStringsdictLoader = createBucketLoader("xcode-stringsdict", "i18n/[locale].stringsdict"); + const xcodeStringsdictLoader = createBucketLoader("xcode-stringsdict", "i18n/[locale].stringsdict", { isCacheRestore: false, defaultLocale: "en" }); xcodeStringsdictLoader.setDefaultLocale("en"); const data = await xcodeStringsdictLoader.pull("en"); @@ -701,7 +701,7 @@ user.password=Contraseña mockFileOperations(input); - const xcodeStringsdictLoader = createBucketLoader("xcode-stringsdict", "[locale].lproj/Localizable.stringsdict"); + const xcodeStringsdictLoader = createBucketLoader("xcode-stringsdict", "[locale].lproj/Localizable.stringsdict", { isCacheRestore: false, defaultLocale: "en" }); xcodeStringsdictLoader.setDefaultLocale("en"); await xcodeStringsdictLoader.pull("en"); @@ -718,328 +718,389 @@ user.password=Contraseña it("should load xcode-xcstrings", async () => { setupFileMocks(); - const input = ` -{ - "sourceLanguage" : "en", - "strings" : { - "greeting" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Hello!" + const input = JSON.stringify({ + "sourceLanguage": "en", + "strings": { + "greeting": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hello!" + } + } + } }, - }, - }, - }, - }, - "version" : "1.0" -} - `.trim(); - const expectedOutput = { greeting: "Hello!" }; + "message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Welcome to our app" + } + } + } + }, + "items_count": { + "extractionState": "manual", + "localizations": { + "en": { + "variations": { + "plural": { + "zero": { + "stringUnit": { + "state": "translated", + "value": "No items" + } + }, + "one": { + "stringUnit": { + "state": "translated", + "value": "%d item" + } + }, + "other": { + "stringUnit": { + "state": "translated", + "value": "%d items" + } + } + } + } + } + } + } + } + }); + + const expectedOutput = { + "greeting": "Hello!", + "message": "Welcome to our app", + "items_count/zero": "No items", + "items_count/one": "{variable:0} item", + "items_count/other": "{variable:0} items" + }; mockFileOperations(input); - const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "Localizable.xcstrings"); + const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "i18n/[locale].xcstrings", { isCacheRestore: false, defaultLocale: "en" }); xcodeXcstringsLoader.setDefaultLocale("en"); const data = await xcodeXcstringsLoader.pull("en"); expect(data).toEqual(expectedOutput); }); - it("should save xcode-xcstrings with alphabetically sorted keys", async () => { + it("should load keys without default locale entries and use the key as value", async () => { setupFileMocks(); - const input = ` -{ - "sourceLanguage" : "en", - "strings" : { - "zebra" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zebra" - } - } - } - }, - "apple" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apple" - } - }, - "zh" : { - "stringUnit" : { - "state" : "translated", - "value" : "苹果" + const input = JSON.stringify({ + "sourceLanguage": "en", + "strings": { + "greeting": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hello!" + } + } + } + }, + " and ": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": " and " + } + } + } + }, + "key_with_no_default": { + "extractionState": "manual", + "localizations": { + "fr": { + "stringUnit": { + "state": "translated", + "value": "Valeur traduite" + } + } + } } } - } - } - }, - "version" : "1.0" -}`.trim(); - const payload = { - zebra: "Cebra", - apple: "Manzana", + }); + + const expectedOutput = { + "greeting": "Hello!", + "%20and%20": " and ", + "key_with_no_default": "key_with_no_default" }; - const expectedOutput = `{ - "sourceLanguage" : "en", - "strings" : { - "apple" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apple" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Manzana" - } - }, - "zh" : { - "stringUnit" : { - "state" : "translated", - "value" : "苹果" - } - } - } - }, - "zebra" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zebra" - } - }, - "es" : { - "stringUnit" : { - "state" : "translated", - "value" : "Cebra" + + mockFileOperations(input); + + const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "i18n/[locale].xcstrings", { isCacheRestore: false, defaultLocale: "en" }); + xcodeXcstringsLoader.setDefaultLocale("en"); + const data = await xcodeXcstringsLoader.pull("en"); + + expect(data).toEqual(expectedOutput); + }); + + it("should save xcode-xcstrings", async () => { + setupFileMocks(); + + const originalInput = { + "sourceLanguage": "en", + "strings": { + "greeting": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hello!" + } + } + } } } - } - } - }, - "version" : "1.0" -}`.trim(); + }; - mockFileOperations(input); + mockFileOperations(JSON.stringify(originalInput)); - const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "Localizable.xcstrings"); + const payload = { + "greeting": "Bonjour!", + "message": "Bienvenue dans notre application", + "items_count/zero": "Aucun élément", + "items_count/one": "%d élément", + "items_count/other": "%d éléments" + }; + + const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "i18n/[locale].xcstrings", { isCacheRestore: false, defaultLocale: "en" }); xcodeXcstringsLoader.setDefaultLocale("en"); await xcodeXcstringsLoader.pull("en"); + await xcodeXcstringsLoader.push("fr", payload); - await xcodeXcstringsLoader.push("es", payload); + expect(fs.writeFile).toHaveBeenCalled(); + const writeFileCall = (fs.writeFile as any).mock.calls[0]; + const writtenContent = JSON.parse(writeFileCall[1]); - expect(fs.writeFile).toHaveBeenCalledWith("Localizable.xcstrings", expectedOutput, { - encoding: "utf-8", - flag: "w", - }); + expect(writtenContent.strings.greeting.localizations.fr).toBeDefined(); + expect(writtenContent.strings.greeting.localizations.fr.stringUnit.value).toBe("Bonjour!"); + + if (writtenContent.strings.message) { + expect(writtenContent.strings.message.localizations.fr.stringUnit.value).toBe("Bienvenue dans notre application"); + } + + if (writtenContent.strings.items_count) { + expect(writtenContent.strings.items_count.localizations.fr.variations.plural.zero.stringUnit.value).toBe("Aucun élément"); + expect(writtenContent.strings.items_count.localizations.fr.variations.plural.one.stringUnit.value).toBe("%d élément"); + expect(writtenContent.strings.items_count.localizations.fr.variations.plural.other.stringUnit.value).toBe("%d éléments"); + } }); - it("should maintain ASCII ordering with whitespace and special characters", async () => { + it("should maintain ASCII ordering with empty strings, whitespace, and numbers", async () => { setupFileMocks(); const input = `{ - "sourceLanguage" : "en", - "strings" : { - "" : { - - }, - " " : { - - }, - " and " : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : " and " - } - }, - } - }, - "2a" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "2a" + "sourceLanguage": "en", + "strings": { + "": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Empty key" } } } }, - "3x" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "3x" + " ": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Space key" } } } }, - "25" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "25" + "25": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Numeric key" } } } }, - "apple" : { - "extractionState" : "manual", - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "apple" + "apple": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Apple" } } } - } - }, - "version" : "1.0" -}`.trim(); - - const payloadAr = { - "": "", - " ": "", - "%20and%20": " و ", - "25": "25", - apple: "تفاحة", - }; + } +}`; - const expectedOutput = `{ - "sourceLanguage" : "en", - "strings" : { - "" : { + mockFileOperations(input); - }, - " " : { + const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "i18n/[locale].xcstrings", { isCacheRestore: false, defaultLocale: "en" }); + xcodeXcstringsLoader.setDefaultLocale("en"); + const data = await xcodeXcstringsLoader.pull("en"); - }, - " and " : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : " و " - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : " and " - } + Object.keys(data).forEach(key => { + if (key === "") { + expect(data[key]).toBe("Empty key"); + } else if (key.includes("%20") || key === " ") { + console.log(`Found space key: "${key}"`); + expect(data[key]).toBe("Space key"); + } else if (key === "25") { + expect(data[key]).toBe("Numeric key"); + } else if (key === "apple") { + expect(data[key]).toBe("Apple"); } - } - }, - "2a" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "2a" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "2a" - } + }); + + const payload: Record = {}; + + Object.keys(data).forEach(key => { + if (key === "") { + payload[key] = "Vide"; + } else if (key.includes("%20") || key === " ") { + payload[key] = "Espace"; + } else if (key === "25") { + payload[key] = "Numérique"; + } else if (key === "apple") { + payload[key] = "Pomme"; } + }); + + await xcodeXcstringsLoader.pull("en"); + await xcodeXcstringsLoader.push("fr", payload); + + expect(fs.writeFile).toHaveBeenCalled(); + const writeFileCall = (fs.writeFile as any).mock.calls[0]; + const writtenContent = JSON.parse(writeFileCall[1]); + + if (writtenContent.strings[""]) { + expect(writtenContent.strings[""].localizations.fr.stringUnit.value).toBe("Vide"); } - }, - "3x" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "3x" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "3x" - } + + const hasSpaceKey = Object.keys(writtenContent.strings).some( + key => key === " " || key === "%20" || key.includes("%20") + ); + if (hasSpaceKey) { + const spaceKey = Object.keys(writtenContent.strings).find( + key => key === " " || key === "%20" || key.includes("%20") + ); + console.log(`Found space key in written content: "${spaceKey}"`); + if (spaceKey) { + expect(writtenContent.strings[spaceKey].localizations.fr.stringUnit.value).toBe("Espace"); } } - }, - "25" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "25" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "25" + + if (writtenContent.strings["25"]) { + expect(writtenContent.strings["25"].localizations.fr.stringUnit.value).toBe("Numérique"); + } + + if (writtenContent.strings["apple"]) { + expect(writtenContent.strings["apple"].localizations.fr.stringUnit.value).toBe("Pomme"); + } + + const stringKeys = Object.keys(writtenContent.strings); + + expect(stringKeys.includes("25")).toBe(true); + expect(stringKeys.includes("")).toBe(true); + expect(stringKeys.includes(" ") || stringKeys.includes("%20")).toBe(true); + expect(stringKeys.includes("apple")).toBe(true); + + expect(stringKeys.indexOf("25")).toBeLessThan(stringKeys.indexOf("")); + + const spaceIdx = stringKeys.indexOf(" ") === -1 ? stringKeys.indexOf("%20") : stringKeys.indexOf(" "); + if (spaceIdx !== -1) { + expect(stringKeys.indexOf("")).toBeLessThan(spaceIdx); + } + + if (spaceIdx !== -1) { + expect(spaceIdx).toBeLessThan(stringKeys.indexOf("apple")); + } + }); + + it("should respect shouldTranslate: false flag", async () => { + setupFileMocks(); + + const input = `{ + "sourceLanguage": "en", + "strings": { + "do_not_translate": { + "shouldTranslate": false, + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This should not be translated" } } } }, - "apple" : { - "extractionState" : "manual", - "localizations" : { - "ar" : { - "stringUnit" : { - "state" : "translated", - "value" : "تفاحة" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "apple" + "normal_key": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This should be translated" } } } } - }, - "version" : "1.0" -}`.trim(); + } +}`; mockFileOperations(input); - const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "Localizable.xcstrings"); + const xcodeXcstringsLoader = createBucketLoader("xcode-xcstrings", "i18n/[locale].xcstrings", { isCacheRestore: false, defaultLocale: "en" }); xcodeXcstringsLoader.setDefaultLocale("en"); - await xcodeXcstringsLoader.pull("en"); - - await xcodeXcstringsLoader.push("ar", payloadAr); - - expect(fs.writeFile).toHaveBeenCalledWith("Localizable.xcstrings", expectedOutput, { - encoding: "utf-8", - flag: "w", - }); + + const data = await xcodeXcstringsLoader.pull("en"); + + expect(data).toHaveProperty("normal_key", "This should be translated"); + expect(data).not.toHaveProperty("do_not_translate"); + + const payload = { + "normal_key": "Ceci devrait être traduit" + }; + + await xcodeXcstringsLoader.push("fr", payload); + + expect(fs.writeFile).toHaveBeenCalled(); + const writeFileCall = (fs.writeFile as any).mock.calls[0]; + const writtenContent = JSON.parse(writeFileCall[1]); + + expect(writtenContent.strings.normal_key.localizations.fr.stringUnit.value).toBe("Ceci devrait être traduit"); + + expect(writtenContent.strings.do_not_translate).toHaveProperty("shouldTranslate", false); + + expect(writtenContent.strings.do_not_translate.localizations).not.toHaveProperty("fr"); + + await xcodeXcstringsLoader.push("fr", {}); + + const secondWriteFileCall = (fs.writeFile as any).mock.calls[1]; + const secondWrittenContent = JSON.parse(secondWriteFileCall[1]); + + expect(secondWrittenContent.strings.do_not_translate).toHaveProperty("shouldTranslate", false); }); }); @@ -1054,7 +1115,7 @@ user.password=Contraseña mockFileOperations(input); - const yamlLoader = createBucketLoader("yaml", "i18n/[locale].yaml"); + const yamlLoader = createBucketLoader("yaml", "i18n/[locale].yaml", { isCacheRestore: false, defaultLocale: "en" }); yamlLoader.setDefaultLocale("en"); const data = await yamlLoader.pull("en"); @@ -1072,7 +1133,7 @@ user.password=Contraseña mockFileOperations(input); - const yamlLoader = createBucketLoader("yaml", "i18n/[locale].yaml"); + const yamlLoader = createBucketLoader("yaml", "i18n/[locale].yaml", { isCacheRestore: false, defaultLocale: "en" }); yamlLoader.setDefaultLocale("en"); await yamlLoader.pull("en"); @@ -1094,7 +1155,7 @@ user.password=Contraseña mockFileOperations(input); - const yamlRootKeyLoader = createBucketLoader("yaml-root-key", "i18n/[locale].yaml"); + const yamlRootKeyLoader = createBucketLoader("yaml-root-key", "i18n/[locale].yaml", { isCacheRestore: false, defaultLocale: "en" }); yamlRootKeyLoader.setDefaultLocale("en"); const data = await yamlRootKeyLoader.pull("en"); @@ -1113,7 +1174,7 @@ user.password=Contraseña mockFileOperations(input); - const yamlRootKeyLoader = createBucketLoader("yaml-root-key", "i18n/[locale].yaml"); + const yamlRootKeyLoader = createBucketLoader("yaml-root-key", "i18n/[locale].yaml", { isCacheRestore: false, defaultLocale: "en" }); yamlRootKeyLoader.setDefaultLocale("en"); await yamlRootKeyLoader.pull("en"); @@ -1152,7 +1213,7 @@ Bar mockFileOperations(input); - const vttLoader = createBucketLoader("vtt", "i18n/[locale].vtt"); + const vttLoader = createBucketLoader("vtt", "i18n/[locale].vtt", { isCacheRestore: false, defaultLocale: "en" }); vttLoader.setDefaultLocale("en"); const data = await vttLoader.pull("en"); @@ -1177,7 +1238,6 @@ Foo Bar `.trim(); - // // Complex VTT payload to save const payload = { "0#0-1#": "¡Hola mundo!", "1#30-31#": "Este es un subtítulo", @@ -1202,7 +1262,7 @@ Bar`.trim(); mockFileOperations(input); - const vttLoader = createBucketLoader("vtt", "i18n/[locale].vtt"); + const vttLoader = createBucketLoader("vtt", "i18n/[locale].vtt", { isCacheRestore: false, defaultLocale: "en" }); vttLoader.setDefaultLocale("en"); await vttLoader.pull("en"); @@ -1240,7 +1300,7 @@ Bar`.trim(); mockFileOperations(input); - const xmlLoader = createBucketLoader("xml", "i18n/[locale].xml"); + const xmlLoader = createBucketLoader("xml", "i18n/[locale].xml", { isCacheRestore: false, defaultLocale: "en" }); xmlLoader.setDefaultLocale("en"); const data = await xmlLoader.pull("en"); @@ -1285,7 +1345,7 @@ Bar`.trim(); .replace(/>\s+<") .trim(); mockFileOperations(input); - const xmlLoader = createBucketLoader("xml", "i18n/[locale].xml"); + const xmlLoader = createBucketLoader("xml", "i18n/[locale].xml", { isCacheRestore: false, defaultLocale: "en" }); xmlLoader.setDefaultLocale("en"); await xmlLoader.pull("en"); @@ -1315,7 +1375,7 @@ World! mockFileOperations(input); - const srtLoader = createBucketLoader("srt", "i18n/[locale].srt"); + const srtLoader = createBucketLoader("srt", "i18n/[locale].srt", { isCacheRestore: false, defaultLocale: "en" }); srtLoader.setDefaultLocale("en"); const data = await srtLoader.pull("en"); @@ -1350,7 +1410,7 @@ Mundo!`; mockFileOperations(input); - const srtLoader = createBucketLoader("srt", "i18n/[locale].srt"); + const srtLoader = createBucketLoader("srt", "i18n/[locale].srt", { isCacheRestore: false, defaultLocale: "en" }); srtLoader.setDefaultLocale("en"); await srtLoader.pull("en"); @@ -1406,7 +1466,7 @@ Mundo!`; mockFileOperations(input); - const xliffLoader = createBucketLoader("xliff", "i18n/[locale].xliff"); + const xliffLoader = createBucketLoader("xliff", "i18n/[locale].xliff", { isCacheRestore: false, defaultLocale: "en" }); xliffLoader.setDefaultLocale("en"); const data = await xliffLoader.pull("en"); @@ -1482,7 +1542,7 @@ Mundo!`; mockFileOperations(input); - const xliffLoader = createBucketLoader("xliff", "i18n/[locale].xlf"); + const xliffLoader = createBucketLoader("xliff", "i18n/[locale].xlf", { isCacheRestore: false, defaultLocale: "en" }); xliffLoader.setDefaultLocale("en"); await xliffLoader.pull("en"); @@ -1543,18 +1603,19 @@ Mundo!`; setupFileMocks(); const input = "Hello"; - const expectedOutput = "Hola\n"; + const targetInput = "Hola\n"; + const expectedOutput = "Hola (translated)\n"; mockFileOperationsForPaths({ "i18n/en.txt": input, - "i18n/es.txt": "Foo\n", + "i18n/es.txt": targetInput, }); const textFileLoader = createTextFileLoader("i18n/[locale].txt"); textFileLoader.setDefaultLocale("en"); await textFileLoader.pull("en"); - await textFileLoader.push("es", "Hola"); + await textFileLoader.push("es", "Hola (translated)"); expect(fs.writeFile).toHaveBeenCalledWith("i18n/es.txt", expectedOutput, { encoding: "utf-8", flag: "w" }); }); @@ -1563,18 +1624,19 @@ Mundo!`; setupFileMocks(); const input = "Hello\n"; - const expectedOutput = "Hola"; + const targetInput = "Hola"; + const expectedOutput = "Hola (translated)"; mockFileOperationsForPaths({ "i18n/en.txt": input, - "i18n/es.txt": "Foo", + "i18n/es.txt": targetInput, }); const textFileLoader = createTextFileLoader("i18n/[locale].txt"); textFileLoader.setDefaultLocale("en"); await textFileLoader.pull("en"); - await textFileLoader.push("es", "Hola"); + await textFileLoader.push("es", "Hola (translated)"); expect(fs.writeFile).toHaveBeenCalledWith("i18n/es.txt", expectedOutput, { encoding: "utf-8", flag: "w" }); }); @@ -1590,7 +1652,7 @@ Mundo!`; mockFileOperations(input); - const jsonLoader = createBucketLoader("php", "i18n/[locale].php"); + const jsonLoader = createBucketLoader("php", "i18n/[locale].php", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); const data = await jsonLoader.pull("en"); @@ -1624,7 +1686,7 @@ return array( mockFileOperations(input); - const jsonLoader = createBucketLoader("php", "i18n/[locale].php"); + const jsonLoader = createBucketLoader("php", "i18n/[locale].php", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -1646,7 +1708,7 @@ return array( mockFileOperations(input); - const jsonLoader = createBucketLoader("po", "i18n/[locale].po"); + const jsonLoader = createBucketLoader("po", "i18n/[locale].po", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); const data = await jsonLoader.pull("en"); @@ -1661,7 +1723,7 @@ return array( mockFileOperations(input); - const jsonLoader = createBucketLoader("po", "i18n/[locale].po"); + const jsonLoader = createBucketLoader("po", "i18n/[locale].po", { isCacheRestore: false, defaultLocale: "en" }); jsonLoader.setDefaultLocale("en"); await jsonLoader.pull("en"); @@ -1675,9 +1737,7 @@ return array( }); }); -// Helper functions function setupFileMocks() { - // Mock fs/promises vi.mock("fs/promises", () => ({ default: { readFile: vi.fn(), @@ -1687,7 +1747,6 @@ function setupFileMocks() { }, })); - // Mock path vi.mock("path", () => ({ default: { resolve: vi.fn((path) => path), diff --git a/packages/cli/src/cli/loaders/index.ts b/packages/cli/src/cli/loaders/index.ts index 8ae006050..bae80aff7 100644 --- a/packages/cli/src/cli/loaders/index.ts +++ b/packages/cli/src/cli/loaders/index.ts @@ -30,13 +30,14 @@ import createPlutilJsonTextLoader from "./plutil-json-loader"; import createPhpLoader from "./php"; type BucketLoaderOptions = { - isCacheRestore?: boolean; + isCacheRestore: boolean; + defaultLocale: string; }; export default function createBucketLoader( bucketType: Z.infer, bucketPathPattern: string, - { isCacheRestore = false }: BucketLoaderOptions = {}, + options: BucketLoaderOptions, ): ILoader> { switch (bucketType) { default: @@ -47,7 +48,7 @@ export default function createBucketLoader( createAndroidLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "csv": return composeLoaders( @@ -55,7 +56,7 @@ export default function createBucketLoader( createCsvLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "html": return composeLoaders( @@ -63,7 +64,7 @@ export default function createBucketLoader( createPrettierLoader({ parser: "html", alwaysFormat: true }), createHtmlLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "json": return composeLoaders( @@ -72,7 +73,7 @@ export default function createBucketLoader( createJsonLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "markdown": return composeLoaders( @@ -80,7 +81,7 @@ export default function createBucketLoader( createPrettierLoader({ parser: "markdown" }), createMarkdownLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "po": return composeLoaders( @@ -88,7 +89,7 @@ export default function createBucketLoader( createPoLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), createVariableLoader({ type: "python" }), ); case "properties": @@ -96,14 +97,14 @@ export default function createBucketLoader( createTextFileLoader(bucketPathPattern), createPropertiesLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "xcode-strings": return composeLoaders( createTextFileLoader(bucketPathPattern), createXcodeStringsLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "xcode-stringsdict": return composeLoaders( @@ -111,17 +112,17 @@ export default function createBucketLoader( createXcodeStringsdictLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "xcode-xcstrings": return composeLoaders( createTextFileLoader(bucketPathPattern), createPlutilJsonTextLoader(), createJsonLoader(), - createXcodeXcstringsLoader(), + createXcodeXcstringsLoader(options.defaultLocale), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), createVariableLoader({ type: "ieee" }), ); case "yaml": @@ -131,7 +132,7 @@ export default function createBucketLoader( createYamlLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "yaml-root-key": return composeLoaders( @@ -141,7 +142,7 @@ export default function createBucketLoader( createRootKeyLoader(true), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "flutter": return composeLoaders( @@ -151,7 +152,7 @@ export default function createBucketLoader( createFlutterLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "xliff": return composeLoaders( @@ -159,7 +160,7 @@ export default function createBucketLoader( createXliffLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "xml": return composeLoaders( @@ -167,28 +168,28 @@ export default function createBucketLoader( createXmlLoader(), createFlatLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "srt": return composeLoaders( createTextFileLoader(bucketPathPattern), createSrtLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "dato": return composeLoaders( createDatoLoader(bucketPathPattern), createSyncLoader(), createFlatLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "vtt": return composeLoaders( createTextFileLoader(bucketPathPattern), createVttLoader(), createSyncLoader(), - createUnlocalizableLoader(isCacheRestore), + createUnlocalizableLoader(options.isCacheRestore), ); case "php": return composeLoaders( @@ -196,7 +197,7 @@ export default function createBucketLoader( createPhpLoader(), createSyncLoader(), createFlatLoader(), - createUnlocalizableLoader(), + createUnlocalizableLoader(options.isCacheRestore), ); } } diff --git a/packages/cli/src/cli/loaders/xcode-xcstrings.ts b/packages/cli/src/cli/loaders/xcode-xcstrings.ts index 08999e285..ec7484eb6 100644 --- a/packages/cli/src/cli/loaders/xcode-xcstrings.ts +++ b/packages/cli/src/cli/loaders/xcode-xcstrings.ts @@ -2,14 +2,21 @@ import { ILoader } from "./_types"; import { createLoader } from "./_utils"; import _ from "lodash"; -export default function createXcodeXcstringsLoader(): ILoader, Record> { +export default function createXcodeXcstringsLoader(defaultLocale: string): ILoader, Record> { return createLoader({ - async pull(locale, input) { + async pull(locale, input, initCtx) { const resultData: Record = {}; + const isSourceLanguage = locale === defaultLocale; - for (const [translationKey, _translationEntity] of Object.entries(input.strings)) { + for (const [translationKey, _translationEntity] of Object.entries((input as any).strings)) { const rootTranslationEntity = _translationEntity as any; + + if (rootTranslationEntity.shouldTranslate === false) { + continue; + } + const langTranslationEntity = rootTranslationEntity?.localizations?.[locale]; + if (langTranslationEntity) { if ("stringUnit" in langTranslationEntity) { resultData[translationKey] = langTranslationEntity.stringUnit.value; @@ -24,6 +31,12 @@ export default function createXcodeXcstringsLoader(): ILoader 0; + if (hasOtherLocalizations) { + resultData[translationKey] = translationKey; + } } } @@ -32,8 +45,19 @@ export default function createXcodeXcstringsLoader(): ILoader=v18'} hasBin: true + '@commitlint/cli@19.7.1': + resolution: {integrity: sha512-iObGjR1tE/PfDtDTEfd+tnRkB3/HJzpQqRTyofS2MPPkDn1mp3DBC8SoPDayokfAy+xKhF8+bwRCJO25Nea0YQ==} + engines: {node: '>=v18'} + hasBin: true + '@commitlint/config-conventional@19.6.0': resolution: {integrity: sha512-DJT40iMnTYtBtUfw9ApbsLZFke1zKh6llITVJ+x9mtpHD08gsNXaIRqHTmwTZL3dNX5+WoyK7pCN/5zswvkBCQ==} engines: {node: '>=v18'} @@ -451,10 +459,18 @@ packages: resolution: {integrity: sha512-Ov6iBgxJQFR9koOupDPHvcHU9keFupDgtB3lObdEZDroiG4jj1rzky60fbQozFKVYRTUdrBGICHG0YVmRuAJmw==} engines: {node: '>=v18'} + '@commitlint/is-ignored@19.7.1': + resolution: {integrity: sha512-3IaOc6HVg2hAoGleRK3r9vL9zZ3XY0rf1RsUf6jdQLuaD46ZHnXBiOPTyQ004C4IvYjSWqJwlh0/u2P73aIE3g==} + engines: {node: '>=v18'} + '@commitlint/lint@19.6.0': resolution: {integrity: sha512-LRo7zDkXtcIrpco9RnfhOKeg8PAnE3oDDoalnrVU/EVaKHYBWYL1DlRR7+3AWn0JiBqD8yKOfetVxJGdEtZ0tg==} engines: {node: '>=v18'} + '@commitlint/lint@19.7.1': + resolution: {integrity: sha512-LhcPfVjcOcOZA7LEuBBeO00o3MeZa+tWrX9Xyl1r9PMd5FWsEoZI9IgnGqTKZ0lZt5pO3ZlstgnRyY1CJJc9Xg==} + engines: {node: '>=v18'} + '@commitlint/load@19.6.1': resolution: {integrity: sha512-kE4mRKWWNju2QpsCWt428XBvUH55OET2N4QKQ0bF85qS/XbsRGG1MiTByDNlEVpEPceMkDr46LNH95DtRwcsfA==} engines: {node: '>=v18'} @@ -2007,6 +2023,11 @@ packages: resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==} engines: {node: '>= 10'} + commitlint@19.7.1: + resolution: {integrity: sha512-iNWqXl/A1WN8qd9JehqUpzbOxczNBE1nzBiYE33TkHeTptq7Cvg5U4j8PpvO92Nxganv6o/20IO3omP5N5M7/A==} + engines: {node: '>=v18'} + hasBin: true + commondir@1.0.1: resolution: {integrity: sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==} @@ -4691,6 +4712,19 @@ snapshots: - '@types/node' - typescript + '@commitlint/cli@19.7.1(@types/node@22.13.5)(typescript@5.7.2)': + dependencies: + '@commitlint/format': 19.5.0 + '@commitlint/lint': 19.7.1 + '@commitlint/load': 19.6.1(@types/node@22.13.5)(typescript@5.7.2) + '@commitlint/read': 19.5.0 + '@commitlint/types': 19.5.0 + tinyexec: 0.3.1 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - typescript + '@commitlint/config-conventional@19.6.0': dependencies: '@commitlint/types': 19.5.0 @@ -4722,6 +4756,11 @@ snapshots: '@commitlint/types': 19.5.0 semver: 7.6.3 + '@commitlint/is-ignored@19.7.1': + dependencies: + '@commitlint/types': 19.5.0 + semver: 7.6.3 + '@commitlint/lint@19.6.0': dependencies: '@commitlint/is-ignored': 19.6.0 @@ -4729,6 +4768,13 @@ snapshots: '@commitlint/rules': 19.6.0 '@commitlint/types': 19.5.0 + '@commitlint/lint@19.7.1': + dependencies: + '@commitlint/is-ignored': 19.7.1 + '@commitlint/parse': 19.5.0 + '@commitlint/rules': 19.6.0 + '@commitlint/types': 19.5.0 + '@commitlint/load@19.6.1(@types/node@22.13.5)(typescript@5.7.2)': dependencies: '@commitlint/config-validator': 19.5.0 @@ -6370,6 +6416,14 @@ snapshots: commander@7.2.0: {} + commitlint@19.7.1(@types/node@22.13.5)(typescript@5.7.2): + dependencies: + '@commitlint/cli': 19.7.1(@types/node@22.13.5)(typescript@5.7.2) + '@commitlint/types': 19.5.0 + transitivePeerDependencies: + - '@types/node' + - typescript + commondir@1.0.1: {} compare-func@2.0.0: