feat(spoof): port session spoofing screen with device presets
This commit is contained in:
+45
-8
@@ -5,6 +5,7 @@ import '../core/config/config.dart';
|
||||
import '../core/config/countries.dart';
|
||||
import '../core/protocol/opcode_map.dart';
|
||||
import '../core/protocol/packet.dart';
|
||||
import '../core/storage/spoofing_service.dart';
|
||||
import '../core/transport/connection.dart';
|
||||
import '../core/transport/dispatcher.dart';
|
||||
import '../core/transport/receiver.dart';
|
||||
@@ -112,7 +113,7 @@ class Api {
|
||||
Future<Packet> sendHandshake() async {
|
||||
final deviceInfo = DeviceInfoPlugin();
|
||||
|
||||
final deviceType = (Platform.isLinux || Platform.isWindows)
|
||||
String deviceType = (Platform.isLinux || Platform.isWindows)
|
||||
? 'DESKTOP'
|
||||
: (Platform.isAndroid)
|
||||
? 'ANDROID'
|
||||
@@ -120,10 +121,16 @@ class Api {
|
||||
String osVersion = '';
|
||||
String deviceName = 'Unknown';
|
||||
String architecture = 'arm64';
|
||||
String appVersion = SpoofingService.hardcodedAppVersion;
|
||||
int buildNumber = SpoofingService.hardcodedBuildNumber;
|
||||
String screen = '1920x1080';
|
||||
|
||||
tz.initializeTimeZones();
|
||||
final timeZoneName = await FlutterTimezone.getLocalTimezone();
|
||||
final timezone = timeZoneName.identifier;
|
||||
String timezone = timeZoneName.identifier;
|
||||
String locale = 'ru';
|
||||
String deviceLocale = Platform.localeName.substring(0, 2);
|
||||
String deviceId = 'a1b2c3d4e5f6a7b8';
|
||||
|
||||
if (Platform.isLinux) {
|
||||
final linuxInfo = await deviceInfo.linuxInfo;
|
||||
@@ -150,24 +157,54 @@ class Api {
|
||||
);
|
||||
}
|
||||
|
||||
final spoofed = await SpoofingService.getSpoofedSessionData();
|
||||
if (spoofed != null) {
|
||||
deviceType = (spoofed['device_type'] as String?) ?? deviceType;
|
||||
final sDeviceName = spoofed['device_name'] as String?;
|
||||
if (sDeviceName != null && sDeviceName.isNotEmpty) {
|
||||
deviceName = sDeviceName;
|
||||
}
|
||||
final sOsVersion = spoofed['os_version'] as String?;
|
||||
if (sOsVersion != null && sOsVersion.isNotEmpty) osVersion = sOsVersion;
|
||||
final sScreen = spoofed['screen'] as String?;
|
||||
if (sScreen != null && sScreen.isNotEmpty) screen = sScreen;
|
||||
final sTimezone = spoofed['timezone'] as String?;
|
||||
if (sTimezone != null && sTimezone.isNotEmpty) timezone = sTimezone;
|
||||
final sLocale = spoofed['locale'] as String?;
|
||||
if (sLocale != null && sLocale.isNotEmpty) {
|
||||
locale = sLocale;
|
||||
deviceLocale = sLocale.split(RegExp(r'[-_]')).first;
|
||||
}
|
||||
final sDeviceId = spoofed['device_id'] as String?;
|
||||
if (sDeviceId != null && sDeviceId.isNotEmpty) deviceId = sDeviceId;
|
||||
appVersion = (spoofed['app_version'] as String?) ?? appVersion;
|
||||
architecture = (spoofed['arch'] as String?) ?? architecture;
|
||||
final sBuild = spoofed['build_number'];
|
||||
if (sBuild is int) {
|
||||
buildNumber = sBuild;
|
||||
} else if (sBuild is String) {
|
||||
buildNumber = int.tryParse(sBuild) ?? buildNumber;
|
||||
}
|
||||
}
|
||||
|
||||
_userAgent = {
|
||||
'deviceType': deviceType,
|
||||
'locale': 'ru',
|
||||
'deviceLocale': Platform.localeName.substring(0, 2),
|
||||
'locale': locale,
|
||||
'deviceLocale': deviceLocale,
|
||||
'osVersion': osVersion,
|
||||
'deviceName': deviceName,
|
||||
'appVersion': '26.8.1',
|
||||
'screen': '1920x1080',
|
||||
'appVersion': appVersion,
|
||||
'screen': screen,
|
||||
'timezone': timezone,
|
||||
'pushDeviceType': 'GCM',
|
||||
'arch': architecture,
|
||||
'buildNumber': 6606,
|
||||
'buildNumber': buildNumber,
|
||||
};
|
||||
|
||||
final payload = <dynamic, dynamic>{
|
||||
'mt_instanceid': '550e8400-e29b-41d4-a716-446655440000',
|
||||
'clientSessionId': 42,
|
||||
'deviceId': 'a1b2c3d4e5f6a7b8',
|
||||
'deviceId': deviceId,
|
||||
'userAgent': _userAgent,
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,31 +0,0 @@
|
||||
class SpoofData {
|
||||
static const List<String> deviceNames = [
|
||||
'Samsung Galaxy S23',
|
||||
'Xiaomi 13 Pro',
|
||||
'Google Pixel 7',
|
||||
'OnePlus 11',
|
||||
];
|
||||
|
||||
static const List<String> osVersions = ['12', '13', '14'];
|
||||
|
||||
static const List<String> resolutions = [
|
||||
'1080x2400',
|
||||
'1440x3200',
|
||||
'720x1600',
|
||||
];
|
||||
|
||||
static const List<String> deviceIds = [
|
||||
'a1b2c3d4e5f6',
|
||||
'f8e7d6c5b4a3',
|
||||
'9876543210ab',
|
||||
'1234567890cd',
|
||||
];
|
||||
|
||||
static const List<String> architectures = ['arm64-v8a', 'armeabi-v7a'];
|
||||
|
||||
static const String deviceType = 'android';
|
||||
static const String timezone = 'Europe/Moscow';
|
||||
static const String locale = 'ru_RU';
|
||||
static const String appVersion = '26.10.1';
|
||||
static const String buildNumber = '6728';
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class SpoofingService {
|
||||
static const String hardcodedAppVersion = '26.8.1';
|
||||
static const int hardcodedBuildNumber = 6606;
|
||||
|
||||
static Future<Map<String, dynamic>?> getSpoofedSessionData() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
final isEnabled = prefs.getBool('spoofing_enabled') ?? false;
|
||||
if (!isEnabled) return null;
|
||||
|
||||
return {
|
||||
'device_name': prefs.getString('spoof_devicename'),
|
||||
'os_version': prefs.getString('spoof_osversion'),
|
||||
'screen': prefs.getString('spoof_screen'),
|
||||
'timezone': prefs.getString('spoof_timezone'),
|
||||
'locale': prefs.getString('spoof_locale'),
|
||||
'device_id': prefs.getString('spoof_deviceid'),
|
||||
'device_type': prefs.getString('spoof_devicetype'),
|
||||
'app_version': prefs.getString('spoof_appversion') ?? hardcodedAppVersion,
|
||||
'arch': prefs.getString('spoof_arch') ?? 'arm64-v8a',
|
||||
'build_number':
|
||||
prefs.getInt('spoof_buildnumber') ?? hardcodedBuildNumber,
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -12,7 +12,7 @@ import 'code_confirmation_screen.dart';
|
||||
import 'select_country_screen.dart';
|
||||
import 'proxy_settings_sheet.dart';
|
||||
import 'server_settings_sheet.dart';
|
||||
import 'spoff_redacted_screen.dart';
|
||||
import '../profile/spoof_screen.dart';
|
||||
import '../../widgets/custom_notification.dart';
|
||||
import '../../../main.dart';
|
||||
|
||||
@@ -522,7 +522,7 @@ class _LoginScreenState extends State<LoginScreen> {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const SpoffRedactedScreen(),
|
||||
builder: (context) => const SpoofScreen(),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,217 +0,0 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:komet/core/config/spoof_data.dart';
|
||||
import 'package:komet/frontend/widgets/custom_notification.dart';
|
||||
|
||||
class SpoffRedactedScreen extends StatefulWidget {
|
||||
const SpoffRedactedScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SpoffRedactedScreen> createState() => _SpoffRedactedScreenState();
|
||||
}
|
||||
|
||||
class _SpoffRedactedScreenState extends State<SpoffRedactedScreen> {
|
||||
final TextEditingController _deviceNameController = TextEditingController();
|
||||
final TextEditingController _osVersionController = TextEditingController();
|
||||
final TextEditingController _resolutionController = TextEditingController();
|
||||
final TextEditingController _deviceIdController = TextEditingController();
|
||||
final TextEditingController _architectureController = TextEditingController();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadSettings();
|
||||
}
|
||||
|
||||
Future<void> _loadSettings() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
|
||||
final random = Random();
|
||||
|
||||
setState(() {
|
||||
_deviceNameController.text =
|
||||
prefs.getString('spoof_device_name') ??
|
||||
SpoofData.deviceNames[random.nextInt(SpoofData.deviceNames.length)];
|
||||
_osVersionController.text =
|
||||
prefs.getString('spoof_os_version') ??
|
||||
SpoofData.osVersions[random.nextInt(SpoofData.osVersions.length)];
|
||||
_resolutionController.text =
|
||||
prefs.getString('spoof_resolution') ??
|
||||
SpoofData.resolutions[random.nextInt(SpoofData.resolutions.length)];
|
||||
_deviceIdController.text =
|
||||
prefs.getString('spoof_device_id') ??
|
||||
SpoofData.deviceIds[random.nextInt(SpoofData.deviceIds.length)];
|
||||
_architectureController.text =
|
||||
prefs.getString('spoof_architecture') ??
|
||||
SpoofData.architectures[random.nextInt(
|
||||
SpoofData.architectures.length,
|
||||
)];
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _saveSettings() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('spoof_device_name', _deviceNameController.text);
|
||||
await prefs.setString('spoof_os_version', _osVersionController.text);
|
||||
await prefs.setString('spoof_resolution', _resolutionController.text);
|
||||
await prefs.setString('spoof_device_id', _deviceIdController.text);
|
||||
await prefs.setString('spoof_architecture', _architectureController.text);
|
||||
|
||||
if (mounted) {
|
||||
showCustomNotification(context, 'Настройки сохранены');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_deviceNameController.dispose();
|
||||
_osVersionController.dispose();
|
||||
_resolutionController.dispose();
|
||||
_deviceIdController.dispose();
|
||||
_architectureController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cs = Theme.of(context).colorScheme;
|
||||
return Scaffold(
|
||||
backgroundColor: cs.surface,
|
||||
appBar: AppBar(
|
||||
iconTheme: IconThemeData(color: cs.onSurface),
|
||||
title: Text(
|
||||
'Подделка спуфа',
|
||||
style: GoogleFonts.inter(
|
||||
color: cs.onSurface,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
backgroundColor: cs.surface,
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Icon(Icons.check, color: cs.primary),
|
||||
onPressed: _saveSettings,
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
_buildTextField(
|
||||
controller: TextEditingController(text: SpoofData.deviceType),
|
||||
label: 'Тип устройства',
|
||||
cs: cs,
|
||||
readOnly: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: _deviceNameController,
|
||||
label: 'Имя устройства',
|
||||
cs: cs,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: _osVersionController,
|
||||
label: 'Версия ОС',
|
||||
cs: cs,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: _resolutionController,
|
||||
label: 'Разрешение экрана',
|
||||
cs: cs,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: TextEditingController(text: SpoofData.timezone),
|
||||
label: 'Часовой пояс',
|
||||
cs: cs,
|
||||
readOnly: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: TextEditingController(text: SpoofData.locale),
|
||||
label: 'Локаль',
|
||||
cs: cs,
|
||||
readOnly: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: _deviceIdController,
|
||||
label: 'ID устройства',
|
||||
cs: cs,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: TextEditingController(text: SpoofData.appVersion),
|
||||
label: 'Версия приложения',
|
||||
cs: cs,
|
||||
readOnly: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: TextEditingController(text: SpoofData.buildNumber),
|
||||
label: 'Build Number',
|
||||
cs: cs,
|
||||
readOnly: true,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildTextField(
|
||||
controller: _architectureController,
|
||||
label: 'Архитектура',
|
||||
cs: cs,
|
||||
),
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTextField({
|
||||
required TextEditingController controller,
|
||||
required String label,
|
||||
required ColorScheme cs,
|
||||
bool readOnly = false,
|
||||
}) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
style: GoogleFonts.inter(
|
||||
color: cs.onSurfaceVariant,
|
||||
fontWeight: FontWeight.w500,
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
TextField(
|
||||
controller: controller,
|
||||
readOnly: readOnly,
|
||||
style: GoogleFonts.inter(
|
||||
color: readOnly ? cs.onSurfaceVariant : cs.onSurface,
|
||||
fontSize: 15,
|
||||
),
|
||||
decoration: InputDecoration(
|
||||
filled: true,
|
||||
fillColor: readOnly
|
||||
? cs.surfaceContainerHighest
|
||||
: cs.surfaceContainerHigh,
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
borderSide: BorderSide.none,
|
||||
),
|
||||
contentPadding: const EdgeInsets.symmetric(
|
||||
horizontal: 16,
|
||||
vertical: 14,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import '../../../core/storage/app_database.dart';
|
||||
import '../../../l10n/app_localizations.dart';
|
||||
import '../auth/proxy_settings_sheet.dart';
|
||||
import 'debug_menu_screen.dart';
|
||||
import 'devices_screen.dart';
|
||||
@@ -143,7 +144,7 @@ class _SettingsTabState extends State<SettingsTab> {
|
||||
),
|
||||
_SettingsItem(
|
||||
icon: Symbols.shield_lock,
|
||||
label: 'Подделка данных',
|
||||
label: AppLocalizations.of(context)!.profileMenuSpoof,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+46
-2
@@ -12,7 +12,7 @@
|
||||
"loginEdit": "Change",
|
||||
"loginDone": "Done",
|
||||
"loginReadTermsNotification": "Please read the terms of use first",
|
||||
"loginSpoofRedacted": "Spoof redaction",
|
||||
"loginSpoofRedacted": "Spoofing",
|
||||
"loginProxy": "Proxy",
|
||||
"loginChangeServer": "Change server",
|
||||
"serverSettingsTitle": "Server",
|
||||
@@ -54,5 +54,49 @@
|
||||
"proxyApply": "Apply and reconnect",
|
||||
"proxyDisable": "Disable proxy",
|
||||
"proxySettingsSaved": "Proxy settings applied",
|
||||
"proxyInvalidHostOrPort": "Enter a valid proxy host and port (1–65535)"
|
||||
"proxyInvalidHostOrPort": "Enter a valid proxy host and port (1–65535)",
|
||||
|
||||
"spoofScreenTitle": "Session spoofing",
|
||||
"spoofInfoHint": "Tap \"Generate\":\n• Short tap: random preset.\n• Long press: real device data.",
|
||||
"spoofMethodTitle": "Spoofing method",
|
||||
"spoofMethodPartial": "Partial",
|
||||
"spoofMethodFull": "Full",
|
||||
"spoofMethodPartialDescription": "Recommended method. Random data is used, but your real timezone and locale are kept for plausibility.",
|
||||
"spoofMethodFullDescription": "All data including timezone and locale is generated randomly. Use this method at your own risk!",
|
||||
"spoofDeviceTypeTitle": "Device type",
|
||||
"spoofDeviceTypeDescription": "Choose a device type for preset generation. Tapping \"Generate\" will only use presets of the selected type.",
|
||||
"spoofDeviceTypeLabel": "Device type",
|
||||
"spoofMainSectionTitle": "Main data",
|
||||
"spoofFieldDeviceName": "Device name",
|
||||
"spoofFieldOsVersion": "OS version",
|
||||
"spoofRegionalSectionTitle": "Regional data",
|
||||
"spoofFieldScreen": "Screen resolution",
|
||||
"spoofFieldTimezone": "Timezone",
|
||||
"spoofFieldLocale": "Locale",
|
||||
"spoofIdentifiersSectionTitle": "Identifiers",
|
||||
"spoofIdentifiersDescription": "mt_instanceid and clientSessionId are generated automatically on every app launch. Only the Device ID can be changed.",
|
||||
"spoofFieldDeviceId": "Device ID",
|
||||
"spoofRegenerateIdTooltip": "Generate a new ID",
|
||||
"spoofFieldAppVersion": "App version",
|
||||
"spoofFieldBuildNumber": "Build number",
|
||||
"spoofFieldArchitecture": "Architecture",
|
||||
"spoofButtonGenerate": "Generate",
|
||||
"spoofButtonApply": "Apply",
|
||||
"spoofDialogUnsureTitle": "Are you sure?",
|
||||
"spoofDialogUnsureContent": "The app may become unstable due to API incompatibility",
|
||||
"spoofDialogCancel": "Cancel",
|
||||
"spoofDialogYes": "Yes",
|
||||
"spoofDialogApplyTitle": "Apply settings?",
|
||||
"spoofDialogApplyContent": "Need to reconnect the app, ok?",
|
||||
"spoofDialogApplyDeny": "No",
|
||||
"spoofDialogApplyConfirm": "Ok!",
|
||||
"spoofErrorApplyFailed": "Failed to apply settings: {error}",
|
||||
"@spoofErrorApplyFailed": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"profileMenuSpoof": "Spoofing"
|
||||
}
|
||||
|
||||
+238
-17
@@ -62,7 +62,8 @@ import 'app_localizations_ru.dart';
|
||||
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
|
||||
/// property.
|
||||
abstract class AppLocalizations {
|
||||
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
AppLocalizations(String locale)
|
||||
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
final String localeName;
|
||||
|
||||
@@ -70,7 +71,8 @@ abstract class AppLocalizations {
|
||||
return Localizations.of<AppLocalizations>(context, AppLocalizations);
|
||||
}
|
||||
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
|
||||
static const LocalizationsDelegate<AppLocalizations> delegate =
|
||||
_AppLocalizationsDelegate();
|
||||
|
||||
/// A list of this localizations delegate along with the default localizations
|
||||
/// delegates.
|
||||
@@ -82,17 +84,18 @@ abstract class AppLocalizations {
|
||||
/// Additional delegates can be added by appending to this list in
|
||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
<LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('en'),
|
||||
Locale('ru')
|
||||
Locale('ru'),
|
||||
];
|
||||
|
||||
/// No description provided for @loginTitle.
|
||||
@@ -170,7 +173,7 @@ abstract class AppLocalizations {
|
||||
/// No description provided for @loginSpoofRedacted.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Spoof redaction'**
|
||||
/// **'Spoofing'**
|
||||
String get loginSpoofRedacted;
|
||||
|
||||
/// No description provided for @loginProxy.
|
||||
@@ -376,9 +379,226 @@ abstract class AppLocalizations {
|
||||
/// In en, this message translates to:
|
||||
/// **'Enter a valid proxy host and port (1–65535)'**
|
||||
String get proxyInvalidHostOrPort;
|
||||
|
||||
/// No description provided for @spoofScreenTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Session spoofing'**
|
||||
String get spoofScreenTitle;
|
||||
|
||||
/// No description provided for @spoofInfoHint.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tap \"Generate\":\n• Short tap: random preset.\n• Long press: real device data.'**
|
||||
String get spoofInfoHint;
|
||||
|
||||
/// No description provided for @spoofMethodTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Spoofing method'**
|
||||
String get spoofMethodTitle;
|
||||
|
||||
/// No description provided for @spoofMethodPartial.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Partial'**
|
||||
String get spoofMethodPartial;
|
||||
|
||||
/// No description provided for @spoofMethodFull.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Full'**
|
||||
String get spoofMethodFull;
|
||||
|
||||
/// No description provided for @spoofMethodPartialDescription.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Recommended method. Random data is used, but your real timezone and locale are kept for plausibility.'**
|
||||
String get spoofMethodPartialDescription;
|
||||
|
||||
/// No description provided for @spoofMethodFullDescription.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'All data including timezone and locale is generated randomly. Use this method at your own risk!'**
|
||||
String get spoofMethodFullDescription;
|
||||
|
||||
/// No description provided for @spoofDeviceTypeTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Device type'**
|
||||
String get spoofDeviceTypeTitle;
|
||||
|
||||
/// No description provided for @spoofDeviceTypeDescription.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Choose a device type for preset generation. Tapping \"Generate\" will only use presets of the selected type.'**
|
||||
String get spoofDeviceTypeDescription;
|
||||
|
||||
/// No description provided for @spoofDeviceTypeLabel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Device type'**
|
||||
String get spoofDeviceTypeLabel;
|
||||
|
||||
/// No description provided for @spoofMainSectionTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Main data'**
|
||||
String get spoofMainSectionTitle;
|
||||
|
||||
/// No description provided for @spoofFieldDeviceName.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Device name'**
|
||||
String get spoofFieldDeviceName;
|
||||
|
||||
/// No description provided for @spoofFieldOsVersion.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'OS version'**
|
||||
String get spoofFieldOsVersion;
|
||||
|
||||
/// No description provided for @spoofRegionalSectionTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Regional data'**
|
||||
String get spoofRegionalSectionTitle;
|
||||
|
||||
/// No description provided for @spoofFieldScreen.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Screen resolution'**
|
||||
String get spoofFieldScreen;
|
||||
|
||||
/// No description provided for @spoofFieldTimezone.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Timezone'**
|
||||
String get spoofFieldTimezone;
|
||||
|
||||
/// No description provided for @spoofFieldLocale.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Locale'**
|
||||
String get spoofFieldLocale;
|
||||
|
||||
/// No description provided for @spoofIdentifiersSectionTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Identifiers'**
|
||||
String get spoofIdentifiersSectionTitle;
|
||||
|
||||
/// No description provided for @spoofIdentifiersDescription.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'mt_instanceid and clientSessionId are generated automatically on every app launch. Only the Device ID can be changed.'**
|
||||
String get spoofIdentifiersDescription;
|
||||
|
||||
/// No description provided for @spoofFieldDeviceId.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Device ID'**
|
||||
String get spoofFieldDeviceId;
|
||||
|
||||
/// No description provided for @spoofRegenerateIdTooltip.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Generate a new ID'**
|
||||
String get spoofRegenerateIdTooltip;
|
||||
|
||||
/// No description provided for @spoofFieldAppVersion.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'App version'**
|
||||
String get spoofFieldAppVersion;
|
||||
|
||||
/// No description provided for @spoofFieldBuildNumber.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Build number'**
|
||||
String get spoofFieldBuildNumber;
|
||||
|
||||
/// No description provided for @spoofFieldArchitecture.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Architecture'**
|
||||
String get spoofFieldArchitecture;
|
||||
|
||||
/// No description provided for @spoofButtonGenerate.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Generate'**
|
||||
String get spoofButtonGenerate;
|
||||
|
||||
/// No description provided for @spoofButtonApply.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Apply'**
|
||||
String get spoofButtonApply;
|
||||
|
||||
/// No description provided for @spoofDialogUnsureTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Are you sure?'**
|
||||
String get spoofDialogUnsureTitle;
|
||||
|
||||
/// No description provided for @spoofDialogUnsureContent.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'The app may become unstable due to API incompatibility'**
|
||||
String get spoofDialogUnsureContent;
|
||||
|
||||
/// No description provided for @spoofDialogCancel.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cancel'**
|
||||
String get spoofDialogCancel;
|
||||
|
||||
/// No description provided for @spoofDialogYes.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Yes'**
|
||||
String get spoofDialogYes;
|
||||
|
||||
/// No description provided for @spoofDialogApplyTitle.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Apply settings?'**
|
||||
String get spoofDialogApplyTitle;
|
||||
|
||||
/// No description provided for @spoofDialogApplyContent.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Need to reconnect the app, ok?'**
|
||||
String get spoofDialogApplyContent;
|
||||
|
||||
/// No description provided for @spoofDialogApplyDeny.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No'**
|
||||
String get spoofDialogApplyDeny;
|
||||
|
||||
/// No description provided for @spoofDialogApplyConfirm.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Ok!'**
|
||||
String get spoofDialogApplyConfirm;
|
||||
|
||||
/// No description provided for @spoofErrorApplyFailed.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to apply settings: {error}'**
|
||||
String spoofErrorApplyFailed(String error);
|
||||
|
||||
/// No description provided for @profileMenuSpoof.
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Spoofing'**
|
||||
String get profileMenuSpoof;
|
||||
}
|
||||
|
||||
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
|
||||
class _AppLocalizationsDelegate
|
||||
extends LocalizationsDelegate<AppLocalizations> {
|
||||
const _AppLocalizationsDelegate();
|
||||
|
||||
@override
|
||||
@@ -387,25 +607,26 @@ class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations>
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => <String>['en', 'ru'].contains(locale.languageCode);
|
||||
bool isSupported(Locale locale) =>
|
||||
<String>['en', 'ru'].contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_AppLocalizationsDelegate old) => false;
|
||||
}
|
||||
|
||||
AppLocalizations lookupAppLocalizations(Locale locale) {
|
||||
|
||||
|
||||
// Lookup logic when only language code is specified.
|
||||
switch (locale.languageCode) {
|
||||
case 'en': return AppLocalizationsEn();
|
||||
case 'ru': return AppLocalizationsRu();
|
||||
case 'en':
|
||||
return AppLocalizationsEn();
|
||||
case 'ru':
|
||||
return AppLocalizationsRu();
|
||||
}
|
||||
|
||||
throw FlutterError(
|
||||
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.'
|
||||
'that was used.',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get loginTitle => 'Sign in to Komet';
|
||||
|
||||
@override
|
||||
String get loginSubtitle => 'Check your country code and enter your\nphone number.';
|
||||
String get loginSubtitle =>
|
||||
'Check your country code and enter your\nphone number.';
|
||||
|
||||
@override
|
||||
String get loginCountry => 'Country';
|
||||
@@ -45,7 +46,7 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get loginReadTermsNotification => 'Please read the terms of use first';
|
||||
|
||||
@override
|
||||
String get loginSpoofRedacted => 'Spoof redaction';
|
||||
String get loginSpoofRedacted => 'Spoofing';
|
||||
|
||||
@override
|
||||
String get loginProxy => 'Proxy';
|
||||
@@ -102,7 +103,8 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get selectCountrySearchHint => 'Search countries…';
|
||||
|
||||
@override
|
||||
String get codeConfirmationSmsSent => 'We sent an SMS with a verification code to your phone number.';
|
||||
String get codeConfirmationSmsSent =>
|
||||
'We sent an SMS with a verification code to your phone number.';
|
||||
|
||||
@override
|
||||
String codeResendInSeconds(int seconds) {
|
||||
@@ -149,5 +151,122 @@ class AppLocalizationsEn extends AppLocalizations {
|
||||
String get proxySettingsSaved => 'Proxy settings applied';
|
||||
|
||||
@override
|
||||
String get proxyInvalidHostOrPort => 'Enter a valid proxy host and port (1–65535)';
|
||||
String get proxyInvalidHostOrPort =>
|
||||
'Enter a valid proxy host and port (1–65535)';
|
||||
|
||||
@override
|
||||
String get spoofScreenTitle => 'Session spoofing';
|
||||
|
||||
@override
|
||||
String get spoofInfoHint =>
|
||||
'Tap \"Generate\":\n• Short tap: random preset.\n• Long press: real device data.';
|
||||
|
||||
@override
|
||||
String get spoofMethodTitle => 'Spoofing method';
|
||||
|
||||
@override
|
||||
String get spoofMethodPartial => 'Partial';
|
||||
|
||||
@override
|
||||
String get spoofMethodFull => 'Full';
|
||||
|
||||
@override
|
||||
String get spoofMethodPartialDescription =>
|
||||
'Recommended method. Random data is used, but your real timezone and locale are kept for plausibility.';
|
||||
|
||||
@override
|
||||
String get spoofMethodFullDescription =>
|
||||
'All data including timezone and locale is generated randomly. Use this method at your own risk!';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeTitle => 'Device type';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeDescription =>
|
||||
'Choose a device type for preset generation. Tapping \"Generate\" will only use presets of the selected type.';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeLabel => 'Device type';
|
||||
|
||||
@override
|
||||
String get spoofMainSectionTitle => 'Main data';
|
||||
|
||||
@override
|
||||
String get spoofFieldDeviceName => 'Device name';
|
||||
|
||||
@override
|
||||
String get spoofFieldOsVersion => 'OS version';
|
||||
|
||||
@override
|
||||
String get spoofRegionalSectionTitle => 'Regional data';
|
||||
|
||||
@override
|
||||
String get spoofFieldScreen => 'Screen resolution';
|
||||
|
||||
@override
|
||||
String get spoofFieldTimezone => 'Timezone';
|
||||
|
||||
@override
|
||||
String get spoofFieldLocale => 'Locale';
|
||||
|
||||
@override
|
||||
String get spoofIdentifiersSectionTitle => 'Identifiers';
|
||||
|
||||
@override
|
||||
String get spoofIdentifiersDescription =>
|
||||
'mt_instanceid and clientSessionId are generated automatically on every app launch. Only the Device ID can be changed.';
|
||||
|
||||
@override
|
||||
String get spoofFieldDeviceId => 'Device ID';
|
||||
|
||||
@override
|
||||
String get spoofRegenerateIdTooltip => 'Generate a new ID';
|
||||
|
||||
@override
|
||||
String get spoofFieldAppVersion => 'App version';
|
||||
|
||||
@override
|
||||
String get spoofFieldBuildNumber => 'Build number';
|
||||
|
||||
@override
|
||||
String get spoofFieldArchitecture => 'Architecture';
|
||||
|
||||
@override
|
||||
String get spoofButtonGenerate => 'Generate';
|
||||
|
||||
@override
|
||||
String get spoofButtonApply => 'Apply';
|
||||
|
||||
@override
|
||||
String get spoofDialogUnsureTitle => 'Are you sure?';
|
||||
|
||||
@override
|
||||
String get spoofDialogUnsureContent =>
|
||||
'The app may become unstable due to API incompatibility';
|
||||
|
||||
@override
|
||||
String get spoofDialogCancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get spoofDialogYes => 'Yes';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyTitle => 'Apply settings?';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyContent => 'Need to reconnect the app, ok?';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyDeny => 'No';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyConfirm => 'Ok!';
|
||||
|
||||
@override
|
||||
String spoofErrorApplyFailed(String error) {
|
||||
return 'Failed to apply settings: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get profileMenuSpoof => 'Spoofing';
|
||||
}
|
||||
|
||||
@@ -12,7 +12,8 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get loginTitle => 'Войдите в Komet';
|
||||
|
||||
@override
|
||||
String get loginSubtitle => 'Проверьте код страны и введите свой\nномер телефона.';
|
||||
String get loginSubtitle =>
|
||||
'Проверьте код страны и введите свой\nномер телефона.';
|
||||
|
||||
@override
|
||||
String get loginCountry => 'Страна';
|
||||
@@ -42,10 +43,11 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get loginDone => 'Готово';
|
||||
|
||||
@override
|
||||
String get loginReadTermsNotification => 'Сначала прочитайте условия использования';
|
||||
String get loginReadTermsNotification =>
|
||||
'Сначала прочитайте условия использования';
|
||||
|
||||
@override
|
||||
String get loginSpoofRedacted => 'Подделка спуфа';
|
||||
String get loginSpoofRedacted => 'Подмена данных';
|
||||
|
||||
@override
|
||||
String get loginProxy => 'Прокси';
|
||||
@@ -69,7 +71,8 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get serverUseDefault => 'Сбросить к умолчанию';
|
||||
|
||||
@override
|
||||
String get serverInvalidHostOrPort => 'Укажите корректный хост и порт (1–65535)';
|
||||
String get serverInvalidHostOrPort =>
|
||||
'Укажите корректный хост и порт (1–65535)';
|
||||
|
||||
@override
|
||||
String get serverSettingsSaved => 'Настройки сервера применены';
|
||||
@@ -102,7 +105,8 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get selectCountrySearchHint => 'Поиск страны…';
|
||||
|
||||
@override
|
||||
String get codeConfirmationSmsSent => 'Мы отправили SMS с кодом подтверждения на ваш номер телефона.';
|
||||
String get codeConfirmationSmsSent =>
|
||||
'Мы отправили SMS с кодом подтверждения на ваш номер телефона.';
|
||||
|
||||
@override
|
||||
String codeResendInSeconds(int seconds) {
|
||||
@@ -149,5 +153,122 @@ class AppLocalizationsRu extends AppLocalizations {
|
||||
String get proxySettingsSaved => 'Настройки прокси применены';
|
||||
|
||||
@override
|
||||
String get proxyInvalidHostOrPort => 'Укажите корректный хост и порт прокси (1–65535)';
|
||||
String get proxyInvalidHostOrPort =>
|
||||
'Укажите корректный хост и порт прокси (1–65535)';
|
||||
|
||||
@override
|
||||
String get spoofScreenTitle => 'Подмена данных сессии';
|
||||
|
||||
@override
|
||||
String get spoofInfoHint =>
|
||||
'Нажмите \"Сгенерировать\":\n• Короткое нажатие: случайный пресет.\n• Длинное нажатие: реальные данные.';
|
||||
|
||||
@override
|
||||
String get spoofMethodTitle => 'Метод подмены';
|
||||
|
||||
@override
|
||||
String get spoofMethodPartial => 'Частичный';
|
||||
|
||||
@override
|
||||
String get spoofMethodFull => 'Полный';
|
||||
|
||||
@override
|
||||
String get spoofMethodPartialDescription =>
|
||||
'Рекомендуемый метод. Используются случайные данные, но ваш реальный часовой пояс и локаль для большей правдоподобности.';
|
||||
|
||||
@override
|
||||
String get spoofMethodFullDescription =>
|
||||
'Все данные, включая часовой пояс и локаль, генерируются случайно. Использование этого метода на ваш страх и риск!';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeTitle => 'Тип устройства';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeDescription =>
|
||||
'Выберите тип устройства для генерации пресетов. При нажатии \"Сгенерировать\" будут использоваться только пресеты выбранного типа.';
|
||||
|
||||
@override
|
||||
String get spoofDeviceTypeLabel => 'Тип устройства';
|
||||
|
||||
@override
|
||||
String get spoofMainSectionTitle => 'Основные данные';
|
||||
|
||||
@override
|
||||
String get spoofFieldDeviceName => 'Имя устройства';
|
||||
|
||||
@override
|
||||
String get spoofFieldOsVersion => 'Версия ОС';
|
||||
|
||||
@override
|
||||
String get spoofRegionalSectionTitle => 'Региональные данные';
|
||||
|
||||
@override
|
||||
String get spoofFieldScreen => 'Разрешение экрана';
|
||||
|
||||
@override
|
||||
String get spoofFieldTimezone => 'Часовой пояс';
|
||||
|
||||
@override
|
||||
String get spoofFieldLocale => 'Локаль';
|
||||
|
||||
@override
|
||||
String get spoofIdentifiersSectionTitle => 'Идентификаторы';
|
||||
|
||||
@override
|
||||
String get spoofIdentifiersDescription =>
|
||||
'mt_instanceid и clientSessionId генерируются автоматически при каждом запуске приложения. Изменить можно только Device ID.';
|
||||
|
||||
@override
|
||||
String get spoofFieldDeviceId => 'ID Устройства';
|
||||
|
||||
@override
|
||||
String get spoofRegenerateIdTooltip => 'Сгенерировать новый ID';
|
||||
|
||||
@override
|
||||
String get spoofFieldAppVersion => 'Версия приложения';
|
||||
|
||||
@override
|
||||
String get spoofFieldBuildNumber => 'Build Number';
|
||||
|
||||
@override
|
||||
String get spoofFieldArchitecture => 'Архитектура';
|
||||
|
||||
@override
|
||||
String get spoofButtonGenerate => 'Сгенерировать';
|
||||
|
||||
@override
|
||||
String get spoofButtonApply => 'Применить';
|
||||
|
||||
@override
|
||||
String get spoofDialogUnsureTitle => 'Ты уверен?';
|
||||
|
||||
@override
|
||||
String get spoofDialogUnsureContent =>
|
||||
'Приложение может начать работать нестабильно из-за несовместимости API';
|
||||
|
||||
@override
|
||||
String get spoofDialogCancel => 'Отмена';
|
||||
|
||||
@override
|
||||
String get spoofDialogYes => 'Да';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyTitle => 'Применить настройки?';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyContent => 'Нужно перезайти в приложение, ок?';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyDeny => 'Не';
|
||||
|
||||
@override
|
||||
String get spoofDialogApplyConfirm => 'Ок!';
|
||||
|
||||
@override
|
||||
String spoofErrorApplyFailed(String error) {
|
||||
return 'Ошибка при применении настроек: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get profileMenuSpoof => 'Подмена данных';
|
||||
}
|
||||
|
||||
+46
-2
@@ -12,7 +12,7 @@
|
||||
"loginEdit": "Изменить",
|
||||
"loginDone": "Готово",
|
||||
"loginReadTermsNotification": "Сначала прочитайте условия использования",
|
||||
"loginSpoofRedacted": "Подделка спуфа",
|
||||
"loginSpoofRedacted": "Подмена данных",
|
||||
"loginProxy": "Прокси",
|
||||
"loginChangeServer": "Смена сервера",
|
||||
"serverSettingsTitle": "Сервер",
|
||||
@@ -54,5 +54,49 @@
|
||||
"proxyApply": "Применить и переподключиться",
|
||||
"proxyDisable": "Отключить прокси",
|
||||
"proxySettingsSaved": "Настройки прокси применены",
|
||||
"proxyInvalidHostOrPort": "Укажите корректный хост и порт прокси (1–65535)"
|
||||
"proxyInvalidHostOrPort": "Укажите корректный хост и порт прокси (1–65535)",
|
||||
|
||||
"spoofScreenTitle": "Подмена данных сессии",
|
||||
"spoofInfoHint": "Нажмите \"Сгенерировать\":\n• Короткое нажатие: случайный пресет.\n• Длинное нажатие: реальные данные.",
|
||||
"spoofMethodTitle": "Метод подмены",
|
||||
"spoofMethodPartial": "Частичный",
|
||||
"spoofMethodFull": "Полный",
|
||||
"spoofMethodPartialDescription": "Рекомендуемый метод. Используются случайные данные, но ваш реальный часовой пояс и локаль для большей правдоподобности.",
|
||||
"spoofMethodFullDescription": "Все данные, включая часовой пояс и локаль, генерируются случайно. Использование этого метода на ваш страх и риск!",
|
||||
"spoofDeviceTypeTitle": "Тип устройства",
|
||||
"spoofDeviceTypeDescription": "Выберите тип устройства для генерации пресетов. При нажатии \"Сгенерировать\" будут использоваться только пресеты выбранного типа.",
|
||||
"spoofDeviceTypeLabel": "Тип устройства",
|
||||
"spoofMainSectionTitle": "Основные данные",
|
||||
"spoofFieldDeviceName": "Имя устройства",
|
||||
"spoofFieldOsVersion": "Версия ОС",
|
||||
"spoofRegionalSectionTitle": "Региональные данные",
|
||||
"spoofFieldScreen": "Разрешение экрана",
|
||||
"spoofFieldTimezone": "Часовой пояс",
|
||||
"spoofFieldLocale": "Локаль",
|
||||
"spoofIdentifiersSectionTitle": "Идентификаторы",
|
||||
"spoofIdentifiersDescription": "mt_instanceid и clientSessionId генерируются автоматически при каждом запуске приложения. Изменить можно только Device ID.",
|
||||
"spoofFieldDeviceId": "ID Устройства",
|
||||
"spoofRegenerateIdTooltip": "Сгенерировать новый ID",
|
||||
"spoofFieldAppVersion": "Версия приложения",
|
||||
"spoofFieldBuildNumber": "Build Number",
|
||||
"spoofFieldArchitecture": "Архитектура",
|
||||
"spoofButtonGenerate": "Сгенерировать",
|
||||
"spoofButtonApply": "Применить",
|
||||
"spoofDialogUnsureTitle": "Ты уверен?",
|
||||
"spoofDialogUnsureContent": "Приложение может начать работать нестабильно из-за несовместимости API",
|
||||
"spoofDialogCancel": "Отмена",
|
||||
"spoofDialogYes": "Да",
|
||||
"spoofDialogApplyTitle": "Применить настройки?",
|
||||
"spoofDialogApplyContent": "Нужно перезайти в приложение, ок?",
|
||||
"spoofDialogApplyDeny": "Не",
|
||||
"spoofDialogApplyConfirm": "Ок!",
|
||||
"spoofErrorApplyFailed": "Ошибка при применении настроек: {error}",
|
||||
"@spoofErrorApplyFailed": {
|
||||
"placeholders": {
|
||||
"error": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"profileMenuSpoof": "Подмена данных"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user