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:
@@ -1,8 +1,7 @@
|
||||
// strings_ru.dart — русские текстовые ресурсы (отображение на одном языке)
|
||||
// strings_ru.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 StringsRu extends AppText {
|
||||
@@ -27,7 +26,6 @@ class StringsRu extends AppText {
|
||||
String get connectNow => 'ПОДКЛЮЧИТЬ';
|
||||
@override
|
||||
String get secure => 'ЗАЩИЩЕНО';
|
||||
|
||||
@override
|
||||
String get tabConnect => 'Подключение';
|
||||
@override
|
||||
@@ -36,7 +34,6 @@ class StringsRu extends AppText {
|
||||
String get tabStats => 'Статистика';
|
||||
@override
|
||||
String get tabMe => 'Аккаунт';
|
||||
|
||||
@override
|
||||
String get currentNode => 'Текущий узел';
|
||||
@override
|
||||
@@ -45,7 +42,6 @@ class StringsRu extends AppText {
|
||||
String get upload => 'Отдача';
|
||||
@override
|
||||
String get latency => 'Пинг';
|
||||
|
||||
@override
|
||||
String get quotaToday => 'Осталось сегодня';
|
||||
@override
|
||||
@@ -65,20 +61,19 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get watchAdMore => 'Смотрите рекламу, чтобы добавить время';
|
||||
@override
|
||||
String get quotaExhaustedNotice => 'Дневной бесплатный лимит исчерпан. Оформите подписку, чтобы продолжить подключение.';
|
||||
String get quotaExhaustedNotice =>
|
||||
'Дневной бесплатный лимит исчерпан. Оформите подписку, чтобы продолжить подключение.';
|
||||
@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,22 +81,22 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get smartSelect => 'Умный выбор';
|
||||
@override
|
||||
String nodeSwitchTitle(String name) => 'Переключиться на $name?';
|
||||
@override
|
||||
String get nodeSwitchBody => 'Текущее соединение будет разорвано и восстановлено через этот узел.';
|
||||
String get nodeSwitchBody =>
|
||||
'Текущее соединение будет разорвано и восстановлено через этот узел.';
|
||||
@override
|
||||
String get nodeSwitchConfirm => 'Переключить';
|
||||
@override
|
||||
String get nodeUnhealthySwitched => 'Текущий узел недоступен — переключение выполнено автоматически';
|
||||
String get nodeUnhealthySwitched =>
|
||||
'Текущий узел недоступен — переключение выполнено автоматически';
|
||||
@override
|
||||
String get nodeUnhealthyError => 'Текущий узел недоступен — переподключитесь или смените узел';
|
||||
String get nodeUnhealthyError =>
|
||||
'Текущий узел недоступен — переподключитесь или смените узел';
|
||||
@override
|
||||
String get nodeReconnecting => 'Сеть нестабильна, переподключение…';
|
||||
@override
|
||||
String get smartSub => 'Подбирает лучший узел для вашей сети';
|
||||
@override
|
||||
String get recommended => 'Рекомендуется';
|
||||
|
||||
@override
|
||||
String get statsTitle => 'Статистика';
|
||||
@override
|
||||
@@ -113,8 +108,6 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get weekTraffic => 'На этой неделе (ГБ)';
|
||||
@override
|
||||
List<String> get days7 => const ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
|
||||
@override
|
||||
String get byDevice => 'По устройствам';
|
||||
@override
|
||||
String get noDeviceUsage => 'Пока нет данных по устройствам';
|
||||
@@ -134,7 +127,6 @@ class StringsRu extends AppText {
|
||||
String get chartTwoWeeks => 'Последние 2 недели';
|
||||
@override
|
||||
String get allDevices => 'Все устройства';
|
||||
|
||||
@override
|
||||
String get meTitle => 'Аккаунт';
|
||||
@override
|
||||
@@ -156,7 +148,8 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get deviceLimitTitle => 'Достигнут лимит устройств';
|
||||
@override
|
||||
String get deviceLimitDesc => 'Ваш тариф допускает до %s устройств. Удалите одно, чтобы продолжить.';
|
||||
String get deviceLimitDesc =>
|
||||
'Ваш тариф допускает до %s устройств. Удалите одно, чтобы продолжить.';
|
||||
@override
|
||||
String get deviceLimitRemoveOldest => 'Удалить давно неиспользуемое';
|
||||
@override
|
||||
@@ -186,15 +179,18 @@ class StringsRu 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,11 +220,10 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get autoConnectSub => 'Подключаться автоматически при запуске';
|
||||
@override
|
||||
String autoConnectingTo(String name) => 'Автоподключение к $name…';
|
||||
@override
|
||||
String get smartRoute => 'Умная маршрутизация';
|
||||
@override
|
||||
String get smartRouteSub => 'Ускорение для зарубежных ресурсов, прямой доступ для локальных';
|
||||
String get smartRouteSub =>
|
||||
'Ускорение для зарубежных ресурсов, прямой доступ для локальных';
|
||||
@override
|
||||
String get killSwitch => 'Kill Switch';
|
||||
@override
|
||||
@@ -238,9 +233,8 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get webUserCenter => 'Личный кабинет (веб)';
|
||||
@override
|
||||
String updateAvailableTitle(String version) => 'Доступна новая версия v$version';
|
||||
@override
|
||||
String get updateNotesFallback => 'Это обновление включает исправления и улучшения стабильности.';
|
||||
String get updateNotesFallback =>
|
||||
'Это обновление включает исправления и улучшения стабильности.';
|
||||
@override
|
||||
String get updateLater => 'Позже';
|
||||
@override
|
||||
@@ -248,8 +242,8 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get updateUpToDate => 'У вас установлена последняя версия';
|
||||
@override
|
||||
String get updateCheckFailed => 'Не удалось проверить обновления, попробуйте позже';
|
||||
|
||||
String get updateCheckFailed =>
|
||||
'Не удалось проверить обновления, попробуйте позже';
|
||||
@override
|
||||
String get freePlan => 'Бесплатный';
|
||||
@override
|
||||
@@ -266,20 +260,6 @@ class StringsRu extends AppText {
|
||||
String get choose => 'Выбрать';
|
||||
@override
|
||||
String get mostPopular => 'Популярный';
|
||||
@override
|
||||
List<String> get featsFree => const [
|
||||
'Только 1 базовый узел',
|
||||
'10 минут в день',
|
||||
'Смотрите рекламу, чтобы начать',
|
||||
'7 дней бесплатно при регистрации',
|
||||
];
|
||||
@override
|
||||
List<String> get featsPro =>
|
||||
const ['80+ локаций', 'Безлимитно · быстро', '5 устройств', 'Оптимизация для стриминга'];
|
||||
@override
|
||||
List<String> get featsTeam =>
|
||||
const ['Всё из Pro', '10 мест', 'Единый счёт', 'Приоритетная поддержка'];
|
||||
|
||||
@override
|
||||
String get redeemTitle => 'Активация и покупка';
|
||||
@override
|
||||
@@ -293,12 +273,12 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get buyTitle => 'Где купить';
|
||||
@override
|
||||
String get buySub => 'Оплата внутри приложения недоступна. Получить код можно через:';
|
||||
String get buySub =>
|
||||
'Оплата внутри приложения недоступна. Получить код можно через:';
|
||||
@override
|
||||
String get chStore => 'Магазин самообслуживания';
|
||||
@override
|
||||
String get chEmail => 'Поддержка по эл. почте';
|
||||
|
||||
@override
|
||||
String get contactTitle => 'Связаться с нами';
|
||||
@override
|
||||
@@ -314,7 +294,6 @@ class StringsRu extends AppText {
|
||||
String get contactHoursTitle => 'Часы поддержки';
|
||||
@override
|
||||
String get contactHours => 'Ежедневно 9:00 – 24:00 (GMT+8)';
|
||||
|
||||
@override
|
||||
String get authTagline => 'Быстро · Стабильно · Без усилий';
|
||||
@override
|
||||
@@ -334,8 +313,6 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get codeLabel => 'Код подтверждения';
|
||||
@override
|
||||
String codeSentTo(String email) => 'Код отправлен на $email';
|
||||
@override
|
||||
String get sendCode => 'Отправить код';
|
||||
@override
|
||||
String get resend => 'Отправить снова';
|
||||
@@ -348,8 +325,8 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get forgotPw => 'Забыли пароль?';
|
||||
@override
|
||||
String get tos => 'Продолжая, вы принимаете наши Условия и Политику конфиденциальности';
|
||||
|
||||
String get tos =>
|
||||
'Продолжая, вы принимаете наши Условия и Политику конфиденциальности';
|
||||
@override
|
||||
String get obSkip => 'Пропустить';
|
||||
@override
|
||||
@@ -361,17 +338,17 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get ob1Title => 'Подключение по всему миру';
|
||||
@override
|
||||
String get ob1Sub => '80+ локаций, автоматический выбор самого быстрого маршрута, надёжная стабильность.';
|
||||
String get ob1Sub =>
|
||||
'80+ локаций, автоматический выбор самого быстрого маршрута, надёжная стабильность.';
|
||||
@override
|
||||
String get ob2Title => 'Разрешите настройку сети';
|
||||
@override
|
||||
String get ob2Sub => 'Система запросит добавление сетевого профиля для создания зашифрованного туннеля.';
|
||||
String get ob2Sub =>
|
||||
'Система запросит добавление сетевого профиля для создания зашифрованного туннеля.';
|
||||
@override
|
||||
String get ob3Title => 'Приватность по умолчанию';
|
||||
@override
|
||||
String get ob3Sub => 'Сквозное шифрование. Мы не храним журналы просмотров.';
|
||||
|
||||
// ── 购买 / 支付 ──
|
||||
@override
|
||||
String get purchaseTitle => 'Покупка тарифа';
|
||||
@override
|
||||
@@ -401,15 +378,18 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get payNetworkLabel => 'Сеть';
|
||||
@override
|
||||
String get payExactAmountHint => 'Отправьте точную сумму — активация произойдёт автоматически';
|
||||
String get payExactAmountHint =>
|
||||
'Отправьте точную сумму — активация произойдёт автоматически';
|
||||
@override
|
||||
String get copied => 'Скопировано';
|
||||
@override
|
||||
String get openAlipay => 'Оплатить через Alipay';
|
||||
@override
|
||||
String get openAlipayHint => 'Вернитесь после оплаты — страница обновится автоматически';
|
||||
String get openAlipayHint =>
|
||||
'Вернитесь после оплаты — страница обновится автоматически';
|
||||
@override
|
||||
String get openAlipayFailed => 'Не удалось открыть Alipay. Проверьте, установлен ли он, или повторите';
|
||||
String get openAlipayFailed =>
|
||||
'Не удалось открыть Alipay. Проверьте, установлен ли он, или повторите';
|
||||
@override
|
||||
String get awaitingPayment => 'Ожидание оплаты';
|
||||
@override
|
||||
@@ -429,13 +409,13 @@ class StringsRu extends AppText {
|
||||
@override
|
||||
String get qrNotSupported => 'Скопируйте и откройте в Alipay';
|
||||
@override
|
||||
String get orderCreateFailed => 'Не удалось создать заказ, повторите попытку позже';
|
||||
String get orderCreateFailed =>
|
||||
'Не удалось создать заказ, повторите попытку позже';
|
||||
@override
|
||||
String get payUnsupportedRenderType => 'Не поддерживается, смените способ оплаты';
|
||||
String get payUnsupportedRenderType =>
|
||||
'Не поддерживается, смените способ оплаты';
|
||||
@override
|
||||
String get payNoActiveOrder => 'Нет активных заказов';
|
||||
|
||||
// ── 支付渠道 switch + 订单 ──
|
||||
@override
|
||||
String get payChannel => 'Способ оплаты';
|
||||
@override
|
||||
@@ -474,12 +454,11 @@ class StringsRu extends AppText {
|
||||
String get orderRebuy => 'Купить снова';
|
||||
@override
|
||||
String get payMethodNezha => 'Nazhapay';
|
||||
|
||||
// ── 邀请 / 通知 / 设置分组 / 订单过期(Spec ②③占位) ──
|
||||
@override
|
||||
String get inviteEntry => 'Приглашайте друзей и получайте членство';
|
||||
@override
|
||||
String get inviteEntrySub => 'Друг регистрируется · оба получают дни подписки';
|
||||
String get inviteEntrySub =>
|
||||
'Друг регистрируется · оба получают дни подписки';
|
||||
@override
|
||||
String get inviteTitle => 'Пригласить друзей';
|
||||
@override
|
||||
@@ -546,4 +525,38 @@ class StringsRu extends AppText {
|
||||
String get promoBadge => 'Спецпредложение';
|
||||
@override
|
||||
String get promoOriginalPrice => 'Было';
|
||||
@override
|
||||
List<String> get days7 => const ['Пн', 'Вт', 'Ср', 'Чт', 'Пт', 'Сб', 'Вс'];
|
||||
@override
|
||||
List<String> get featsFree => const [
|
||||
'Только 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';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user