feat(i18n): l10n codegen — strings.json 单源生成 6 份 strings_*.dart

② 单源 codegen 落地:
- strings.json 补全 lists 段(days7/featsFree/featsPro/featsTeam),
  之前 extraction 漏了 4 个 List<String> getter;现 246 getter+4 list+5 method×6 语。
- design/codegen/gen_l10n_dart.mjs:strings.json → strings_{zh,en,ja,ko,ru,es}.dart,
  getter 转义 \$、method 保留 $var 插值,dart format 定型(保证漂移闸零 diff)。
- app_text.dart 保持手写(enum/abstract 声明/AppLangMisc 逻辑),编译器强制 concrete⊆abstract 兜底。
- 往返无损:生成的 Dart 重新抽取 == strings.json 逐字节一致;flutter analyze 0 issue、flutter test 244 全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01A79VtQA1BwTuQN1ThpvYpo
This commit is contained in:
wangjia
2026-07-27 08:47:44 +08:00
parent 9ab550d398
commit f76e3cdffd
9 changed files with 662 additions and 372 deletions
+45 -52
View File
@@ -1,8 +1,7 @@
// strings_ja.dart — 日本語の文言リソース(単一言語表示)
// strings_ja.dart — 日本語文案(自动生成 · 勿手改)
//
// 禁止ワード: 検閲回避・センシティブな表現。一覧は design/CLAUDE.md §1 ルール13を参照。
// ポジショニング: ネットワーク高速化 / 体験最適化 + プライバシー
// プラン番号は design/CLAUDE.md §7 に準拠。
// GENERATED by design/codegen/gen_l10n_dart.mjs from design/i18n/strings.json.
// 改文案:改 strings.json 后重跑 codegen;新增 key 需同步 app_text.dart 抽象声明
import 'app_text.dart';
class StringsJa extends AppText {
@@ -27,7 +26,6 @@ class StringsJa extends AppText {
String get connectNow => '接続';
@override
String get secure => 'セキュア';
@override
String get tabConnect => '接続';
@override
@@ -36,7 +34,6 @@ class StringsJa extends AppText {
String get tabStats => '統計';
@override
String get tabMe => 'アカウント';
@override
String get currentNode => '現在のノード';
@override
@@ -45,7 +42,6 @@ class StringsJa extends AppText {
String get upload => '上り';
@override
String get latency => 'Ping';
@override
String get quotaToday => '本日の残り';
@override
@@ -69,16 +65,14 @@ class StringsJa extends AppText {
@override
String get adPlaying => '広告を再生中…';
@override
String adRewarded(int minutes) => '+$minutes 分を追加しました';
@override
String get adFailed => '時間の追加に失敗しました。もう一度お試しください';
@override
String get quotaDesktopTitle => '本日の無料時間を使い切りました';
@override
String get quotaDesktopBody => 'モバイルアプリで広告を見ると時間を追加できます。無制限に使うにはアップグレードしてください。';
String get quotaDesktopBody =>
'モバイルアプリで広告を見ると時間を追加できます。無制限に使うにはアップグレードしてください。';
@override
String get gotIt => '了解';
@override
String get chooseNode => 'サーバーを選択';
@override
@@ -86,8 +80,6 @@ class StringsJa extends AppText {
@override
String get smartSelect => 'スマート選択';
@override
String nodeSwitchTitle(String name) => '$name に切り替えますか?';
@override
String get nodeSwitchBody => '現在の接続を切断し、このノードに再接続します。';
@override
String get nodeSwitchConfirm => '切り替える';
@@ -101,7 +93,6 @@ class StringsJa extends AppText {
String get smartSub => 'お使いのネットワークに最適なノードを選びます';
@override
String get recommended => 'おすすめ';
@override
String get statsTitle => '統計';
@override
@@ -113,8 +104,6 @@ class StringsJa extends AppText {
@override
String get weekTraffic => '今週 (GB)';
@override
List<String> get days7 => const ['', '', '', '', '', '', ''];
@override
String get byDevice => 'デバイス別';
@override
String get noDeviceUsage => 'デバイスの利用履歴はまだありません';
@@ -134,7 +123,6 @@ class StringsJa extends AppText {
String get chartTwoWeeks => '過去2週間';
@override
String get allDevices => 'すべてのデバイス';
@override
String get meTitle => 'アカウント';
@override
@@ -186,15 +174,18 @@ class StringsJa extends AppText {
@override
String get devSave => '保存';
@override
String get devForceLogoutConfirm => 'このデバイスのログインセッションを無効にします。オフラインになり、再度サインインが必要になります。デバイスはリストに残ります。';
String get devForceLogoutConfirm =>
'このデバイスのログインセッションを無効にします。オフラインになり、再度サインインが必要になります。デバイスはリストに残ります。';
@override
String get devClearLoginConfirm => 'このデバイスをリストから完全に削除し、ログインセッションとデータ通信の認証情報を無効にします。再び利用するには、もう一度サインインが必要です。';
String get devClearLoginConfirm =>
'このデバイスをリストから完全に削除し、ログインセッションとデータ通信の認証情報を無効にします。再び利用するには、もう一度サインインが必要です。';
@override
String get devCancel => 'キャンセル';
@override
String get sessionRevokedTitle => 'このデバイスはサインアウトされました';
@override
String get sessionRevokedBody => '別のデバイスから、このデバイスがサインアウトされました。もう一度サインインしてください。';
String get sessionRevokedBody =>
'別のデバイスから、このデバイスがサインアウトされました。もう一度サインインしてください。';
@override
String get sessionRevokedOk => '再度サインイン';
@override
@@ -224,8 +215,6 @@ class StringsJa extends AppText {
@override
String get autoConnectSub => '起動時に自動的に接続';
@override
String autoConnectingTo(String name) => '$name に自動接続中…';
@override
String get smartRoute => 'スマートルーティング';
@override
String get smartRouteSub => '海外は高速化、国内は直接接続';
@@ -238,8 +227,6 @@ class StringsJa extends AppText {
@override
String get webUserCenter => 'ユーザーセンター (Web)';
@override
String updateAvailableTitle(String version) => '新しいバージョン v$version が利用可能です';
@override
String get updateNotesFallback => 'このアップデートには不具合の修正と安定性の向上が含まれています。';
@override
String get updateLater => '後で';
@@ -249,7 +236,6 @@ class StringsJa extends AppText {
String get updateUpToDate => '最新の状態です';
@override
String get updateCheckFailed => 'アップデートの確認に失敗しました。後でもう一度お試しください';
@override
String get freePlan => '無料';
@override
@@ -266,20 +252,6 @@ class StringsJa extends AppText {
String get choose => '選択';
@override
String get mostPopular => '人気';
@override
List<String> get featsFree => const [
'基本ノード1つのみ',
'1日10分',
'広告を見て開始',
'登録で7日間無料トライアル',
];
@override
List<String> get featsPro =>
const ['80以上の拠点', '無制限 · 高速', '5台のデバイス', 'ストリーミング最適化'];
@override
List<String> get featsTeam =>
const ['Proのすべての機能', '10ライセンス', '一括請求', '優先サポート'];
@override
String get redeemTitle => 'コード引き換え・購入';
@override
@@ -298,12 +270,10 @@ class StringsJa extends AppText {
String get chStore => 'セルフサービスストア';
@override
String get chEmail => 'メールサポート';
@override
String get contactTitle => 'お問い合わせ';
@override
String get contactIntro =>
'お困りですか?以下のいずれかの方法でお問い合わせください。通常は数分以内に返信します。';
String get contactIntro => 'お困りですか?以下のいずれかの方法でお問い合わせください。通常は数分以内に返信します。';
@override
String get contactEmail => 'メールサポート';
@override
@@ -314,7 +284,6 @@ class StringsJa extends AppText {
String get contactHoursTitle => 'サポート時間';
@override
String get contactHours => '毎日 9:00 24:00 (GMT+8)';
@override
String get authTagline => '高速 · 安定 · かんたん';
@override
@@ -334,8 +303,6 @@ class StringsJa extends AppText {
@override
String get codeLabel => '確認コード';
@override
String codeSentTo(String email) => '$email に確認コードを送信しました';
@override
String get sendCode => 'コードを送信';
@override
String get resend => '再送信';
@@ -349,7 +316,6 @@ class StringsJa extends AppText {
String get forgotPw => 'パスワードをお忘れですか?';
@override
String get tos => '続行すると、利用規約とプライバシーポリシーに同意したことになります';
@override
String get obSkip => 'スキップ';
@override
@@ -370,8 +336,6 @@ class StringsJa extends AppText {
String get ob3Title => '設計段階からプライバシー重視';
@override
String get ob3Sub => 'エンドツーエンドで暗号化。閲覧ログは一切保持しません。';
// ── 购买 / 支付 ──
@override
String get purchaseTitle => 'プランを購入';
@override
@@ -434,8 +398,6 @@ class StringsJa extends AppText {
String get payUnsupportedRenderType => '未対応です。支払い方法を変更してください';
@override
String get payNoActiveOrder => '進行中の注文はありません';
// ── 支付渠道 switch + 订单 ──
@override
String get payChannel => '支払いチャネル';
@override
@@ -474,8 +436,6 @@ class StringsJa extends AppText {
String get orderRebuy => '再購入';
@override
String get payMethodNezha => 'Nazhapay';
// ── 邀请 / 通知 / 设置分组 / 订单过期(Spec ②③占位) ──
@override
String get inviteEntry => '友達を招待してメンバーシップを獲得';
@override
@@ -546,4 +506,37 @@ class StringsJa extends AppText {
String get promoBadge => '期間限定オファー';
@override
String get promoOriginalPrice => '通常価格';
@override
List<String> get days7 => const ['', '', '', '', '', '', ''];
@override
List<String> get featsFree => const [
'基本ノード1つのみ',
'1日10分',
'広告を見て開始',
'登録で7日間無料トライアル',
];
@override
List<String> get featsPro => const [
'80以上の拠点',
'無制限 · 高速',
'5台のデバイス',
'ストリーミング最適化',
];
@override
List<String> get featsTeam => const [
'Proのすべての機能',
'10ライセンス',
'一括請求',
'優先サポート',
];
@override
String adRewarded(int minutes) => '+$minutes 分を追加しました';
@override
String nodeSwitchTitle(String name) => '$name に切り替えますか?';
@override
String autoConnectingTo(String name) => '$name に自動接続中…';
@override
String updateAvailableTitle(String version) => '新しいバージョン v$version が利用可能です';
@override
String codeSentTo(String email) => '$email に確認コードを送信しました';
}