import 'package:flutter/widgets.dart'; import '../providers/locale_provider.dart'; /// 轻量级国际化助手。 /// /// 覆盖底部导航、首页、设备、门店、管理、设置、激活码、用户、公司介绍等 /// 高频界面文案。后续业务模块继续在此补充。 /// /// 用法: /// ```dart /// final t = AppLocalizations.of(context); /// Text(t.home); /// ``` class AppLocalizations { AppLocalizations(this._locale); final AppLocale _locale; static AppLocalizations of(BuildContext context) { final locale = Localizations.of(context, AppLocale); return AppLocalizations(locale ?? AppLocale.zh); } String _pick(String zh, String en) => _locale == AppLocale.en ? en : zh; /// 当前是否为英文模式。 bool get isEnglish => _locale == AppLocale.en; // ============ 底部导航 ============ String get home => _pick('首页', 'Home'); String get devices => _pick('设备', 'Devices'); String get stores => _pick('门店', 'Stores'); String get admin => _pick('管理', 'Admin'); String get profile => _pick('我的', 'Profile'); // ============ 设置 ============ String get orientationMode => _pick('显示方向', 'Display Orientation'); String get orientationSystem => _pick('跟随系统', 'System'); String get orientationPortrait => _pick('竖屏', 'Portrait'); String get orientationLandscape => _pick('横屏', 'Landscape'); // ============ 首页 ============ /// AppBar / 顶部栏大标题。 String get appTitle => _pick('云定制主页运营平台', '云定制主页运营平台'); /// 首页品牌横幅 / 登录页主标题。 String get appHeroTitle => _pick('云定制主页运营助手', '云定制主页运营助手'); /// 登录页副标题。 String get appSubtitle => _pick('Mobile Management', 'Mobile Management'); String get totalDevices => _pick('设备总数', 'Total Devices'); String get totalStores => _pick('门店总数', 'Total Stores'); String get onlineDevices => _pick('在线设备', 'Online Devices'); String get offlineDevices => _pick('离线设备', 'Offline Devices'); String get quickActions => _pick('快捷操作', 'Quick Actions'); String get systemManagement => _pick('系统管理', 'System Management'); String get mediaManagement => _pick('媒资管理', 'Media Management'); // ============ 通用 ============ String get loading => _pick('加载中…', 'Loading…'); String get retry => _pick('重试', 'Retry'); String get save => _pick('保存', 'Save'); String get cancel => _pick('取消', 'Cancel'); String get confirm => _pick('确认', 'Confirm'); String get reset => _pick('重置', 'Reset'); String get edit => _pick('编辑', 'Edit'); String get delete => _pick('删除', 'Delete'); String get add => _pick('新增', 'Add'); String get search => _pick('搜索', 'Search'); String get back => _pick('返回', 'Back'); String get yes => _pick('是', 'Yes'); String get no => _pick('否', 'No'); String get unknown => _pick('未知', 'Unknown'); String get none => _pick('无', 'None'); String get notGrouped => _pick('未分组', 'Not Grouped'); String get all => _pick('全部', 'All'); String get noData => _pick('暂无数据', 'No data'); String get noMoreData => _pick('没有更多数据', 'No more data'); String get saved => _pick('保存成功', 'Saved'); String get saveFailed => _pick('保存失败', 'Save failed'); String get deleted => _pick('删除成功', 'Deleted'); String get deleteFailed => _pick('删除失败', 'Delete failed'); String get copied => _pick('已复制', 'Copied'); String get pleaseSelect => _pick('请选择', 'Please select'); // ============ 设置页 ============ String get settings => _pick('设置', 'Settings'); String get themeMode => _pick('主题模式', 'Theme'); String get language => _pick('语言', 'Language'); String get changePassword => _pick('修改密码', 'Change Password'); String get about => _pick('关于', 'About'); String get logout => _pick('退出登录', 'Log Out'); String get account => _pick('账号', 'Account'); String get themeDark => _pick('深色', 'Dark'); String get themeLight => _pick('浅色', 'Light'); String get themeSystem => _pick('跟随系统', 'System'); String get passwordDialogTitle => _pick('修改登录密码', 'Change Login Password'); String get oldPassword => _pick('原密码', 'Old Password'); String get newPassword => _pick('新密码', 'New Password'); String get confirmNewPassword => _pick('确认新密码', 'Confirm New Password'); String get pleaseFillPassword => _pick('请填写原密码和新密码', 'Please fill in old and new passwords'); String get passwordsDoNotMatch => _pick('两次输入的新密码不一致', 'New passwords do not match'); String get passwordChangeSuccess => _pick('密码修改成功,请重新登录', 'Password changed, please log in again'); String passwordChangeFailed(String error) => _pick('修改失败:$error', 'Change failed: $error'); // ============ 管理页菜单 ============ String get deviceManagement => _pick('设备管理', 'Device Management'); String get activationCode => _pick('激活码', 'Activation Code'); String get deviceLimit => _pick('设备上限', 'Device Limit'); String get units => _pick('台', 'Units'); String get storeConfig => _pick('门店配置', 'Store Config'); String get userManagement => _pick('用户管理', 'User Management'); String get companyIntro => _pick('公司介绍', 'Company Intro'); // ============ 设备管理 ============ String get deviceList => _pick('设备列表', 'Device List'); String get deviceDetails => _pick('设备详情', 'Device Details'); String get searchDeviceHint => _pick('搜索设备MAC / 房号', 'Search MAC / room number'); String get searchModelHint => _pick('型号', 'Model'); String get scanQueryDevice => _pick('扫码查询设备', 'Scan to Query'); String get scanActivateDevice => _pick('扫码激活新设备', 'Scan to Activate'); String get scanBindDevice => _pick('扫码绑定设备', 'Scan to Bind'); String get scanTitleActivate => _pick('扫码激活新设备', 'Scan to Activate Device'); String get scanTitleBind => _pick('扫码绑定设备', 'Scan to Bind Device'); String get scanTitleQuery => _pick('扫码查询设备', 'Scan to Query Device'); String get scanHintActivate => _pick('将新设备二维码放入框内以激活', 'Place the new device QR code in the frame to activate'); String get scanHintBind => _pick('将二维码放入框内以绑定设备', 'Place the QR code in the frame to bind the device'); String get scanHintQuery => _pick('将设备二维码放入框内以查询', 'Place the device QR code in the frame to query'); String get cameraPermissionDenied => _pick('未获得相机权限', 'Camera permission denied'); String get cameraPermissionDeniedHint => _pick('请在系统设置中开启后重试', 'Please enable camera permission in system settings and try again'); String get cameraInitializing => _pick('正在初始化相机…', 'Initializing camera…'); String get cameraUnavailable => _pick('相机不可用', 'Camera unavailable'); String cameraOpenFailed(String code) => _pick('相机打开失败:$code', 'Failed to open camera: $code'); String get scanConfirmActivateTitle => _pick('确认激活设备', 'Confirm Device Activation'); String get scanConfirmBindTitle => _pick('确认绑定', 'Confirm Binding'); String scanConfirmContent(String storeName, String groupId, String payload) => _pick( '将设备绑定到门店「$storeName」' '${groupId.isNotEmpty ? ' / 分组 $groupId' : ''}?\n\n' '二维码内容:$payload', 'Bind device to store "$storeName"' '${groupId.isNotEmpty ? ' / Group $groupId' : ''}?\n\n' 'QR code content: $payload', ); String get scanActivate => _pick('激活', 'Activate'); String get scanBind => _pick('绑定', 'Bind'); String get scanDeviceNotFound => _pick('未找到设备,请确认二维码内容', 'Device not found, please check the QR code content'); String get scanPayloadUnrecognized => _pick( '无法识别该二维码,请扫描设备二维码或确认二维码内容', 'Unrecognized QR code. Please scan a device QR code'); String scanDeviceNotReady(String identifier) => _pick( '未找到对应设备($identifier)。设备可能尚未联网或同步,请确认设备已开机联网、已激活并归属当前账号后重试', 'No matching device found ($identifier). The device may not be online or synced yet. Please confirm it is powered on, connected, activated and assigned to this account, then retry'); String scanQueryFailed(String error) => _pick('查询失败:$error', 'Query failed: $error'); String scanLoadStoresFailed(String error) => _pick('加载门店失败:$error', 'Failed to load stores: $error'); String get scanNoStores => _pick('暂无可选门店,请先在门店管理中创建', 'No stores available. Please create one in Store Management first'); String get scanSelectStoreTitle => _pick('选择目标门店', 'Select Target Store'); String get scanActivateSuccess => _pick('设备已激活', 'Device activated'); String get scanBindSuccess => _pick('设备已绑定', 'Device bound'); String get scanPayloadNoMac => _pick('未能从二维码中识别到 MAC 地址,请检查二维码内容', 'Could not find MAC address in QR code'); String scanLoadGroupsFailed(String error) => _pick('加载分组失败:$error', 'Failed to load groups: $error'); String scanNoGroups(String storeName) => _pick('门店「$storeName」暂无设备分组,请先在设备分组中创建', 'Store "$storeName" has no device groups. Please create one first'); String get scanSelectGroupTitle => _pick('选择目标分组', 'Select Target Group'); String scanBindFailed(String error) => _pick('绑定失败:$error', 'Binding failed: $error'); // ============ 扫码绑定表单(页面内表单) ============ String get scanGroupLabel => _pick('门店分组', 'Store Group'); String get scanStoreRequired => _pick('请先选择门店', 'Please select a store first'); String get scanGroupRequired => _pick('请选择门店分组', 'Please select a store group'); String get scanRoomRequired => _pick('请输入房号', 'Please enter room number'); String get scanRoomInvalid => _pick( '房号格式不正确(仅限中英文、数字、连字符、斜杠,长度 1-20)', 'Invalid room number (letters/digits/hyphen/slash only, 1-20 chars)'); // 房号改为选填:标签与提示都标明「选填」,避免用户误以为必填。 String get roomNoOptional => _pick('房号(选填)', 'Room Number (optional)'); String get scanRoomHint => _pick('选填,如 801、A101、3楼', 'Optional, e.g. 801, A101, 3rd floor'); String get scanRescan => _pick('重新扫码', 'Scan Again'); String get scanFormInvalid => _pick('请完善门店与门店分组后再提交', 'Please complete store and store group'); String get scanFormDeviceTitle => _pick('已识别设备', 'Recognized Device'); String get sendCommand => _pick('下发指令', 'Send Command'); String get editGroup => _pick('修改分组', 'Edit Group'); String get macAddress => _pick('MAC 地址', 'MAC Address'); String get ipAddress => _pick('IP 地址', 'IP Address'); String get belongStore => _pick('所属门店', 'Store'); String get belongGroup => _pick('所属分组', 'Group'); String get roomNo => _pick('房号', 'Room No.'); String deviceModel(String model) => _pick('型号:$model', 'Model: $model'); String deviceSubtitleStore(String name) => _pick('门店:$name', 'Store: $name'); String deviceSubtitleMac(String mac) => _pick('MAC:$mac', 'MAC: $mac'); String deviceSubtitleRoom(String room) => _pick('房号:$room', 'Room: $room'); String get deviceSubtitleNotSet => _pick('未设置', 'Not set'); String get location => _pick('位置', 'Location'); String get operatingSystem => _pick('操作系统', 'OS'); String get uptime => _pick('运行时长', 'Uptime'); // ============ 设备详情区块 ============ String get basicInfo => _pick('基本信息', 'Basic Info'); String get configParams => _pick('配置参数', 'Config Params'); String get networkInfo => _pick('网络信息', 'Network Info'); String get runtimeData => _pick('运行时数据', 'Runtime Data'); String get deviceName => _pick('设备名称', 'Device Name'); String get deviceId => _pick('设备 ID', 'Device ID'); String get modelLabel => _pick('型号', 'Model'); String get deviceSnLabel => _pick('设备序列号', 'Device SN'); String get deviceUidLabel => _pick('设备 UID', 'Device UID'); String get lastActiveTime => _pick('最后活跃时间', 'Last Active Time'); String get minutesAgo => _pick('分钟前', 'min ago'); String get cpuUsage => _pick('CPU 使用率', 'CPU Usage'); String get memoryUsage => _pick('内存使用率', 'Memory Usage'); String get diskUsage => _pick('磁盘使用率', 'Disk Usage'); String get networkRxTx => _pick('网络(收/发)', 'Network (Rx/Tx)'); String get showRuntimeMetrics => _pick('显示运行指标', 'Show Runtime Metrics'); String get showRuntimeMetricsHint => _pick('开启后在设备详情页展示 CPU、内存、磁盘、网络指标', 'Show CPU, memory, disk and network metrics on device detail'); String deviceListLoadFailed(String error) => _pick('设备列表加载失败:$error', 'Failed to load device list: $error'); String get noMatchedDevices => _pick('没有匹配的设备', 'No matched devices'); String get allStores => _pick('全部门店', 'All Stores'); String get selectStore => _pick('选择门店', 'Select Store'); String get groupId => _pick('所属分组 ID', 'Group ID'); String get groupIdHint => _pick('填写设备分组标识,如 g-core', 'Enter device group identifier, e.g. g-core'); String get saveSuccess => _pick('已保存', 'Saved successfully'); String get groupListLoading => _pick('加载分组列表…', 'Loading groups…'); // ============ 设备状态 ============ String get statusOnline => _pick('在线', 'Online'); String get statusOffline => _pick('离线', 'Offline'); String get statusWarning => _pick('告警', 'Warning'); String get statusNormal => _pick('正常', 'Normal'); String get statusDisabled => _pick('禁用', 'Disabled'); String deviceStatusLabel(DeviceStatusKey status) { switch (status) { case DeviceStatusKey.online: return statusOnline; case DeviceStatusKey.offline: return statusOffline; case DeviceStatusKey.warning: return statusWarning; } } // ============ 指令下发 ============ String get sendCommandTitle => _pick('下发指令', 'Send Command'); String get sendOrgCommandTitle => _pick('下发门店指令', 'Send Store Command'); String get commandType => _pick('指令类型', 'Command Type'); String get commandConfirmTitle => _pick('确认下发', 'Confirm Send'); String commandConfirmContent(String label) => _pick('确定要向该设备下发「$label」指令吗?', 'Are you sure you want to send the "$label" command?'); String commandSent(String target, String label) => _pick('已向$target下发「$label」指令(后端已接收,不代表设备已执行)', 'Command "$label" sent to $target (accepted by server, not yet confirmed by device)'); String get commandSendFailed => _pick('指令下发失败', 'Failed to send command'); String get pleaseInput => _pick('请输入', 'Please enter'); String get volumeRangeHint => _pick('请输入 0~100 的整数音量', 'Please enter an integer volume between 0 and 100'); String get maxVolume => _pick('最大音量', 'Max Volume'); String get commandOfflineWarning => _pick('该设备当前离线(或心跳已超时),指令可能不会立即生效;设备重新上报心跳后才会执行。', 'This device is offline (or its heartbeat timed out). The command may not take effect immediately; it will run after the device reconnects.'); String get commandOfflineConfirm => _pick('仍然下发', 'Send Anyway'); String get commandMacMissing => _pick('该设备缺少 MAC 地址,无法按 MAC 下发指令,请改用门店批量下发。', 'This device has no MAC address, so a MAC-targeted command cannot be sent. Use store-level delivery instead.'); String deviceCommandLabel(String cmd) { return _pick( const { 'powerOff': '关机', 'reboot': '重启', 'screenshot': '截屏', 'themeUpdate': '主题更新', 'versionUpdate': '版本更新', 'marqueeUpdate': '滚动字幕更新', 'weatherUpdate': '更新天气信息', 'mediaZoneVol': '媒体区域音量', 'defaultVol': '默认音量', 'themeClear': '清除主题缓存', 'cacheClear': '清除缓存', 'storeExpire': '门店到期', 'storeDisable': '门店禁用', 'passwordUpdate': '修改设置密码', 'worldAd': '获取世界广告', }[cmd] ?? cmd, const { 'powerOff': 'Power Off', 'reboot': 'Reboot', 'screenshot': 'Screenshot', 'themeUpdate': 'Theme Update', 'versionUpdate': 'Version Update', 'marqueeUpdate': 'Marquee Update', 'weatherUpdate': 'Update Weather', 'mediaZoneVol': 'Media Zone Volume', 'defaultVol': 'Default Volume', 'themeClear': 'Clear Theme Cache', 'cacheClear': 'Clear Cache', 'storeExpire': 'Store Expired', 'storeDisable': 'Store Disabled', 'passwordUpdate': 'Change Settings Password', 'worldAd': 'Fetch World Ads', }[cmd] ?? cmd, ); } String deviceCommandInputLabel(String cmd) { if (cmd == 'passwordUpdate') return _pick('新密码', 'New Password'); return _pick('音量(0-100)', 'Volume (0-100)'); } // ============ 门店管理 ============ String get storeManagement => _pick('门店管理', 'Store Management'); String get storeCommands => _pick('门店指令', 'Store Commands'); String get searchStoreHint => _pick('搜索门店名称', 'Search store name'); String get storeDeleteConfirmTitle => _pick('删除门店', 'Delete Store'); String storeDeleteConfirmContent(String name) => _pick('确定要删除门店「$name」吗?', 'Are you sure you want to delete store "$name"?'); String get storeDeleted => _pick('门店已删除', 'Store deleted'); String get loadFailed => _pick('加载失败', 'Load failed'); String get storeId => _pick('门店ID', 'Store ID'); String get address => _pick('地址', 'Address'); String get contactPhone => _pick('联系电话', 'Contact Phone'); String get expireTime => _pick('到期时间', 'Expire Time'); String get expired => _pick('已过期', 'Expired'); String get noExpireTime => _pick('无到期时间', 'No expire date'); String get createTime => _pick('创建时间', 'Create Time'); String get storeName => _pick('门店名称', 'Store Name'); String get storeNameRequired => _pick('请输入门店名称', 'Please enter store name'); String get region => _pick('所在地区', 'Region'); String get regionHint => _pick('请选择省 / 市 / 区', 'Please select province / city / district'); String get addressDetail => _pick('详细地址', 'Detailed Address'); String get addressDetailHint => _pick('街道 / 门牌号等', 'Street / house number'); String get interfaceConfig => _pick('界面配置', 'Interface Config'); String get themeSkin => _pick('主题皮肤', 'Theme Skin'); String get themeCurrent => _pick('当前', 'Current'); String get themeUnnamed => _pick('未命名主题', 'Unnamed Theme'); String get noInterfaceConfig => _pick('当前门店暂无设备分组主题', 'No device group themes for this store'); String get editStore => _pick('编辑门店', 'Edit Store'); String get addStore => _pick('新增门店', 'Add Store'); String get create => _pick('创建', 'Create'); String get sampleStore => _pick('示例门店', 'Sample Store'); String get parentOrg => _pick('所属组织', 'Parent Organization'); String get parentOrgRequired => _pick('请选择所属组织', 'Please select parent organization'); String get regionRequired => _pick('请选择所在地区', 'Please select region'); String get storeUpdatedPlaceholder => _pick('门店已更新(本地占位)', 'Store updated (local placeholder)'); String get storeCreatedPlaceholder => _pick('门店已创建(本地占位)', 'Store created (local placeholder)'); // ============ 激活码管理 ============ String get activationCodeManagement => _pick('激活码管理', 'Activation Code Management'); String get noStoreAvailable => _pick('暂无可选门店', 'No stores available'); String get pleaseSelectStoreFirst => _pick('请先选择门店', 'Please select a store first'); String get currentActivationCode => _pick('当前激活码', 'Current Activation Code'); String get noActivationCode => _pick('暂无激活码信息', 'No activation code info'); String get generateActivationCode => _pick('生成激活码', 'Generate Activation Code'); String get resetActivationCode => _pick('重置激活码', 'Reset Activation Code'); String get resetActivationCodeConfirm => _pick('重置后原激活码将失效,确定要继续吗?', 'The original code will become invalid after reset. Continue?'); String get activationCodeGenerated => _pick('激活码已生成', 'Activation code generated'); String get activationCodeReset => _pick('激活码已重置', 'Activation code reset'); String get generateFailed => _pick('生成失败', 'Generate failed'); String get resetFailed => _pick('重置失败', 'Reset failed'); String get activationCodeResetSuccess => _pick('激活码已重置', 'Activation code reset'); String activationCodeResetFailed(String error) => _pick('激活码重置失败:$error', 'Activation code reset failed: $error'); String get maxActivateCount => _pick('最大激活数', 'Max Activations'); String get activatedCount => _pick('已激活数', 'Activated Count'); String get copy => _pick('复制', 'Copy'); String get generate => _pick('生成', 'Generate'); String get activationCodeCopied => _pick('激活码已复制', 'Activation code copied'); String get generateActivationCodeHint => _pick( '将为当前门店生成新的激活码,原有激活码将被替换。', 'A new activation code will be generated for this store, replacing the existing one.'); String activationCodeLoadFailed(String error) => _pick('激活码加载失败:$error', 'Failed to load activation code: $error'); String generateFailedWithError(String error) => _pick('生成失败:$error', 'Generate failed: $error'); String get activationCodeNoCodeHint => _pick('无激活码,请点击「生成激活码」', 'No activation code, please tap "Generate Activation Code"'); String get maxActivationCountLabel => _pick('最大激活次数', 'Max Activation Count'); String get maxActivationCountHint => _pick('该激活码最多可激活的设备数量', 'Maximum number of devices this code can activate'); String get positiveIntegerRequired => _pick('请输入大于 0 的整数', 'Please enter an integer greater than 0'); // 门店表单中的激活码/终端数 String get terminalCountLabel => _pick('终端数', 'Terminal Count'); String get terminalCountHint => _pick('该门店允许激活的终端数量', 'Number of terminals allowed'); String get maxTerminalCount => _pick('最大终端数', 'Max Terminals'); String get usedTerminalCount => _pick('已用终端数', 'Used Terminals'); String get createActivationCode => _pick('创建激活码', 'Create Activation Code'); String get activationCodeWillAutoGenerate => _pick('保存门店后将自动生成激活码', 'Activation code will be auto-generated after saving the store'); String get activeActivationCode => _pick('当前激活码', 'Current Activation Code'); String get noActiveActivationCode => _pick('暂无正在使用的激活码', 'No activation code currently in use'); String get activationCodeGenerateHint => _pick('每次点击仅生成一个对应激活码', 'Each tap generates one activation code'); String storeSavedActivationFailed(String error) => _pick('门店已保存,但激活码生成失败:$error', 'Store saved, but activation code generation failed: $error'); String storeListLoadFailed(String error) => _pick('门店列表加载失败:$error', 'Failed to load store list: $error'); // ============ 用户管理 ============ String get username => _pick('用户名', 'Username'); String get usernameRequired => _pick('请输入用户名', 'Please enter username'); String get email => _pick('邮箱', 'Email'); String get mobile => _pick('手机号', 'Mobile'); String get password => _pick('密码', 'Password'); String get passwordEditHint => _pick('不修改请留空', 'Leave blank to keep unchanged'); String get passwordRequired => _pick('请输入密码', 'Please enter password'); String get confirmPassword => _pick('确认密码', 'Confirm Password'); String get confirmPasswordHint => _pick('请再次输入密码', 'Please enter the password again'); String get confirmPasswordRequired => _pick('请输入确认密码', 'Please enter confirm password'); String get role => _pick('角色', 'Role'); String get roleRequired => _pick('请选择角色', 'Please select a role'); String get org => _pick('所属组织', 'Organization'); String get selectOrg => _pick('请选择所属组织', 'Please select an organization'); String get noOrgHint => _pick('暂无可选组织,保留原归属', 'No organizations available, keep original'); String get status => _pick('状态', 'Status'); String get unassigned => _pick('未分配', 'Unassigned'); String get searchUsernameHint => _pick('搜索用户名', 'Search username'); String get searchOrgHint => _pick('搜索组织名称', 'Search organization name'); String get noMatchingOrg => _pick('未找到匹配组织', 'No matching organization'); String get roleLabel => _pick('角色', 'Role'); String get orgLabel => _pick('所属组织', 'Organization'); String get currentAccountInfo => _pick('当前账号信息', 'Current Account Info'); String get passwordNotSaved => _pick('未保存', 'Not saved'); String get noSubordinateAccount => _pick('当前账号暂无下级账号', 'No subordinate accounts'); String get showPassword => _pick('显示密码', 'Show password'); String get hidePassword => _pick('隐藏密码', 'Hide password'); String get editUser => _pick('编辑用户', 'Edit User'); String get addUser => _pick('新增用户', 'Add User'); String get deleteUserConfirmTitle => _pick('确认删除', 'Confirm Delete'); String deleteUserConfirmContent(String name) => _pick('确定要删除用户「$name」吗?', 'Are you sure you want to delete user "$name"?'); String get rolesLoadFailed => _pick('角色列表加载失败', 'Failed to load roles'); // ============ 滚动字幕管理 ============ String get marqueeManagement => _pick('滚动字幕管理', 'Scrolling Subtitle Management'); String get addMarquee => _pick('新增滚动字幕', 'Add Scrolling Subtitle'); String get editMarquee => _pick('编辑滚动字幕', 'Edit Scrolling Subtitle'); String get marqueeContent => _pick('字幕内容', 'Subtitle Content'); String get marqueeContentRequired => _pick('请输入字幕内容', 'Please enter subtitle content'); String get marqueeSpeed => _pick('滚动速度', 'Scroll Speed'); String get marqueeSpeedHint => _pick('像素/秒,建议 30~120', 'pixels/sec, recommended 30-120'); String get marqueeSpeedInvalid => _pick('请选择滚动速度', 'Please select scroll speed'); String get marqueeFontSizeInvalid => _pick('请输入大于 0 的字体大小', 'Please enter a font size greater than 0'); String get marqueeSpeedSlow => _pick('慢', 'Slow'); String get marqueeSpeedSlower => _pick('较慢', 'Slower'); String get marqueeSpeedMedium => _pick('中', 'Medium'); String get marqueeSpeedFaster => _pick('较快', 'Faster'); String get marqueeSpeedFast => _pick('快', 'Fast'); String get marqueeGradeDanger => _pick('危险', 'Danger'); String get marqueeGradeUrgent => _pick('紧急', 'Urgent'); String get marqueeGradeNormal => _pick('普通', 'Normal'); String get targetStore => _pick('目标门店', 'Target Store'); String get filterByStore => _pick('按门店筛选', 'Filter by Store'); String get searchMarqueeHint => _pick('搜索字幕内容或门店', 'Search subtitle content or store'); String get noMarqueeData => _pick('暂无滚动字幕', 'No scrolling subtitles'); String get marqueeStatus => _pick('状态', 'Status'); String get marqueeStatusEnabled => _pick('启用', 'Enabled'); String get marqueeStatusDisabled => _pick('禁用', 'Disabled'); String get marqueeStatusPending => _pick('待下发', 'Pending'); String get marqueeStatusDispatched => _pick('已下发', 'Dispatched'); String get dispatch => _pick('下发', 'Dispatch'); String get cancelDispatch => _pick('取消下发', 'Cancel Dispatch'); String get marqueeDispatched => _pick('字幕已下发', 'Subtitle dispatched'); String get marqueeDispatchFailed => _pick('字幕下发失败', 'Failed to dispatch subtitle'); String get marqueeDispatchCancelled => _pick('已取消下发', 'Dispatch cancelled'); String get marqueeCancelFailed => _pick('取消下发失败', 'Failed to cancel dispatch'); String get marqueeFontColor => _pick('字体颜色', 'Font Color'); String get marqueeBackgroundColor => _pick('背景颜色', 'Background Color'); String get marqueeFontSize => _pick('字体大小', 'Font Size'); String get marqueeLevel => _pick('级别', 'Level'); String get marqueeStartTime => _pick('开始时间', 'Start Time'); String get marqueeEndTime => _pick('结束时间', 'End Time'); String get marqueeHour => _pick('时', 'Hour'); String get marqueeMinute => _pick('分', 'Minute'); String get marqueeSecond => _pick('秒', 'Second'); String get marqueeContentPreview => _pick('字幕内容', 'Subtitle Content'); // ============ 公司介绍 ============ String get introCategoryTitle => _pick('公司介绍', 'Company Intro'); String get introStoreFilter => _pick('门店名称', 'Store Name'); String get introAllStores => _pick('全部门店', 'All Stores'); String get introCategoryName => _pick('名称', 'Name'); String get introCategoryTypeCode => _pick('类型编码', 'Type Code'); String get introCategoryEdit => _pick('编辑大类', 'Edit Category'); String get introCategoryAdd => _pick('新增大类', 'Add Category'); String get introSubcategoryEdit => _pick('编辑小类', 'Edit Subcategory'); String get introSubcategoryAdd => _pick('新增小类', 'Add Subcategory'); String get introDetailEdit => _pick('编辑内容', 'Edit Content'); String get introDetailAdd => _pick('新增内容', 'Add Content'); String get introTitle => _pick('标题', 'Title'); String get introTitleRequired => _pick('请输入标题', 'Please enter the title'); String get introDescription => _pick('描述', 'Description'); String get introMediaType => _pick('媒体类型', 'Media Type'); String get introMediaUrl => _pick('媒体地址', 'Media URL'); String get introMediaUrlRequired => _pick('请上传或填写媒体地址', 'Please upload or enter the media URL'); String get introImage => _pick('图片', 'Image'); String get introVideo => _pick('视频', 'Video'); String get introTypeLabel => _pick('类型', 'Type'); String get introStoreLabel => _pick('门店', 'Store'); String get introFilterStores => _pick('筛选门店', 'Filter Stores'); String get introSelectStoresHint => _pick('可多选门店', 'Select multiple stores'); String get introCategoryStore => _pick('所属门店', 'Store'); String get introStoreRequired => _pick('请选择所属门店', 'Please select a store'); String get introCategoryNameRequired => _pick('请输入名称', 'Please enter the name'); String get introCategoryTypeRequired => _pick('请输入类型编码', 'Please enter the type code'); String get introCategoryTypeNoChinese => _pick('类型编码禁止包含中文', 'Type code must not contain Chinese characters'); String get introStoreLoadFailed => _pick('门店列表加载失败,请下拉刷新后重试', 'Failed to load stores, please refresh and retry'); String get introSortOrder => _pick('排序号', 'Sort Order'); String get introEnabled => _pick('启用', 'Enabled'); String get introDisabled => _pick('禁用', 'Disabled'); String get introUploadImage => _pick('上传图片', 'Upload Image'); String get introPickImage => _pick('选择图片', 'Pick Image'); String get introImagePreview => _pick('图片预览', 'Image Preview'); String get introUploading => _pick('上传中…', 'Uploading…'); String get introUploadFailed => _pick('图片上传失败', 'Image upload failed'); String get introInsertImage => _pick('插入图片', 'Insert Image'); String get introSubImageHint => _pick('图片不超过 300KB,建议分辨率 1920×1080', 'Image ≤ 300KB, suggested 1920×1080'); String get introDetailImageHint => _pick('图片不超过 3MB', 'Image ≤ 3MB'); String get introDetailVideoHint => _pick('视频不超过 30MB', 'Video ≤ 30MB'); String get introImageTypeInvalid => _pick('请上传 jpg、png、gif 或 webp 图片', 'Please upload jpg, png, gif or webp image'); String get introVideoTypeInvalid => _pick('请上传 mp4、webm、mov 或 m4v 视频', 'Please upload mp4, webm, mov or m4v video'); String get introFileTooLarge => _pick('文件大小超过限制', 'File exceeds the size limit'); // ============ 地区选择器 ============ String get selectProvince => _pick('选择省份', 'Select Province'); String get selectCity => _pick('选择城市', 'Select City'); String get selectDistrict => _pick('选择区县', 'Select District'); String get selectRegion => _pick('选择地区', 'Select Region'); String get previousLevel => _pick('上一级', 'Previous'); // ============ 运行时长 ============ String formatUptime(int seconds) { final duration = Duration(seconds: seconds); final days = duration.inDays; final hours = duration.inHours % 24; final minutes = duration.inMinutes % 60; final parts = []; if (days > 0) parts.add('$days${_pick('天', 'd')}'); if (hours > 0) parts.add('$hours${_pick('小时', 'h')}'); if (minutes > 0 || parts.isEmpty) { parts.add('$minutes${_pick('分', 'm')}'); } return parts.join(' '); } // ============ 通用状态/操作(后置兼容) ============ String get noOrgId => _pick('该门店缺少组织 ID,无法下发指令', 'This store lacks an organization ID and cannot receive commands'); // ============ 通用删除确认 ============ String get confirmDelete => _pick('确认删除', 'Confirm Delete'); String deleteConfirmContent(String name) => _pick('确定要删除「$name」吗?', 'Are you sure you want to delete "$name"?'); // ============ 渠道商管理 ============ String get channelManagement => _pick('渠道商管理', 'Channel Management'); String get addChannel => _pick('新增渠道', 'Add Channel'); String get editChannel => _pick('编辑渠道商', 'Edit Channel'); String get addSubChannel => _pick('新增子级', 'Add Child'); String get channelName => _pick('名称', 'Name'); String get channelType => _pick('类型', 'Type'); String get channelSort => _pick('排序', 'Sort'); String get channelStatus => _pick('状态', 'Status'); String get channelContactPhone => _pick('联系电话', 'Contact Phone'); String get channelAddress => _pick('地址', 'Address'); String get channelOrgCode => _pick('组织编码', 'Org Code'); String get channelTypeChannel => _pick('渠道', 'Channel'); String get channelTypeAgent => _pick('代理', 'Agent'); String get channelEnabled => _pick('启用', 'Enabled'); String get channelDisabled => _pick('禁用', 'Disabled'); String get channelParent => _pick('上级', 'Parent'); String get channelNameRequired => _pick('请输入名称', 'Please enter a name'); String get searchChannelHint => _pick('搜索渠道/代理商名称', 'Search channel/agent name'); String get channelDetail => _pick('渠道详情', 'Channel Detail'); String get channelExpireTime => _pick('到期时间', 'Expire Time'); String get channelCannotDeleteWithChildren => _pick('存在子集时不允许删除', 'Cannot delete a node that has children'); String get channelFilterStatus => _pick('状态', 'Status'); String get channelSwipeToDelete => _pick('左滑删除', 'Swipe left to delete'); // ============ 渠道版本管理 ============ /// 渠道/代理节点下钻的 App 版本管理入口。 String get channelVersionManage => _pick('版本管理', 'Version'); String get versionName => _pick('版本名', 'Version Name'); String get versionCode => _pick('版本号', 'Version Code'); String get downloadUrlHint => _pick('下载地址', 'Download URL'); String get forceUpdate => _pick('强制更新', 'Force Update'); String get showPopup => _pick('弹窗提示', 'Popup'); String get forceUpdateYes => _pick('是', 'Yes'); String get forceUpdateNo => _pick('否', 'No'); String get addVersion => _pick('新增版本', 'Add Version'); String get editVersion => _pick('编辑版本', 'Edit Version'); String get versionNameRequired => _pick('请输入版本名', 'Please enter a version name'); String get versionCodeRequired => _pick('请输入正整数版本号', 'Please enter a positive integer version code'); String get versionUrlRequired => _pick('请输入下载地址', 'Please enter a download URL'); String get versionUrlInvalid => _pick('请输入以 http(s) 开头的下载地址', 'URL must start with http(s)'); String get versionDeleteConfirm => _pick( '确定删除该版本配置?删除后可重新新增。', 'Delete this version config? You can add it again afterward.'); String get versionDeleted => _pick('版本已删除', 'Version deleted'); String get uploadFile => _pick('上传文件', 'Upload'); String get uploading => _pick('上传中…', 'Uploading…'); String get uploadSuccess => _pick('文件上传成功', 'Uploaded'); String get uploadFailed => _pick('文件上传失败', 'Upload failed'); String get pleaseSelectApk => _pick('请选择 .apk 文件', 'Please select an .apk file'); // ============ 版本更新 ============ String get checkUpdate => _pick('检查更新', 'Check Update'); String get updateAvailable => _pick('发现新版本', 'Update Available'); String get currentVersion => _pick('当前版本', 'Current'); String get latestVersion => _pick('最新版本', 'Latest'); String get downloadUrl => _pick('下载地址', 'Download'); String get updateNow => _pick('立即更新', 'Update Now'); String get updateLater => _pick('稍后', 'Later'); String get updateNoNew => _pick('已是最新版本', 'Already up to date'); String get updateOpenFailed => _pick('无法打开下载地址', 'Failed to open download link'); } /// 设备状态键(避免在模型层引入 BuildContext)。 enum DeviceStatusKey { online, offline, warning }