refactor(i18n): fork 引入的命令全面 i18n 化,对齐 upstream 风格

仅改造 fork 自己实现/新增的命令,不动 upstream 本身未 i18n 的包:

- issue/batch_*.go(7文件): newBatchXxxShortcut 接受 tr,所有
  Description/Usage 改 tr.T();新增 batchRuntimeFlags(tr) 共享 helper
  消除 dry-run/confirm/max/delay 重复
- search +issues: 11 个硬编码改 tr.T(),复用 flag.search.keyword/
  flag.page/flag.limit/flag.sort_by/flag.sort_direction
- user headmaps/stats-*/trends: newStatsShortcut 接受 tr,
  Description/Usage 改 tr.T()
- locale: 新增 51 个 key(zh-CN + en-US 双语),清理 10 个孤立死 key
  (batch_list.*/batch.reason/yes 等无对应命令的遗留 key)

全模块测试通过(40 包,0 失败)。
This commit is contained in:
wauxing 2026-06-15 17:28:21 +08:00
parent 31065df31d
commit fbdab04a57
13 changed files with 221 additions and 137 deletions

View File

@ -34,12 +34,15 @@
"cmd.dataset.view.short": "View a repository's dataset",
"cmd.doctor.long": "Run local diagnostics for gitlink-cli configuration, authentication, repository context and API connectivity.",
"cmd.doctor.short": "Diagnose gitlink-cli environment problems",
"cmd.issue.batch_close.long": "Close filtered issues in bulk.\n\nThis command defaults to dry-run mode and only prints matching issues.\nPass --yes to execute remote close operations. Use restrictive filters and a small limit.\n\nExamples:\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20 --yes",
"cmd.issue.batch_close.short": "Close filtered issues in bulk. Defaults to dry-run; pass --yes to execute.",
"cmd.issue.batch_label.long": "Add a label to filtered issues in bulk.\n\nThis command defaults to dry-run mode and only prints matching issues.\nPass --yes to execute remote label operations. The current implementation does not fake label writes when the API endpoint is unavailable.\n\nExamples:\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50 --yes",
"cmd.issue.batch_label.short": "Add a label to filtered issues in bulk. Defaults to dry-run; pass --yes to execute.",
"cmd.issue.batch_list.long": "List issue batch maintenance candidates without changing remote data.\n\nExamples:\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --state open --older-than-days 30 --limit 50 --format table\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --label bug --format json",
"cmd.issue.batch_list.short": "List issue batch maintenance candidates without changing remote data",
"cmd.issue.batch_assign.short": "Assign issues to a user or via CSV",
"cmd.issue.batch_close.long": "Close multiple issues. Pass issue numbers via --numbers or read from a CSV via --from.\n\nDefaults to dry-run; pass --confirm to execute.",
"cmd.issue.batch_close.short": "Close multiple issues by issue numbers or a CSV file",
"cmd.issue.batch_create.short": "Create multiple issues from CSV",
"cmd.issue.batch_delete.short": "Batch delete multiple issues (use with caution)",
"cmd.issue.batch_label.long": "Batch add, remove, or set labels on multiple issues.\n\nDefaults to dry-run; pass --confirm to execute.",
"cmd.issue.batch_label.short": "Add, remove, or set labels on multiple issues",
"cmd.issue.batch_open.short": "Reopen multiple issues",
"cmd.issue.batch_update.short": "Update multiple issues via CSV or --ids",
"cmd.issue.close.short": "Close an issue",
"cmd.issue.comment.short": "Add a comment to an issue",
"cmd.issue.create.short": "Create a new issue",
@ -90,12 +93,19 @@
"cmd.repo.tree.short": "List repository files and directories",
"cmd.root.long": "Manage repositories, issues, pull requests, releases, CI and workflows on GitLink.",
"cmd.root.short": "GitLink CLI - command-line tool for GitLink",
"cmd.search.issues.short": "Search issues in a repository",
"cmd.search.repos.short": "Search repositories",
"cmd.search.short": "Search operations",
"cmd.search.users.short": "Search users",
"cmd.user.headmaps.short": "Show user contribution heatmap",
"cmd.user.info.short": "Show user profile",
"cmd.user.me.short": "Show current authenticated user",
"cmd.user.short": "User operations",
"cmd.user.stats_activity.short": "Show user activity statistics",
"cmd.user.stats_develop.short": "Show user development capability",
"cmd.user.stats_major.short": "Show user major positioning",
"cmd.user.stats_role.short": "Show user role positioning",
"cmd.user.trends.short": "Show user project activity trends",
"cmd.version.short": "Print version information",
"cmd.webhook.create.short": "Create a repository webhook",
"cmd.webhook.delete.short": "Delete a repository webhook",
@ -150,13 +160,36 @@
"flag.issue.assignee": "Assignee login",
"flag.issue.assignee_id": "Assignee user ID",
"flag.issue.author_id": "Author user ID",
"flag.issue.batch.reason": "Optional reason shown in the batch result",
"flag.issue.batch.yes": "Execute remote operations. Without this flag the command is dry-run only.",
"flag.issue.batch_close.older_than_days": "Required safety filter; must be at least 7",
"flag.issue.batch_close.state": "Filter by issue state before closing",
"flag.issue.batch_label.state": "Filter by issue state",
"flag.issue.batch_list.limit": "Maximum issues to return, capped at 100",
"flag.issue.batch_process.limit": "Maximum issues to process, capped at 100",
"flag.issue.batch.confirm": "Confirm batch operation",
"flag.issue.batch.delay": "Delay in milliseconds between requests",
"flag.issue.batch.dry_run": "Preview the issues that would be changed without making any changes",
"flag.issue.batch.from": "Read issue numbers from a CSV file. Supports a number/issue_number/project_issues_index column or first column without header",
"flag.issue.batch.label": "Filter by label name",
"flag.issue.batch.max": "Maximum number of issues to process",
"flag.issue.batch.numbers": "Comma-separated issue numbers from the web URL, for example: 1,2,3",
"flag.issue.batch.search": "Search issues by keyword",
"flag.issue.batch.state": "Filter by state: open, closed, all",
"flag.issue.batch_assign.assignee": "Assignee username or ID (uniform mode)",
"flag.issue.batch_assign.csv": "CSV file with number,assignee columns",
"flag.issue.batch_assign.numbers": "Comma-separated issue numbers",
"flag.issue.batch_close.state": "Filter by state before closing",
"flag.issue.batch_create.csv": "CSV file with issue data",
"flag.issue.batch_create.print_schema": "Print CSV header and exit",
"flag.issue.batch_delete.confirm": "Confirm deletion (required for safety)",
"flag.issue.batch_delete.dry_run": "Preview deletion without executing",
"flag.issue.batch_delete.ids": "Comma-separated issue IDs",
"flag.issue.batch_label.action": "Action: add, remove, or set",
"flag.issue.batch_label.csv": "CSV file path with issue numbers",
"flag.issue.batch_label.label_ids": "Comma-separated label IDs (mutually exclusive with --labels)",
"flag.issue.batch_label.labels": "Comma-separated label names",
"flag.issue.batch_label.numbers": "Comma-separated issue numbers",
"flag.issue.batch_update.assignees": "Comma-separated assignee user IDs",
"flag.issue.batch_update.csv": "CSV file path with updates",
"flag.issue.batch_update.ids": "Comma-separated issue IDs",
"flag.issue.batch_update.milestone": "Milestone ID",
"flag.issue.batch_update.priority": "Priority ID",
"flag.issue.batch_update.status": "New status: open or closed",
"flag.issue.batch_update.tags": "Comma-separated label/tag IDs",
"flag.issue.body": "Issue description",
"flag.issue.label": "Label ID",
"flag.issue.label_filter": "Filter by existing label",
@ -214,6 +247,11 @@
"flag.repo.private": "Make repository private (true/false)",
"flag.repo.tree.path": "Directory path to list (default: repository root)",
"flag.repo.tree.ref": "Branch, tag, or commit ref",
"flag.search.issues.assignee": "Filter by assignee user ID",
"flag.search.issues.author": "Filter by author user ID",
"flag.search.issues.category": "Issue category: all, opened, closed",
"flag.search.issues.milestone": "Filter by milestone ID",
"flag.search.issues.tag": "Filter by tag IDs (comma-separated)",
"flag.search.keyword": "Search keyword",
"flag.sort_by": "Sort field",
"flag.sort_direction": "Sort direction: asc, desc",

View File

@ -34,12 +34,15 @@
"cmd.dataset.view.short": "查看仓库数据集",
"cmd.doctor.long": "诊断 gitlink-cli 的配置、认证、仓库上下文和 API 连通性问题。",
"cmd.doctor.short": "诊断 gitlink-cli 环境问题",
"cmd.issue.batch_close.long": "批量关闭筛选后的议题。\n\n该命令默认处于 dry-run 模式,只打印匹配的议题。\n传入 --yes 后执行远端关闭操作。请使用严格筛选条件和较小 limit。\n\n示例\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20\n gitlink-cli issue +batch-close --owner Gitlink --repo gitlink-cli --older-than-days 60 --limit 20 --yes",
"cmd.issue.batch_close.short": "批量关闭筛选后的议题。默认 dry-run传入 --yes 后执行。",
"cmd.issue.batch_label.long": "给筛选后的议题批量添加标签。\n\n该命令默认处于 dry-run 模式,只打印匹配的议题。\n传入 --yes 后执行远端标签操作。当前实现不会在 API 端点不可用时伪造写入结果。\n\n示例\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50\n gitlink-cli issue +batch-label --owner Gitlink --repo gitlink-cli --add-label stale --older-than-days 30 --limit 50 --yes",
"cmd.issue.batch_label.short": "给筛选后的议题批量添加标签。默认 dry-run传入 --yes 后执行。",
"cmd.issue.batch_list.long": "列出议题批量维护候选项,不修改远端数据。\n\n示例\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --state open --older-than-days 30 --limit 50 --format table\n gitlink-cli issue +batch-list --owner Gitlink --repo gitlink-cli --label bug --format json",
"cmd.issue.batch_list.short": "列出议题批量维护候选项,不修改远端数据",
"cmd.issue.batch_assign.short": "批量指派议题负责人",
"cmd.issue.batch_close.long": "批量关闭多个议题。支持 --numbers 直接传入编号,或 --from 从 CSV 读取。\n\n默认 dry-run传入 --confirm 后执行。",
"cmd.issue.batch_close.short": "批量关闭多个议题(按编号或 CSV",
"cmd.issue.batch_create.short": "从 CSV 批量创建议题",
"cmd.issue.batch_delete.short": "批量删除多个议题(谨慎使用)",
"cmd.issue.batch_label.long": "批量给多个议题添加、移除或设置标签。\n\n默认 dry-run传入 --confirm 后执行。",
"cmd.issue.batch_label.short": "批量管理议题标签(添加/移除/设置)",
"cmd.issue.batch_open.short": "批量重新打开多个议题",
"cmd.issue.batch_update.short": "批量更新议题(按 CSV 或 ID",
"cmd.issue.close.short": "关闭议题",
"cmd.issue.comment.short": "给议题添加评论",
"cmd.issue.create.short": "创建新议题",
@ -90,12 +93,19 @@
"cmd.repo.tree.short": "列出仓库文件和目录",
"cmd.root.long": "用于管理 GitLink 上的仓库、议题、拉取请求、发布、CI 和工作流。",
"cmd.root.short": "GitLink CLI - GitLink 命令行工具",
"cmd.search.issues.short": "搜索仓库议题",
"cmd.search.repos.short": "搜索仓库",
"cmd.search.short": "搜索操作",
"cmd.search.users.short": "搜索用户",
"cmd.user.headmaps.short": "显示用户贡献热力图",
"cmd.user.info.short": "显示用户资料",
"cmd.user.me.short": "显示当前认证用户",
"cmd.user.short": "用户操作",
"cmd.user.stats_activity.short": "显示用户活动统计",
"cmd.user.stats_develop.short": "显示用户开发能力",
"cmd.user.stats_major.short": "显示用户专业/学科定位",
"cmd.user.stats_role.short": "显示用户角色定位",
"cmd.user.trends.short": "显示用户项目活动趋势",
"cmd.version.short": "打印版本信息",
"cmd.webhook.create.short": "创建仓库 Webhook",
"cmd.webhook.delete.short": "删除仓库 Webhook",
@ -150,13 +160,36 @@
"flag.issue.assignee": "负责人登录名",
"flag.issue.assignee_id": "负责人用户 ID",
"flag.issue.author_id": "作者用户 ID",
"flag.issue.batch.reason": "批量结果中显示的可选原因",
"flag.issue.batch.yes": "执行远端操作。未传入该参数时仅 dry-run。",
"flag.issue.batch_close.older_than_days": "必需的安全筛选条件;至少为 7",
"flag.issue.batch.confirm": "确认执行批量操作",
"flag.issue.batch.delay": "请求间隔(毫秒)",
"flag.issue.batch.dry_run": "预览将被修改的议题,不实际执行",
"flag.issue.batch.from": "从 CSV 文件读取议题编号(支持 number/issue_number/project_issues_index 列)",
"flag.issue.batch.label": "按标签名筛选",
"flag.issue.batch.max": "最多处理的议题数",
"flag.issue.batch.numbers": "议题编号列表(逗号分隔),例如 1,2,3",
"flag.issue.batch.search": "按关键词搜索议题",
"flag.issue.batch.state": "按状态筛选open、closed、all",
"flag.issue.batch_assign.assignee": "负责人用户名或 ID统一模式",
"flag.issue.batch_assign.csv": "CSV 文件(含 number,assignee 列)",
"flag.issue.batch_assign.numbers": "议题编号列表(逗号分隔)",
"flag.issue.batch_close.state": "关闭前按议题状态筛选",
"flag.issue.batch_label.state": "按议题状态筛选",
"flag.issue.batch_list.limit": "最多返回的议题数,上限 100",
"flag.issue.batch_process.limit": "最多处理的议题数,上限 100",
"flag.issue.batch_create.csv": "含议题数据的 CSV 文件",
"flag.issue.batch_create.print_schema": "打印 CSV 表头并退出",
"flag.issue.batch_delete.confirm": "确认删除(安全必需)",
"flag.issue.batch_delete.dry_run": "预览删除,不实际执行",
"flag.issue.batch_delete.ids": "议题 ID 列表(逗号分隔)",
"flag.issue.batch_label.action": "操作类型add、remove 或 set",
"flag.issue.batch_label.csv": "含议题编号的 CSV 文件路径",
"flag.issue.batch_label.label_ids": "标签 ID 列表(逗号分隔,与 --labels 互斥)",
"flag.issue.batch_label.labels": "标签名列表(逗号分隔)",
"flag.issue.batch_label.numbers": "议题编号列表(逗号分隔)",
"flag.issue.batch_update.assignees": "负责人用户 ID 列表(逗号分隔)",
"flag.issue.batch_update.csv": "含更新数据的 CSV 文件路径",
"flag.issue.batch_update.ids": "议题 ID 列表(逗号分隔)",
"flag.issue.batch_update.milestone": "里程碑 ID",
"flag.issue.batch_update.priority": "优先级 ID",
"flag.issue.batch_update.status": "新状态open 或 closed",
"flag.issue.batch_update.tags": "标签/标记 ID 列表(逗号分隔)",
"flag.issue.body": "议题描述",
"flag.issue.label": "标签 ID",
"flag.issue.label_filter": "按已有标签筛选",
@ -214,6 +247,11 @@
"flag.repo.private": "设为私有仓库true/false",
"flag.repo.tree.path": "要列出的目录路径(默认:仓库根目录)",
"flag.repo.tree.ref": "分支、标签或提交引用",
"flag.search.issues.assignee": "按负责人用户 ID 筛选",
"flag.search.issues.author": "按作者用户 ID 筛选",
"flag.search.issues.category": "议题分类all、opened、closed",
"flag.search.issues.milestone": "按里程碑 ID 筛选",
"flag.search.issues.tag": "按标签 ID 筛选(逗号分隔)",
"flag.search.keyword": "搜索关键词",
"flag.sort_by": "排序字段",
"flag.sort_direction": "排序方向asc、desc",

View File

@ -1,16 +1,17 @@
package issue
import (
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
const closeIssueStatusID = 5
func newBatchCloseShortcut() *common.Shortcut {
func newBatchCloseShortcut(tr *i18n.Translator) *common.Shortcut {
return &common.Shortcut{
Name: "batch-close",
Description: "Close multiple issues by issue numbers or a CSV file",
Flags: batchStateFlags(),
Description: tr.T("cmd.issue.batch_close.short"),
Flags: batchStateFlags(tr),
Run: func(ctx *common.RuntimeContext) error { return runBatchStateChange(ctx, "close", closeIssueStatusID) },
}
}

View File

@ -3,28 +3,26 @@ package issue
import (
"fmt"
"os"
"strconv"
"strings"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
func newBatchAssignShortcut() *common.Shortcut {
func newBatchAssignShortcut(tr *i18n.Translator) *common.Shortcut {
flags := []common.Flag{
{Name: "numbers", Short: "n", Usage: tr.T("flag.issue.batch_assign.numbers")},
{Name: "from", Usage: tr.T("flag.issue.batch_assign.csv")},
{Name: "search", Usage: tr.T("flag.issue.batch.search")},
{Name: "state", Usage: tr.T("flag.issue.batch.state")},
{Name: "assignee", Short: "a", Usage: tr.T("flag.issue.batch_assign.assignee")},
}
flags = append(flags, batchRuntimeFlags(tr)...)
return &common.Shortcut{
Name: "batch-assign",
Description: "Assign issues to a user or via CSV",
Flags: []common.Flag{
{Name: "numbers", Short: "n", Usage: "Comma-separated issue numbers"},
{Name: "from", Usage: "CSV file with number,assignee columns"},
{Name: "search", Usage: "Search keyword"},
{Name: "state", Usage: "State filter for --search"},
{Name: "assignee", Short: "a", Usage: "Assignee username or ID (uniform mode)"},
{Name: "dry-run", Usage: "Preview", Bool: true, Default: "false"},
{Name: "confirm", Usage: "Confirm", Bool: true, Default: "false"},
{Name: "max", Usage: "Max items", Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: "Delay ms", Default: strconv.Itoa(defaultBatchDelayMs)},
},
Run: runBatchAssign,
Description: tr.T("cmd.issue.batch_assign.short"),
Flags: flags,
Run: runBatchAssign,
}
}

View File

@ -11,6 +11,7 @@ import (
"sync"
"time"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
@ -39,17 +40,27 @@ func parseBatchOptions(ctx *common.RuntimeContext) BatchOptions {
}
// batchStateFlags 返回 batch 状态变更命令close、open共用的 flag 列表。
func batchStateFlags() []common.Flag {
func batchStateFlags(tr *i18n.Translator) []common.Flag {
return []common.Flag{
{Name: "numbers", Short: "n", Usage: "Comma-separated issue numbers from the web URL, for example: 1,2,3"},
{Name: "from", Usage: "Read issue numbers from a CSV file. Supports a number/issue_number/project_issues_index column or first column without header"},
{Name: "search", Usage: "Search issues by keyword"},
{Name: "state", Usage: "Filter by state: open, closed, all"},
{Name: "label", Usage: "Filter by label name"},
{Name: "confirm", Usage: "Confirm batch operation", Bool: true, Default: "false"},
{Name: "max", Usage: "Maximum number of issues to process", Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: "Delay in milliseconds between requests", Default: strconv.Itoa(defaultBatchDelayMs)},
{Name: "dry-run", Usage: "Preview the issues that would be changed without making any changes", Bool: true, Default: "false"},
{Name: "numbers", Short: "n", Usage: tr.T("flag.issue.batch.numbers")},
{Name: "from", Usage: tr.T("flag.issue.batch.from")},
{Name: "search", Usage: tr.T("flag.issue.batch.search")},
{Name: "state", Usage: tr.T("flag.issue.batch.state")},
{Name: "label", Usage: tr.T("flag.issue.batch.label")},
{Name: "confirm", Usage: tr.T("flag.issue.batch.confirm"), Bool: true, Default: "false"},
{Name: "max", Usage: tr.T("flag.issue.batch.max"), Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: tr.T("flag.issue.batch.delay"), Default: strconv.Itoa(defaultBatchDelayMs)},
{Name: "dry-run", Usage: tr.T("flag.issue.batch.dry_run"), Bool: true, Default: "false"},
}
}
// batchRuntimeFlags 返回各 batch 命令共用的运行时 flagdry-run/confirm/max/delay
func batchRuntimeFlags(tr *i18n.Translator) []common.Flag {
return []common.Flag{
{Name: "dry-run", Usage: tr.T("flag.issue.batch.dry_run"), Bool: true, Default: "false"},
{Name: "confirm", Usage: tr.T("flag.issue.batch.confirm"), Bool: true, Default: "false"},
{Name: "max", Usage: tr.T("flag.issue.batch.max"), Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: tr.T("flag.issue.batch.delay"), Default: strconv.Itoa(defaultBatchDelayMs)},
}
}

View File

@ -7,22 +7,21 @@ import (
"strings"
"time"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
func newBatchCreateShortcut() *common.Shortcut {
func newBatchCreateShortcut(tr *i18n.Translator) *common.Shortcut {
flags := []common.Flag{
{Name: "from", Short: "f", Usage: tr.T("flag.issue.batch_create.csv"), Required: true},
{Name: "print-schema", Usage: tr.T("flag.issue.batch_create.print_schema"), Bool: true, Default: "false"},
}
flags = append(flags, batchRuntimeFlags(tr)...)
return &common.Shortcut{
Name: "batch-create",
Description: "Create multiple issues from CSV",
Flags: []common.Flag{
{Name: "from", Short: "f", Usage: "CSV file with issue data", Required: true},
{Name: "print-schema", Usage: "Print CSV header and exit", Bool: true, Default: "false"},
{Name: "dry-run", Usage: "Preview", Bool: true, Default: "false"},
{Name: "confirm", Usage: "Confirm", Bool: true, Default: "false"},
{Name: "max", Usage: "Max items", Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: "Delay ms", Default: strconv.Itoa(defaultBatchDelayMs)},
},
Run: runBatchCreate,
Description: tr.T("cmd.issue.batch_create.short"),
Flags: flags,
Run: runBatchCreate,
}
}

View File

@ -5,17 +5,18 @@ import (
"strconv"
"strings"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
func newBatchDeleteShortcut() *common.Shortcut {
func newBatchDeleteShortcut(tr *i18n.Translator) *common.Shortcut {
return &common.Shortcut{
Name: "batch-delete",
Description: "Batch delete multiple issues (use with caution)",
Description: tr.T("cmd.issue.batch_delete.short"),
Flags: []common.Flag{
{Name: "ids", Short: "i", Usage: "Comma-separated issue IDs", Required: true},
{Name: "dry-run", Usage: "Preview deletion without executing", Bool: true, Default: "false"},
{Name: "confirm", Usage: "Confirm deletion (required for safety)", Bool: true, Default: "false"},
{Name: "ids", Short: "i", Usage: tr.T("flag.issue.batch_delete.ids"), Required: true},
{Name: "dry-run", Usage: tr.T("flag.issue.batch_delete.dry_run"), Bool: true, Default: "false"},
{Name: "confirm", Usage: tr.T("flag.issue.batch_delete.confirm"), Bool: true, Default: "false"},
},
Run: runBatchDelete,
}

View File

@ -5,27 +5,26 @@ import (
"strconv"
"strings"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
func newBatchLabelShortcut() *common.Shortcut {
func newBatchLabelShortcut(tr *i18n.Translator) *common.Shortcut {
flags := []common.Flag{
{Name: "numbers", Short: "n", Usage: tr.T("flag.issue.batch_label.numbers")},
{Name: "from", Usage: tr.T("flag.issue.batch_label.csv")},
{Name: "search", Usage: tr.T("flag.issue.batch.search")},
{Name: "state", Usage: tr.T("flag.issue.batch.state")},
{Name: "action", Short: "a", Usage: tr.T("flag.issue.batch_label.action"), Required: true},
{Name: "labels", Short: "l", Usage: tr.T("flag.issue.batch_label.labels")},
{Name: "label-ids", Usage: tr.T("flag.issue.batch_label.label_ids")},
}
flags = append(flags, batchRuntimeFlags(tr)...)
return &common.Shortcut{
Name: "batch-label",
Description: "Add, remove, or set labels on multiple issues",
Flags: []common.Flag{
{Name: "numbers", Short: "n", Usage: "Comma-separated issue numbers"},
{Name: "from", Usage: "CSV file path with issue numbers"},
{Name: "search", Usage: "Search keyword"},
{Name: "state", Usage: "State filter for --search"},
{Name: "action", Short: "a", Usage: "Action: add, remove, or set", Required: true},
{Name: "labels", Short: "l", Usage: "Comma-separated label names"},
{Name: "label-ids", Usage: "Comma-separated label IDs (mutually exclusive with --labels)"},
{Name: "dry-run", Usage: "Preview", Bool: true, Default: "false"},
{Name: "confirm", Usage: "Confirm", Bool: true, Default: "false"},
{Name: "max", Usage: "Max items", Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: "Delay ms", Default: strconv.Itoa(defaultBatchDelayMs)},
},
Run: runBatchLabel,
Description: tr.T("cmd.issue.batch_label.short"),
Flags: flags,
Run: runBatchLabel,
}
}

View File

@ -1,16 +1,17 @@
package issue
import (
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
const openIssueStatusID = 1
func newBatchOpenShortcut() *common.Shortcut {
func newBatchOpenShortcut(tr *i18n.Translator) *common.Shortcut {
return &common.Shortcut{
Name: "batch-open",
Description: "Reopen multiple issues",
Flags: batchStateFlags(),
Description: tr.T("cmd.issue.batch_open.short"),
Flags: batchStateFlags(tr),
Run: func(ctx *common.RuntimeContext) error { return runBatchStateChange(ctx, "open", openIssueStatusID) },
}
}

View File

@ -6,6 +6,7 @@ import (
"strconv"
"strings"
"github.com/gitlink-org/gitlink-cli/internal/i18n"
"github.com/gitlink-org/gitlink-cli/shortcuts/common"
)
@ -19,27 +20,24 @@ var updateFieldMapping = map[string]string{
"priority": "priority_id",
}
func newBatchUpdateShortcut() *common.Shortcut {
func newBatchUpdateShortcut(tr *i18n.Translator) *common.Shortcut {
flags := []common.Flag{
// --ids 统一模式参数
{Name: "ids", Short: "i", Usage: tr.T("flag.issue.batch_update.ids"), Required: false},
{Name: "status", Short: "s", Usage: tr.T("flag.issue.batch_update.status")},
{Name: "priority", Short: "p", Usage: tr.T("flag.issue.batch_update.priority")},
{Name: "milestone", Short: "m", Usage: tr.T("flag.issue.batch_update.milestone")},
{Name: "labels", Short: "l", Usage: tr.T("flag.issue.batch_update.tags")},
{Name: "assignees", Short: "a", Usage: tr.T("flag.issue.batch_update.assignees")},
// CSV 模式参数
{Name: "from", Usage: tr.T("flag.issue.batch_update.csv")},
}
flags = append(flags, batchRuntimeFlags(tr)...)
return &common.Shortcut{
Name: "batch-update",
Description: "Update multiple issues via CSV or --ids",
Flags: []common.Flag{
// --ids 统一模式参数
{Name: "ids", Short: "i", Usage: "Comma-separated issue IDs", Required: false},
{Name: "status", Short: "s", Usage: "New status: open or closed"},
{Name: "priority", Short: "p", Usage: "Priority ID"},
{Name: "milestone", Short: "m", Usage: "Milestone ID"},
{Name: "labels", Short: "l", Usage: "Comma-separated label/tag IDs"},
{Name: "assignees", Short: "a", Usage: "Comma-separated assignee user IDs"},
// CSV 模式参数
{Name: "from", Usage: "CSV file path with updates"},
// 共享参数
{Name: "dry-run", Usage: "Preview", Bool: true, Default: "false"},
{Name: "confirm", Usage: "Confirm", Bool: true, Default: "false"},
{Name: "max", Usage: "Max items", Default: strconv.Itoa(defaultBatchMaxItems)},
{Name: "delay", Usage: "Delay ms", Default: strconv.Itoa(defaultBatchDelayMs)},
},
Run: runBatchUpdate,
Description: tr.T("cmd.issue.batch_update.short"),
Flags: flags,
Run: runBatchUpdate,
}
}

View File

@ -51,13 +51,13 @@ func normalizeIssueListState(state string) string {
func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
tr := shortcutTranslator(translators...)
return []*common.Shortcut{
newBatchCreateShortcut(),
newBatchCloseShortcut(),
newBatchOpenShortcut(),
newBatchAssignShortcut(),
newBatchLabelShortcut(),
newBatchUpdateShortcut(),
newBatchDeleteShortcut(),
newBatchCreateShortcut(tr),
newBatchCloseShortcut(tr),
newBatchOpenShortcut(tr),
newBatchAssignShortcut(tr),
newBatchLabelShortcut(tr),
newBatchUpdateShortcut(tr),
newBatchDeleteShortcut(tr),
{
Name: "list",
Description: tr.T("cmd.issue.list.short"),

View File

@ -55,18 +55,18 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
},
{
Name: "issues",
Description: "Search issues in a repository",
Description: tr.T("cmd.search.issues.short"),
Flags: []common.Flag{
{Name: "keyword", Short: "k", Usage: "Search keyword", Required: true},
{Name: "category", Short: "c", Usage: "Issue category: all, opened, closed", Default: "all"},
{Name: "assignee", Short: "a", Usage: "Filter by assignee user ID"},
{Name: "author", Usage: "Filter by author user ID"},
{Name: "milestone", Short: "m", Usage: "Filter by milestone ID"},
{Name: "tag", Short: "t", Usage: "Filter by tag IDs (comma-separated)"},
{Name: "sort-by", Usage: "Sort field: updated_on, created_on, priority", Default: "updated_on"},
{Name: "sort-dir", Usage: "Sort direction: asc, desc", Default: "desc"},
{Name: "page", Short: "p", Usage: "Page number", Default: "1"},
{Name: "limit", Short: "l", Usage: "Items per page", Default: "20"},
{Name: "keyword", Short: "k", Usage: tr.T("flag.search.keyword"), Required: true},
{Name: "category", Short: "c", Usage: tr.T("flag.search.issues.category"), Default: "all"},
{Name: "assignee", Short: "a", Usage: tr.T("flag.search.issues.assignee")},
{Name: "author", Usage: tr.T("flag.search.issues.author")},
{Name: "milestone", Short: "m", Usage: tr.T("flag.search.issues.milestone")},
{Name: "tag", Short: "t", Usage: tr.T("flag.search.issues.tag")},
{Name: "sort-by", Usage: tr.T("flag.sort_by"), Default: "updated_on"},
{Name: "sort-dir", Usage: tr.T("flag.sort_direction"), Default: "desc"},
{Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"},
{Name: "limit", Short: "l", Usage: tr.T("flag.limit"), Default: "20"},
},
Run: func(ctx *common.RuntimeContext) error {
if err := ctx.ResolveOwnerRepo(); err != nil {

View File

@ -42,9 +42,9 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
},
{
Name: "headmaps",
Description: "Show user contribution heatmap",
Description: tr.T("cmd.user.headmaps.short"),
Flags: []common.Flag{
{Name: "login", Short: "l", Usage: "User login name", Required: true},
{Name: "login", Short: "l", Usage: tr.T("flag.user.login"), Required: true},
},
Run: func(ctx *common.RuntimeContext) error {
login, err := ctx.RequireArg("login")
@ -58,17 +58,17 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
return ctx.Output(env)
},
},
newStatsShortcut("stats-activity", "Show user activity statistics", "activity"),
newStatsShortcut("stats-develop", "Show user development capability", "develop"),
newStatsShortcut("stats-role", "Show user role positioning", "role"),
newStatsShortcut("stats-major", "Show user major positioning", "major"),
newStatsShortcut(tr, "stats-activity", tr.T("cmd.user.stats_activity.short"), "activity"),
newStatsShortcut(tr, "stats-develop", tr.T("cmd.user.stats_develop.short"), "develop"),
newStatsShortcut(tr, "stats-role", tr.T("cmd.user.stats_role.short"), "role"),
newStatsShortcut(tr, "stats-major", tr.T("cmd.user.stats_major.short"), "major"),
{
Name: "trends",
Description: "Show user project activity trends",
Description: tr.T("cmd.user.trends.short"),
Flags: []common.Flag{
{Name: "login", Short: "l", Usage: "User login name", Required: true},
{Name: "page", Short: "p", Usage: "Page number", Default: "1"},
{Name: "limit", Usage: "Items per page", Default: "20"},
{Name: "login", Short: "l", Usage: tr.T("flag.user.login"), Required: true},
{Name: "page", Short: "p", Usage: tr.T("flag.page"), Default: "1"},
{Name: "limit", Usage: tr.T("flag.limit"), Default: "20"},
},
Run: func(ctx *common.RuntimeContext) error {
login, err := ctx.RequireArg("login")
@ -89,12 +89,12 @@ func Shortcuts(translators ...*i18n.Translator) []*common.Shortcut {
}
// newStatsShortcut 生成用户统计类 shortcut消除 stats-activity/develop/role/major 的重复代码。
func newStatsShortcut(name, desc, subPath string) *common.Shortcut {
func newStatsShortcut(tr *i18n.Translator, name, desc, subPath string) *common.Shortcut {
return &common.Shortcut{
Name: name,
Description: desc,
Flags: []common.Flag{
{Name: "login", Short: "l", Usage: "User login name", Required: true},
{Name: "login", Short: "l", Usage: tr.T("flag.user.login"), Required: true},
},
Run: func(ctx *common.RuntimeContext) error {
login, err := ctx.RequireArg("login")