Skip to content

Commit 4cb4fb9

Browse files
committed
fix: I18n and lint error --bug=1
1 parent 35bb2d0 commit 4cb4fb9

8 files changed

Lines changed: 512 additions & 165 deletions

File tree

.golangci.yml

Lines changed: 129 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,83 +1,120 @@
1-
# 完整版本在 https://golangci-lint.run/usage/configuration/
1+
# golangci-lint 配置文件
2+
# 参考文档: https://golangci-lint.run/docs/configuration/file/
3+
version: 2
4+
5+
# 运行配置
6+
run:
7+
# 超时时间
8+
timeout: 20m
9+
# 要分析的目录
10+
# go: 1.18+ 默认使用 ./...
11+
# 跳过目录
12+
skip-dirs:
13+
- vendor
14+
# 跳过文件
15+
skip-files: []
16+
17+
# Linters 配置
218
linters-settings:
3-
funlen:
4-
lines: 80
5-
statements: 80
19+
# goconst: 查找重复的字符串常量
620
goconst:
721
min-len: 2
822
min-occurrences: 2
23+
24+
# gocyclo: 检查函数的圈复杂度
925
gocyclo:
1026
min-complexity: 20
11-
goimports:
12-
#local-prefixes: git.code.oa.com,git.woa.com
13-
revive:
14-
confidence: 0
15-
rules:
16-
- name: var-declaration
17-
- name: package-comments
18-
- name: dot-imports
19-
- name: blank-imports
20-
- name: exported
21-
- name: var-naming
22-
- name: indent-error-flow
23-
- name: range
24-
- name: errorf
25-
- name: error-naming
26-
- name: error-strings
27-
- name: receiver-naming
28-
- name: increment-decrement
29-
- name: error-return
30-
#- name: unexported-return
31-
- name: time-naming
32-
- name: context-keys-type
33-
- name: context-as-argument
34-
- name: filename-format
35-
arguments: ["^[_a-z][_a-z0-9]*\\.go$"]
27+
28+
# govet: Go 官方的 vet 工具
3629
govet:
37-
enable:
38-
- shadow
39-
lll:
40-
line-length: 120
41-
errcheck:
42-
check-type-assertions: true
30+
enable-all: true
31+
disable:
32+
- fieldalignment # 字段对齐优化,可能影响可读性
33+
settings:
34+
shadow:
35+
strict: false
36+
37+
# gocritic: Go 代码审查工具
4338
gocritic:
44-
enabled-checks:
45-
- nestingReduce
39+
enabled-tags:
40+
- diagnostic
41+
- style
42+
- performance
43+
disabled-checks:
44+
- unnamedResult # 允许未命名的返回值
45+
- hugeParam # 大参数检查可能过于严格
4646
settings:
4747
nestingReduce:
4848
bodyWidth: 5
49+
50+
# staticcheck: 静态分析工具
51+
staticcheck:
52+
checks: ["all"]
53+
54+
# unused: 查找未使用的代码
55+
unused:
56+
check-exported: false # 不检查导出的未使用代码
57+
58+
# errcheck: 错误检查配置
59+
errcheck:
60+
# 检查类型断言
61+
check-type-assertions: false
62+
# 检查空白标识符
63+
check-blank: false
64+
# 忽略的函数列表(这些函数的错误返回值可以不检查)
65+
exclude-functions:
66+
- (io.Closer).Close
67+
- (*os.File).Close
68+
- (io.ReadCloser).Close
69+
- (*database/sql.Rows).Close
70+
- (*database/sql.DB).Close
4971

72+
# Linters 启用/禁用配置
5073
linters:
5174
disable-all: true
5275
enable:
53-
- funlen
54-
- goconst
55-
- gocyclo
56-
- gofmt
57-
- ineffassign
58-
- staticcheck
59-
- typecheck
60-
- goimports
61-
- revive
62-
- gosimple
63-
- govet
64-
- lll
65-
- rowserrcheck
66-
# - errcheck
67-
- unused
68-
- sqlclosecheck
69-
- gocritic
70-
# - bodyclose https://github.com/timakin/bodyclose/issues 问题太多了,屏蔽都屏蔽不过来,显式不使用它
71-
72-
run:
73-
timeout: 20m
76+
# 推荐的基础 linters
77+
- govet # Go 官方 vet 工具
78+
- staticcheck # 静态分析(包含 gosimple)
79+
- unused # 未使用代码检查
80+
- ineffassign # 无效赋值检查
81+
82+
# 代码质量
83+
- goconst # 重复字符串检查
84+
- gocyclo # 圈复杂度检查
85+
- gocritic # 代码审查
86+
87+
# SQL 相关
88+
- rowserrcheck # SQL rows.Err() 检查
89+
- sqlclosecheck # SQL Close() 检查
90+
91+
# 其他有用的 linters
92+
- misspell # 拼写检查
93+
- unconvert # 不必要的类型转换
94+
- unparam # 未使用的函数参数
95+
96+
# 明确禁用的 linters(可选,用于文档说明)
97+
disable:
98+
- errcheck # 错误检查过于严格,特别是在测试代码中
99+
- funlen # 函数长度检查过于严格
100+
- lll # 行长度检查过于严格
101+
- revive # 与 staticcheck 重复,且规则过多
102+
- bodyclose # https://github.com/timakin/bodyclose/issues 问题太多
74103

104+
# Issues 配置
75105
issues:
106+
# 使用默认的排除规则
76107
exclude-use-default: true
108+
109+
# 最大问题数配置
110+
max-same-issues: 0
111+
max-issues-per-linter: 0
112+
113+
# 不只显示新问题
114+
new: false
77115

78-
# The list of ids of default excludes to include or disable. By default it's empty.
79-
# 下面的规则,golangci-lint认为应该屏蔽,但是我们选择不屏蔽。所以,`exclude-use-default: true`屏蔽一部分,把下面的再捞出来。
80-
# golanglint-ci维护的忽略列表里有一些是我们不想屏蔽的,捞出来。这里说一下,使用白名单是好于黑名单的。名单随着golanglint-ci引入更多工具,我们跟进享受好处。我们搞黑名单,就变成自己维护,不如golanglint-ci去维护,更好。
116+
# 包含一些默认被排除的规则
117+
# golangci-lint 默认会排除一些规则,但我们希望包含它们
81118
include:
82119
- EXC0004 # govet (possible misuse of unsafe.Pointer|should have signature)
83120
- EXC0005 # staticcheck ineffective break statement. Did you mean to break out of the outer loop
@@ -86,22 +123,45 @@ issues:
86123
- EXC0014 # revive comment on exported (.+) should be of the form "(.+)..."
87124
- EXC0015 # revive should have a package comment, unless it's in another file for this package
88125

126+
# 排除规则
89127
exclude-rules:
128+
# 测试文件排除规则
90129
- path: _test\.go
91130
linters:
92-
- funlen # 规范说单测函数,单个函数可以到160行,但是工具不好做区分处理,这里就直接不检查单测的函数长度
131+
- errcheck # 测试代码中可以不检查所有错误
132+
- gosec # 测试代码安全性要求较低
133+
- unparam # 测试代码中未使用的参数是正常的
134+
- gocyclo # 测试代码可以更复杂
135+
- gocritic # 测试代码不需要过于严格
136+
137+
# 集成测试目录排除规则
138+
- path: tests/integration/
139+
linters:
140+
- errcheck
141+
- gosec
142+
- unparam
143+
- gocyclo
144+
145+
# 允许错误字符串大写(特别是中文错误消息)
93146
- linters:
94147
- staticcheck
95-
text: "SA6002: argument should be pointer-like to avoid allocations" # sync.pool.Put(buf), slice `var buf []byte` will tiger this
148+
text: "ST1005"
149+
150+
# sync.pool 相关优化建议可以忽略
96151
- linters:
97-
- lll
98-
source: "^//go:generate " # Exclude lll issues for long lines with go:generate
99-
100-
max-same-issues: 0
101-
new: false
102-
max-issues-per-linter: 0
152+
- staticcheck
153+
text: "SA6002: argument should be pointer-like to avoid allocations"
154+
155+
# main 函数和 init 函数可以有未使用的参数
156+
- source: "^func (main|init)\\("
157+
linters:
158+
- unparam
103159

160+
# Output 配置
104161
output:
162+
# 按结果排序
105163
sort-results: true
164+
# 输出格式(可选:colored-line-number, line-number, json, tab, checkstyle, code-climate, html, junit-xml, github-actions)
165+
format: colored-line-number
106166

107167

cmd/aicli/init.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ const (
2121

2222
var initCmd = &cobra.Command{
2323
Use: "init",
24-
Short: "初始化配置 / Initialize configuration",
25-
Long: "引导用户设置 LLM 配置并生成配置文件 ~/.aicli.json / Guide user to set up LLM configuration",
24+
Short: "", // 将在 main 中通过 updateCommandDescriptions 设置
25+
Long: "", // 将在 main 中通过 updateCommandDescriptions 设置
2626
RunE: runInit,
2727
}
2828

cmd/aicli/main.go

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ var (
2424
)
2525

2626
func main() {
27+
// 早期初始化i18n(用于--help等不进入run的场景)
28+
// 使用环境变量检测,配置文件会在run中重新初始化
29+
i18n.Init(nil) // nil表示仅使用环境变量和默认值
30+
31+
// 设置自定义 Help 函数,在显示帮助前更新命令描述
32+
// 这样可以确保 Cobra 自动生成的命令(如 completion、help)也能被国际化
33+
originalHelpFunc := rootCmd.HelpFunc()
34+
rootCmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
35+
// 在显示帮助前更新所有命令的描述
36+
updateCommandDescriptions(rootCmd)
37+
originalHelpFunc(cmd, args)
38+
})
39+
40+
// 更新rootCmd描述(第一次,在子命令添加之前)
41+
updateCommandDescriptions(rootCmd)
42+
2743
if err := rootCmd.Execute(); err != nil {
2844
fmt.Fprintf(os.Stderr, "%s: %v\n", i18n.T("label.error"), err)
2945
os.Exit(1)
@@ -191,6 +207,18 @@ func init() {
191207

192208
// 设置版本模板
193209
rootCmd.SetVersionTemplate(`{{printf "aicli version %s\n" .Version}}`)
210+
211+
// 添加 completion 命令(Cobra 不会自动添加,需要手动添加)
212+
rootCmd.AddCommand(createCompletionCmd())
213+
}
214+
215+
// createCompletionCmd 创建 completion 命令
216+
func createCompletionCmd() *cobra.Command {
217+
return &cobra.Command{
218+
Use: "completion",
219+
Short: "", // 将在 updateCommandDescriptions 中设置
220+
Long: "", // 将在 updateCommandDescriptions 中设置
221+
}
194222
}
195223

196224
// getHistoryPath 获取历史记录文件路径
@@ -299,10 +327,28 @@ func retryCommand(id int) error {
299327

300328
// updateCommandDescriptions 更新命令描述为对应语言
301329
func updateCommandDescriptions(cmd *cobra.Command) {
302-
cmd.Use = i18n.T(i18n.CobraUse)
330+
// 更新根命令描述(不更新 Use,因为会导致 Cobra 把它当成子命令)
303331
cmd.Short = i18n.T(i18n.CobraShort)
304332
cmd.Long = i18n.T(i18n.CobraLong)
305333

334+
// 更新子命令描述(包括 Cobra 自动生成的命令)
335+
for _, subCmd := range cmd.Commands() {
336+
switch subCmd.Name() {
337+
case "init":
338+
subCmd.Use = i18n.T(i18n.InitUse)
339+
subCmd.Short = i18n.T(i18n.InitShort)
340+
subCmd.Long = i18n.T(i18n.InitLong)
341+
case "completion":
342+
subCmd.Short = i18n.T(i18n.CompletionShort)
343+
case "help":
344+
subCmd.Short = i18n.T(i18n.HelpShort)
345+
}
346+
// 递归更新子命令的子命令
347+
if subCmd.HasSubCommands() {
348+
updateCommandDescriptions(subCmd)
349+
}
350+
}
351+
306352
// 更新标志说明
307353
if flag := cmd.PersistentFlags().Lookup("config"); flag != nil {
308354
flag.Usage = i18n.T(i18n.CobraFlagConfig)
@@ -325,4 +371,10 @@ func updateCommandDescriptions(cmd *cobra.Command) {
325371
if flag := cmd.Flags().Lookup("retry"); flag != nil {
326372
flag.Usage = i18n.T(i18n.CobraFlagRetry)
327373
}
374+
if flag := cmd.Flags().Lookup("version"); flag != nil {
375+
flag.Usage = i18n.T(i18n.VersionShort)
376+
}
377+
if flag := cmd.Flags().Lookup("help"); flag != nil {
378+
flag.Usage = i18n.T(i18n.HelpFlag)
379+
}
328380
}

0 commit comments

Comments
 (0)