feat(i18n): ③ 原型接单源 — I18N 块由 strings.json 生成,消除重复翻译

原型 design/prototype/screens/{ui-desktop,ui-mobile}.html 的 I18N 数据块不再手写,
改由 strings.json 生成(marker 包裹、生成器唯一写):
- alias.json:protoKey → flutterKey(产品串取单源 zh/en,单源赢);desktop 130 / mobile 143。
- overlay.json:原型专属(开发挡板 + app 没有的串,zh/en);desktop 98 / mobile 104。
- new-strings.json:4 个新产品串(分流规则/自定义/局域网直连/强制),6 语,已并入
  strings.json + app_text.dart 抽象声明 + 重生成 6 份 strings_*.dart。
- gen_proto_i18n.mjs:strings.json+alias+overlay → 两份 HTML 的 I18N 块;--check 只比对
  marker 块(unrelated HTML 编辑不误报)。
- check-proto-i18n.mjs:两份 HTML 所有 data-i18n key 的 zh/en 必须 resolve。
- ci/check-codegen-drift.sh:加原型 i18n 段(--check 漂移 + resolution 验收)。

同带入之前路由原型 WIP 的 i18n 收口:私有服务内置行→局域网/私网直连行、rr.* 接 data-i18n
(rr.lan→routingLanDirect 等)。路由页其余 UI(段选/添加规则页)仍为独立后续。

验收(自复核全绿):生成器跑通、data-i18n 0 unresolved、两生成器重生成零 diff、
flutter analyze lib/l10n 0 issue、flutter test 244 全绿、new-strings 无红线词。

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 09:59:18 +08:00
parent f46191ef4d
commit 75d23023e3
16 changed files with 2139 additions and 264 deletions
+5
View File
@@ -628,4 +628,9 @@ abstract class AppText {
String get settingsGroupConn; // 连接 / Connection
String get settingsGroupAppearance;// 外观 / Appearance
String get settingsGroupAbout; // 关于 / About
// ── 分流规则(configurable proxy)──
String get routingRulesTitle; // 分流规则 / Routing rules
String get routingRulesSub; // 自定义直连 / 走隧道 / 拒绝
String get routingLanDirect; // 局域网 / 私网直连 / LAN & private direct
String get routingLanForced; // 强制,不可关 / Always on
}
+8
View File
@@ -503,6 +503,14 @@ class StringsEn extends AppText {
@override
String get promoOriginalPrice => 'Was';
@override
String get routingRulesTitle => 'Routing rules';
@override
String get routingRulesSub => 'Custom direct / tunnel / reject';
@override
String get routingLanDirect => 'LAN & private direct';
@override
String get routingLanForced => 'Always on';
@override
List<String> get days7 => const ['M', 'T', 'W', 'T', 'F', 'S', 'S'];
@override
List<String> get featsFree => const ['1 basic node only', '10 min per day', 'Watch an ad to start', '7-day free trial on sign-up'];
+8
View File
@@ -503,6 +503,14 @@ class StringsEs extends AppText {
@override
String get promoOriginalPrice => 'Antes';
@override
String get routingRulesTitle => 'Reglas de enrutamiento';
@override
String get routingRulesSub => 'Personalizar: directo / túnel / rechazar';
@override
String get routingLanDirect => 'LAN y red privada directas';
@override
String get routingLanForced => 'Siempre activo';
@override
List<String> get days7 => const ['L', 'M', 'X', 'J', 'V', 'S', 'D'];
@override
List<String> get featsFree => const ['Solo 1 nodo básico', '10 min al día', 'Mira un anuncio para empezar', 'Prueba gratis de 7 días al registrarte'];
+8
View File
@@ -503,6 +503,14 @@ class StringsJa extends AppText {
@override
String get promoOriginalPrice => '通常価格';
@override
String get routingRulesTitle => 'ルーティングルール';
@override
String get routingRulesSub => '直接接続 / トンネル / 拒否をカスタム';
@override
String get routingLanDirect => 'LAN・プライベート直接接続';
@override
String get routingLanForced => '常時オン';
@override
List<String> get days7 => const ['', '', '', '', '', '', ''];
@override
List<String> get featsFree => const ['基本ノード1つのみ', '1日10分', '広告を見て開始', '登録で7日間無料トライアル'];
+8
View File
@@ -503,6 +503,14 @@ class StringsKo extends AppText {
@override
String get promoOriginalPrice => '정가';
@override
String get routingRulesTitle => '라우팅 규칙';
@override
String get routingRulesSub => '직접 연결 / 터널 / 거부 사용자 지정';
@override
String get routingLanDirect => 'LAN / 사설망 직접 연결';
@override
String get routingLanForced => '항상 켜짐';
@override
List<String> get days7 => const ['', '', '', '', '', '', ''];
@override
List<String> get featsFree => const ['기본 노드 1개', '하루 10분', '광고 시청 후 시작', '가입 시 7일 무료 체험'];
+8
View File
@@ -503,6 +503,14 @@ class StringsRu extends AppText {
@override
String get promoOriginalPrice => 'Было';
@override
String get routingRulesTitle => 'Правила маршрутизации';
@override
String get routingRulesSub => 'Настройка: напрямую / туннель / отклонить';
@override
String get routingLanDirect => 'Локальная и частная сеть напрямую';
@override
String get routingLanForced => 'Всегда включено';
@override
List<String> get days7 => const ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
@override
List<String> get featsFree => const ['Только 1 базовый узел', '10 минут в день', 'Смотрите рекламу, чтобы начать', '7 дней бесплатно при регистрации'];
+8
View File
@@ -503,6 +503,14 @@ class StringsZh extends AppText {
@override
String get promoOriginalPrice => '原价';
@override
String get routingRulesTitle => '分流规则';
@override
String get routingRulesSub => '自定义直连 / 走隧道 / 拒绝';
@override
String get routingLanDirect => '局域网 / 私网直连';
@override
String get routingLanForced => '强制,不可关';
@override
List<String> get days7 => const ['', '', '', '', '', '', ''];
@override
List<String> get featsFree => const ['仅 1 个基础节点', '每日 10 分钟时长', '使用前观看广告', '注册享 7 天免费试用'];