Skip to content

feat: restrict --lang to zh/en/ja with legacy read fallback#1177

Open
luozhixiong01 wants to merge 5 commits into
mainfrom
feat/lang-restrict-zh-en-ja
Open

feat: restrict --lang to zh/en/ja with legacy read fallback#1177
luozhixiong01 wants to merge 5 commits into
mainfrom
feat/lang-restrict-zh-en-ja

Conversation

@luozhixiong01
Copy link
Copy Markdown
Collaborator

@luozhixiong01 luozhixiong01 commented May 29, 2026

Summary

The --lang flag (used by config init, config bind, profile add) accepted 14 Feishu locales, but CLI internals only ever branch on zh/en/ja (TUI bundle, mail signature locale) — the other 11 were nominally accepted yet had no downstream specialization, leaving the contract wider than the capability. This PR shrinks the accepted set to zh/en/ja (short codes plus canonical zh_cn/en_us/ja_jp). Invalid values are now strictly rejected with an agent-friendly error, and existing stored configs holding a dropped locale (e.g. ko_kr) are silently coerced to zh on read, so no existing config breaks.

Changes

  • Shrink the internal/i18n catalog from 14 to 3 entries; remove the 11 unused LangXxXx constants (internal/i18n/lang.go)
  • Update --lang help text from (e.g. zh or zh_cn) to (zh, en, or ja) at all three sites (cmd/config/init.go, cmd/config/bind.go, cmd/profile/add.go)
  • Coerce unrecognized non-empty legacy values to LangZhCN instead of returning empty in RuntimeContext.Lang() (shortcuts/common/runner.go)
  • Lock the ko/ko_kr rejection contract on all three entry points and flip the read-layer legacy-coerce expectations (cmd/config/*_test.go, cmd/profile/profile_test.go, shortcuts/common/runner_lang_test.go, internal/i18n/lang_test.go)

Test Plan

  • unit tests passed (internal/i18n, cmd/config, cmd/profile, shortcuts/common — run per-package with GOMAXPROCS=2)
  • skipped: full validate.sh deferred to CI — local run hit macOS jetsam OOM killing compile subprocesses (signal: killed); go build/go vet pass locally, affected packages pass individually
  • local-eval passed (E2E 50/50 lang sub-tests green at commit 5d63d1e; skillave N/A — no shortcut/skill change)
  • acceptance-reviewer passed (5/5 cases)
  • manual verification: config init --lang ko exits 2 with invalid --lang "ko"; valid values: zh_cn, en_us, ja_jp and writes no config; --lang zh_cn exits 0 stored as zh_cn; config show on a config holding ko_kr exits 0 with the value preserved verbatim

Related Issues

N/A

Summary by CodeRabbit

  • Documentation

    • Clarified help text to state supported languages are Chinese (zh), English (en), and Japanese (ja).
  • Bug Fixes

    • Validation now rejects unsupported or legacy language codes (e.g., deprecated Korean variants) to prevent ambiguous settings.
  • Tests

    • Expanded tests to cover stricter language validation and fallback behavior across configuration and profile commands.

Review Change Stack

CLI internals only branch on zh/en/ja (TUI bundle, mail signature
locale). The other 11 codes were nominally accepted but had no
downstream specialization, leaving the contract larger than the
capability. Shrink the catalog to match.

i18n.Codes() now returns 3 canonical locales; i18n.Parse() rejects
ko/fr/de/etc. The 11 LangXxXx constants are removed; only the
mail_signature_lang_test fixture referenced one (LangFrFR) and is
switched to an i18n.Lang() literal to preserve the test intent.
After the i18n catalog shrink, ko/ko_kr fall into the strict-reject
path of cmdutil.ParseLangFlag. Pin that with explicit test cases on
all three --lang entry points so future catalog edits can't silently
re-expand the supported set.
Old wording 'e.g. zh or zh_cn' implied a larger supported set than
the new 3-language catalog. Replace the 'e.g.' framing with the
exhaustive list so AI agents and CLI users see the actual contract.
After the 2026-05-28 catalog shrink to zh/en/ja, existing user configs
may still hold ko_kr / fr_fr / etc. RuntimeContext.Lang() now coerces
any non-empty unrecognized value to LangZhCN instead of returning
empty. Storage on disk is untouched — config.json keeps the legacy
value verbatim — so users can still see what was previously set via
'config show', but runtime behavior is uniformly zh.
@github-actions github-actions Bot added domain/mail PR touches the mail domain size/L Large or sensitive change across domains or core paths labels May 29, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3bfd052b-ce3b-453d-b9fa-809327de24cc

📥 Commits

Reviewing files that changed from the base of the PR and between 5d63d1e and 28d37fe.

📒 Files selected for processing (1)
  • internal/i18n/lang_test.go

📝 Walkthrough

Walkthrough

The PR narrows supported locales to zh, en, and ja; updates CLI help text; coerces unrecognized legacy language values to the Chinese fallback at runtime; and extends tests to reject dropped locales like ko/ko_kr.

Changes

Language catalog restriction and validation

Layer / File(s) Summary
Language catalog constants and tests
internal/i18n/lang.go, internal/i18n/lang_test.go
Exported locale constants and the internal catalog are reduced to LangZhCN, LangEnUS, LangJaJP (short codes zh, en, ja). Tests updated to accept ja_jp and assert exact codes ["zh_cn","en_us","ja_jp"], and to reject dropped legacy locales.
CLI flag help text updates
cmd/config/bind.go, cmd/config/init.go, cmd/profile/add.go
--lang flag descriptions changed to list accepted short codes zh, en, ja instead of example-based wording.
Runtime coercion and fallback
shortcuts/common/runner.go, shortcuts/common/runner_lang_test.go, shortcuts/mail/mail_signature_lang_test.go
RuntimeContext.Lang() now: returns "" for empty config, returns parsed canonical locale when recognized, and coerces non-empty unrecognized/legacy values to i18n.LangZhCN. Tests updated to expect coercion and fallback behavior.
Command-level validation tests
cmd/config/bind_test.go, cmd/config/config_test.go, cmd/profile/profile_test.go
Extended tests to assert dropped language codes (ko, ko_kr) are rejected with validation errors across bind, init/config validation, and profile add flows.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • larksuite/cli#1132: Touches the same i18n parsing/--lang validation paths and the shared language catalog, related to catalog/validation behavior changes.

Suggested reviewers

  • GeekyMax
  • liuxinyanglxy
  • MaxHuang22

Poem

🐰 From many tongues we trim to three,
zh, en, ja now bound and free.
Old codes gently mapped to zh,
CLI helps clear what not to be —
A tidy hop toward clarity.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 58.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: restricting the --lang flag to zh/en/ja while adding fallback handling for legacy configs.
Description check ✅ Passed The description fully covers all required template sections with clear summary, detailed changes, comprehensive test plan with verification results, and related issues noted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/lang-restrict-zh-en-ja

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 29, 2026

Codecov Report

❌ Patch coverage is 88.88889% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 68.92%. Comparing base (01fe71d) to head (28d37fe).
⚠️ Report is 13 commits behind head on main.

Files with missing lines Patch % Lines
cmd/profile/add.go 0.00% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1177      +/-   ##
==========================================
+ Coverage   68.71%   68.92%   +0.21%     
==========================================
  Files         627      629       +2     
  Lines       58451    58766     +315     
==========================================
+ Hits        40163    40507     +344     
+ Misses      14999    14952      -47     
- Partials     3289     3307      +18     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 29, 2026

🚀 PR Preview Install Guide

🧰 CLI update

npm i -g https://pkg.pr.new/larksuite/cli/@larksuite/cli@28d37fe0800c2f8dcc556169978c144fc08fd3b9

🧩 Skill update

npx skills add larksuite/cli#feat/lang-restrict-zh-en-ja -y -g

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
internal/i18n/lang_test.go (1)

85-99: ⚡ Quick win

Lock the full Codes() contract, not just count + first entry.

len()==3 plus codes[0]=="zh_cn" still passes if Codes() returns duplicates or silently drops en_us/ja_jp. Since this catalog drives the user-facing ordering contract, assert the exact slice here.

♻️ Suggested test tightening
-import "testing"
+import (
+	"slices"
+	"testing"
+)
...
 func TestCodes(t *testing.T) {
 	codes := Codes()
-	if len(codes) != 3 {
-		t.Fatalf("len(Codes()) = %d, want 3", len(codes))
-	}
-	if codes[0] != "zh_cn" {
-		t.Errorf("Codes()[0] = %q, want %q (catalog order)", codes[0], "zh_cn")
+	want := []string{"zh_cn", "en_us", "ja_jp"}
+	if !slices.Equal(codes, want) {
+		t.Fatalf("Codes() = %v, want %v", codes, want)
 	}
 	// Every code must round-trip through Parse to itself (canonical).
 	for _, c := range codes {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/i18n/lang_test.go` around lines 85 - 99, Replace the weak assertions
in TestCodes with a strict equality check of the full Codes() slice: instead of
checking len(Codes()) and codes[0], assert that Codes() equals the exact
expected slice (e.g. []string{"zh_cn","en_us","ja_jp"}) so duplicates or missing
entries are detected; use the Codes() result and Parse(c) checks as-is, but
remove the separate len/first checks and replace them with a single exact-slice
comparison to lock the contract.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@internal/i18n/lang_test.go`:
- Around line 85-99: Replace the weak assertions in TestCodes with a strict
equality check of the full Codes() slice: instead of checking len(Codes()) and
codes[0], assert that Codes() equals the exact expected slice (e.g.
[]string{"zh_cn","en_us","ja_jp"}) so duplicates or missing entries are
detected; use the Codes() result and Parse(c) checks as-is, but remove the
separate len/first checks and replace them with a single exact-slice comparison
to lock the contract.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9feefaac-1ee2-4cdc-b432-bdf1c5174d05

📥 Commits

Reviewing files that changed from the base of the PR and between d126ea2 and 5d63d1e.

📒 Files selected for processing (11)
  • cmd/config/bind.go
  • cmd/config/bind_test.go
  • cmd/config/config_test.go
  • cmd/config/init.go
  • cmd/profile/add.go
  • cmd/profile/profile_test.go
  • internal/i18n/lang.go
  • internal/i18n/lang_test.go
  • shortcuts/common/runner.go
  • shortcuts/common/runner_lang_test.go
  • shortcuts/mail/mail_signature_lang_test.go

Per review feedback: len==3 + codes[0]==zh_cn still passes if Codes()
returns duplicates or drops en_us/ja_jp. Assert the full ordered slice
to lock the user-facing ordering contract.
@luozhixiong01
Copy link
Copy Markdown
Collaborator Author

@coderabbitai Applied the TestCodes nitpick in 28d37fe — now asserts the exact ordered slice [zh_cn, en_us, ja_jp] via slices.Equal instead of len + first entry, so duplicates or a dropped locale are caught. Thanks.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 29, 2026

Tip

For best results, initiate chat on the files or code changes.

@luozhixiong01 Great improvement! Using slices.Equal with the full ordered slice [zh_cn, en_us, ja_jp] is strictly stronger — it guards against duplicates, ordering changes, and any locale silently slipping back in. Well done.

(🐇 ✨)


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

domain/mail PR touches the mail domain feature size/L Large or sensitive change across domains or core paths

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant