chore(flow): expand host-return whitelist and add a DEBUG host bundle probe
- Rebuild the return-to-host whitelist from the CN/US top charts plus Apple system apps; drop the canOpenURL pre-check (LSApplicationQueriesSchemes is capped at 50) and let open() report failure. - Never record an OSG bundle id as the host to return to. - DEBUG only: probe the host bundle id through the keyboard arbiter callback and surface the log on a Home test card. Release builds keep the previous behaviour (no host identification).
This commit is contained in:
@@ -112,12 +112,16 @@ final class AppSceneDelegate: NSObject, UIWindowSceneDelegate {
|
||||
MainActor.assumeIsolated {
|
||||
for item in items {
|
||||
// `sourceApplication` is only non-nil when the caller belongs to
|
||||
// the same Apple Developer Team (our own keyboard extension) —
|
||||
// exactly what the host-return whitelist relies on. Record it
|
||||
// ONLY for the `startflow` handoff: overwriting it for every
|
||||
// deep link (e.g. `osgkeyboard://settings`) could point a later
|
||||
// cold-start "return to host" at the wrong app.
|
||||
if let source = item.source, item.url.host == "startflow" {
|
||||
// the same Apple Developer Team, so for the keyboard handoff it is
|
||||
// our own extension, not the app the user was typing in. The
|
||||
// keyboard publishes the real host before opening `startflow`;
|
||||
// never overwrite that with an OSG bundle id. Record it ONLY for
|
||||
// the `startflow` handoff: overwriting it for every deep link
|
||||
// (e.g. `osgkeyboard://settings`) could point a later cold-start
|
||||
// "return to host" at the wrong app.
|
||||
if let source = item.source,
|
||||
item.url.host == "startflow",
|
||||
!HostAppURLRegistry.isOwnBundleId(source) {
|
||||
FlowSessionBridge.setPendingHostBundleId(source)
|
||||
}
|
||||
AppOpenURLRouter.shared.route(item.url)
|
||||
|
||||
@@ -2,6 +2,10 @@
|
||||
// OSGKeyboard · Main App
|
||||
//
|
||||
// Opens a whitelisted host-app URL after a cold-start Flow handoff.
|
||||
//
|
||||
// No `canOpenURL` pre-check: iOS caps `LSApplicationQueriesSchemes` at 50
|
||||
// entries (already spent) and the whitelist is far larger. `open` needs no
|
||||
// declaration and reports failure through its completion instead.
|
||||
|
||||
import OSGKeyboardShared
|
||||
import UIKit
|
||||
@@ -13,12 +17,11 @@ enum HostReturnService {
|
||||
let bundleId = FlowSessionBridge.pendingHostBundleId()
|
||||
guard let entry = HostAppURLRegistry.lookup(bundleId: bundleId),
|
||||
let url = entry.returnURL else {
|
||||
return false
|
||||
}
|
||||
guard UIApplication.shared.canOpenURL(url) else {
|
||||
logReturn(bundleId: bundleId, outcome: "no-entry")
|
||||
return false
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:]) { success in
|
||||
logReturn(bundleId: bundleId, outcome: success ? "opened" : "open-failed")
|
||||
if success {
|
||||
FlowSessionBridge.clearPendingHostBundleId()
|
||||
}
|
||||
@@ -28,7 +31,7 @@ enum HostReturnService {
|
||||
|
||||
@MainActor
|
||||
static func openHost(entry: HostAppEntry) -> Bool {
|
||||
guard let url = entry.returnURL, UIApplication.shared.canOpenURL(url) else {
|
||||
guard let url = entry.returnURL else {
|
||||
return false
|
||||
}
|
||||
UIApplication.shared.open(url, options: [:]) { success in
|
||||
@@ -43,4 +46,10 @@ enum HostReturnService {
|
||||
static func pendingHostEntry() -> HostAppEntry? {
|
||||
HostAppURLRegistry.lookup(bundleId: FlowSessionBridge.pendingHostBundleId())
|
||||
}
|
||||
|
||||
private static func logReturn(bundleId: String?, outcome: String) {
|
||||
#if DEBUG
|
||||
HostBundleProbeLog.append(event: "return", bundleId: bundleId, detail: outcome)
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
// HostBundleProbeCard.swift
|
||||
// OSGKeyboard · Main App
|
||||
//
|
||||
// 临时调试卡片(仅 DEBUG):展示键盘扩展识别到的宿主 bundle ID,
|
||||
// 用于真机验证 iOS 26.4+ 宿主识别。验证结束后删除。
|
||||
|
||||
#if DEBUG
|
||||
import OSGKeyboardShared
|
||||
import SwiftUI
|
||||
|
||||
struct HostBundleProbeCard: View {
|
||||
@Environment(\.themePalette) private var palette: ThemePalette
|
||||
@State private var entries: [HostBundleProbeLog.Entry] = []
|
||||
@State private var draft = ""
|
||||
|
||||
private static let timeFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.dateFormat = "HH:mm:ss.SSS"
|
||||
return formatter
|
||||
}()
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: Spacing.sm) {
|
||||
HStack {
|
||||
Text("宿主识别测试(临时)")
|
||||
.font(TypeStyle.footnote.weight(.semibold))
|
||||
.foregroundStyle(palette.textTertiary)
|
||||
Spacer(minLength: Spacing.xs)
|
||||
Button("清空") {
|
||||
HostBundleProbeLog.clear()
|
||||
reload()
|
||||
}
|
||||
.font(TypeStyle.caption2)
|
||||
.foregroundStyle(palette.accent)
|
||||
}
|
||||
|
||||
// 在 OSG 自己里唤起键盘时,预期识别结果是主 App 的 bundle ID。
|
||||
TextField("点这里唤起 OSG 键盘", text: $draft)
|
||||
.textFieldStyle(.roundedBorder)
|
||||
|
||||
if entries.isEmpty {
|
||||
Text("暂无记录:去其他 App 唤起 OSG 键盘后回到这里查看")
|
||||
.font(TypeStyle.caption2)
|
||||
.foregroundStyle(palette.textTertiary)
|
||||
} else {
|
||||
VStack(alignment: .leading, spacing: 6) {
|
||||
ForEach(entries) { entry in
|
||||
entryRow(entry)
|
||||
}
|
||||
}
|
||||
.textSelection(.enabled)
|
||||
}
|
||||
}
|
||||
.padding(Spacing.md)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.surfaceCard()
|
||||
// 卡片可见期间每秒刷新,在本 App 内唤起键盘时也能实时看到结果。
|
||||
.task {
|
||||
while !Task.isCancelled {
|
||||
reload()
|
||||
try? await Task.sleep(for: .seconds(1))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func entryRow(_ entry: HostBundleProbeLog.Entry) -> some View {
|
||||
VStack(alignment: .leading, spacing: 1) {
|
||||
HStack(spacing: Spacing.xs) {
|
||||
Text(Self.timeFormatter.string(from: entry.date))
|
||||
.foregroundStyle(palette.textTertiary)
|
||||
Text(entry.event)
|
||||
.foregroundStyle(entry.event == "appear" ? palette.textSecondary : palette.accent)
|
||||
if let detail = entry.detail {
|
||||
Text(detail)
|
||||
.foregroundStyle(palette.textTertiary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
.font(.system(size: 11, design: .monospaced))
|
||||
|
||||
if entry.event != "appear" {
|
||||
Text(entry.bundleId ?? "nil")
|
||||
.font(.system(size: 13, weight: .semibold, design: .monospaced))
|
||||
.foregroundStyle(entry.bundleId == nil ? palette.warning : palette.textPrimary)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func reload() {
|
||||
let latest = HostBundleProbeLog.entries()
|
||||
if latest != entries { entries = latest }
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -369,6 +369,10 @@ struct HomeView: View {
|
||||
layout: UsageStatsClusterLayout,
|
||||
compact: Bool
|
||||
) -> some View {
|
||||
#if DEBUG
|
||||
HostBundleProbeCard()
|
||||
#endif
|
||||
|
||||
AccountRewardsCard {
|
||||
path.append(HomeRoute.account)
|
||||
}
|
||||
|
||||
@@ -829,6 +829,9 @@
|
||||
"hostApp.wecom" = "WeCom";
|
||||
"hostApp.dingtalk" = "DingTalk";
|
||||
"hostApp.lark" = "Lark";
|
||||
"hostApp.tencentMeeting" = "Tencent Meeting";
|
||||
"hostApp.qqmail" = "QQ Mail";
|
||||
"hostApp.wps" = "WPS Office";
|
||||
"hostApp.telegram" = "Telegram";
|
||||
"hostApp.whatsapp" = "WhatsApp";
|
||||
"hostApp.line" = "LINE";
|
||||
@@ -836,28 +839,56 @@
|
||||
"hostApp.slack" = "Slack";
|
||||
"hostApp.teams" = "Microsoft Teams";
|
||||
"hostApp.discord" = "Discord";
|
||||
"hostApp.notion" = "Notion";
|
||||
"hostApp.bear" = "Bear";
|
||||
"hostApp.obsidian" = "Obsidian";
|
||||
"hostApp.drafts" = "Drafts";
|
||||
"hostApp.gmail" = "Gmail";
|
||||
"hostApp.outlook" = "Outlook";
|
||||
"hostApp.chrome" = "Chrome";
|
||||
"hostApp.weibo" = "Weibo";
|
||||
"hostApp.xiaohongshu" = "RED";
|
||||
"hostApp.signal" = "Signal";
|
||||
"hostApp.kakaotalk" = "KakaoTalk";
|
||||
"hostApp.viber" = "Viber";
|
||||
"hostApp.zalo" = "Zalo";
|
||||
"hostApp.skype" = "Skype";
|
||||
"hostApp.zoom" = "Zoom";
|
||||
"hostApp.tinder" = "Tinder";
|
||||
"hostApp.notion" = "Notion";
|
||||
"hostApp.bear" = "Bear";
|
||||
"hostApp.obsidian" = "Obsidian";
|
||||
"hostApp.drafts" = "Drafts";
|
||||
"hostApp.things" = "Things";
|
||||
"hostApp.todoist" = "Todoist";
|
||||
"hostApp.evernote" = "Evernote";
|
||||
"hostApp.onenote" = "OneNote";
|
||||
"hostApp.word" = "Microsoft Word";
|
||||
"hostApp.excel" = "Microsoft Excel";
|
||||
"hostApp.gmail" = "Gmail";
|
||||
"hostApp.outlook" = "Outlook";
|
||||
"hostApp.spark" = "Spark";
|
||||
"hostApp.yahooMail" = "Yahoo Mail";
|
||||
"hostApp.googleDocs" = "Google Docs";
|
||||
"hostApp.googleSheets" = "Google Sheets";
|
||||
"hostApp.googleDrive" = "Google Drive";
|
||||
"hostApp.googleTranslate" = "Google Translate";
|
||||
"hostApp.google" = "Google";
|
||||
"hostApp.chrome" = "Chrome";
|
||||
"hostApp.firefox" = "Firefox";
|
||||
"hostApp.edge" = "Edge";
|
||||
"hostApp.chatgpt" = "ChatGPT";
|
||||
"hostApp.claude" = "Claude";
|
||||
"hostApp.weibo" = "Weibo";
|
||||
"hostApp.xiaohongshu" = "RED";
|
||||
"hostApp.zhihu" = "Zhihu";
|
||||
"hostApp.bilibili" = "Bilibili";
|
||||
"hostApp.douyin" = "Douyin";
|
||||
"hostApp.douyinLite" = "Douyin Lite";
|
||||
"hostApp.kuaishou" = "Kuaishou";
|
||||
"hostApp.kuaishouLite" = "Kuaishou Lite";
|
||||
"hostApp.toutiao" = "Toutiao";
|
||||
"hostApp.douban" = "Douban";
|
||||
"hostApp.baidu" = "Baidu";
|
||||
"hostApp.youku" = "Youku";
|
||||
"hostApp.tencentVideo" = "Tencent Video";
|
||||
"hostApp.iqiyi" = "iQIYI";
|
||||
"hostApp.mangoTV" = "Mango TV";
|
||||
"hostApp.qqMusic" = "QQ Music";
|
||||
"hostApp.neteaseMusic" = "NetEase Cloud Music";
|
||||
"hostApp.kugou" = "Kugou Music";
|
||||
"hostApp.ximalaya" = "Ximalaya";
|
||||
"hostApp.weread" = "WeRead";
|
||||
"hostApp.facebook" = "Facebook";
|
||||
"hostApp.instagram" = "Instagram";
|
||||
"hostApp.x" = "X";
|
||||
@@ -865,10 +896,61 @@
|
||||
"hostApp.snapchat" = "Snapchat";
|
||||
"hostApp.reddit" = "Reddit";
|
||||
"hostApp.pinterest" = "Pinterest";
|
||||
"hostApp.zhihu" = "Zhihu";
|
||||
"hostApp.bilibili" = "Bilibili";
|
||||
"hostApp.douyin" = "Douyin";
|
||||
"hostApp.tiktok" = "TikTok";
|
||||
"hostApp.youtube" = "YouTube";
|
||||
"hostApp.linkedin" = "LinkedIn";
|
||||
"hostApp.tumblr" = "Tumblr";
|
||||
"hostApp.twitch" = "Twitch";
|
||||
"hostApp.spotify" = "Spotify";
|
||||
"hostApp.netflix" = "Netflix";
|
||||
"hostApp.capcut" = "CapCut";
|
||||
"hostApp.duolingo" = "Duolingo";
|
||||
"hostApp.taobao" = "Taobao";
|
||||
"hostApp.tmall" = "Tmall";
|
||||
"hostApp.jd" = "JD.com";
|
||||
"hostApp.pinduoduo" = "Pinduoduo";
|
||||
"hostApp.xianyu" = "Xianyu";
|
||||
"hostApp.alibaba1688" = "1688";
|
||||
"hostApp.vipshop" = "Vipshop";
|
||||
"hostApp.meituan" = "Meituan";
|
||||
"hostApp.meituanWaimai" = "Meituan Waimai";
|
||||
"hostApp.eleme" = "Taobao Shangou";
|
||||
"hostApp.dianping" = "Dianping";
|
||||
"hostApp.wuba" = "58.com";
|
||||
"hostApp.didi" = "DiDi";
|
||||
"hostApp.amap" = "Amap";
|
||||
"hostApp.baiduMap" = "Baidu Maps";
|
||||
"hostApp.tencentMap" = "Tencent Maps";
|
||||
"hostApp.ctrip" = "Ctrip";
|
||||
"hostApp.baiduNetdisk" = "Baidu Netdisk";
|
||||
"hostApp.ucBrowser" = "UC Browser";
|
||||
"hostApp.qqBrowser" = "QQ Browser";
|
||||
"hostApp.alipay" = "Alipay";
|
||||
"hostApp.unionpay" = "UnionPay";
|
||||
"hostApp.cmb" = "China Merchants Bank";
|
||||
"hostApp.ccb" = "China Construction Bank";
|
||||
"hostApp.abc" = "Agricultural Bank of China";
|
||||
"hostApp.amazon" = "Amazon";
|
||||
"hostApp.walmart" = "Walmart";
|
||||
"hostApp.ebay" = "eBay";
|
||||
"hostApp.aliexpress" = "AliExpress";
|
||||
"hostApp.uber" = "Uber";
|
||||
"hostApp.lyft" = "Lyft";
|
||||
"hostApp.doordash" = "DoorDash";
|
||||
"hostApp.airbnb" = "Airbnb";
|
||||
"hostApp.googleMaps" = "Google Maps";
|
||||
"hostApp.paypal" = "PayPal";
|
||||
"hostApp.venmo" = "Venmo";
|
||||
"hostApp.cashApp" = "Cash App";
|
||||
"hostApp.messages" = "Messages";
|
||||
"hostApp.notes" = "Notes";
|
||||
"hostApp.mail" = "Mail";
|
||||
"hostApp.reminders" = "Reminders";
|
||||
"hostApp.calendar" = "Calendar";
|
||||
"hostApp.shortcuts" = "Shortcuts";
|
||||
"hostApp.files" = "Files";
|
||||
"hostApp.maps" = "Maps";
|
||||
"hostApp.appStore" = "App Store";
|
||||
"flow.warning.polishDegradedQuality" = "Polish output failed validation; inserted a conservative version.";
|
||||
"flow.error.editLastInputFailed" = "Could not complete the edit. Please try again.";
|
||||
"flow.error.aiQuestionFailed" = "AI response failed. Please try again.";
|
||||
|
||||
@@ -829,6 +829,9 @@
|
||||
"hostApp.wecom" = "企业微信";
|
||||
"hostApp.dingtalk" = "钉钉";
|
||||
"hostApp.lark" = "飞书";
|
||||
"hostApp.tencentMeeting" = "腾讯会议";
|
||||
"hostApp.qqmail" = "QQ邮箱";
|
||||
"hostApp.wps" = "WPS Office";
|
||||
"hostApp.telegram" = "Telegram";
|
||||
"hostApp.whatsapp" = "WhatsApp";
|
||||
"hostApp.line" = "LINE";
|
||||
@@ -836,28 +839,56 @@
|
||||
"hostApp.slack" = "Slack";
|
||||
"hostApp.teams" = "Microsoft Teams";
|
||||
"hostApp.discord" = "Discord";
|
||||
"hostApp.notion" = "Notion";
|
||||
"hostApp.bear" = "Bear";
|
||||
"hostApp.obsidian" = "Obsidian";
|
||||
"hostApp.drafts" = "Drafts";
|
||||
"hostApp.gmail" = "Gmail";
|
||||
"hostApp.outlook" = "Outlook";
|
||||
"hostApp.chrome" = "Chrome";
|
||||
"hostApp.weibo" = "微博";
|
||||
"hostApp.xiaohongshu" = "小红书";
|
||||
"hostApp.signal" = "Signal";
|
||||
"hostApp.kakaotalk" = "KakaoTalk";
|
||||
"hostApp.viber" = "Viber";
|
||||
"hostApp.zalo" = "Zalo";
|
||||
"hostApp.skype" = "Skype";
|
||||
"hostApp.zoom" = "Zoom";
|
||||
"hostApp.tinder" = "Tinder";
|
||||
"hostApp.notion" = "Notion";
|
||||
"hostApp.bear" = "熊掌记";
|
||||
"hostApp.obsidian" = "Obsidian";
|
||||
"hostApp.drafts" = "Drafts";
|
||||
"hostApp.things" = "Things";
|
||||
"hostApp.todoist" = "Todoist";
|
||||
"hostApp.evernote" = "印象笔记";
|
||||
"hostApp.evernote" = "Evernote";
|
||||
"hostApp.onenote" = "OneNote";
|
||||
"hostApp.word" = "Word";
|
||||
"hostApp.excel" = "Excel";
|
||||
"hostApp.gmail" = "Gmail";
|
||||
"hostApp.outlook" = "Outlook";
|
||||
"hostApp.spark" = "Spark";
|
||||
"hostApp.yahooMail" = "雅虎邮箱";
|
||||
"hostApp.googleDocs" = "Google 文档";
|
||||
"hostApp.googleSheets" = "Google 表格";
|
||||
"hostApp.googleDrive" = "Google 云端硬盘";
|
||||
"hostApp.googleTranslate" = "Google 翻译";
|
||||
"hostApp.google" = "Google";
|
||||
"hostApp.chrome" = "Chrome";
|
||||
"hostApp.firefox" = "Firefox";
|
||||
"hostApp.edge" = "Edge";
|
||||
"hostApp.chatgpt" = "ChatGPT";
|
||||
"hostApp.claude" = "Claude";
|
||||
"hostApp.weibo" = "微博";
|
||||
"hostApp.xiaohongshu" = "小红书";
|
||||
"hostApp.zhihu" = "知乎";
|
||||
"hostApp.bilibili" = "哔哩哔哩";
|
||||
"hostApp.douyin" = "抖音";
|
||||
"hostApp.douyinLite" = "抖音极速版";
|
||||
"hostApp.kuaishou" = "快手";
|
||||
"hostApp.kuaishouLite" = "快手极速版";
|
||||
"hostApp.toutiao" = "今日头条";
|
||||
"hostApp.douban" = "豆瓣";
|
||||
"hostApp.baidu" = "百度";
|
||||
"hostApp.youku" = "优酷视频";
|
||||
"hostApp.tencentVideo" = "腾讯视频";
|
||||
"hostApp.iqiyi" = "爱奇艺";
|
||||
"hostApp.mangoTV" = "芒果TV";
|
||||
"hostApp.qqMusic" = "QQ音乐";
|
||||
"hostApp.neteaseMusic" = "网易云音乐";
|
||||
"hostApp.kugou" = "酷狗音乐";
|
||||
"hostApp.ximalaya" = "喜马拉雅";
|
||||
"hostApp.weread" = "微信读书";
|
||||
"hostApp.facebook" = "Facebook";
|
||||
"hostApp.instagram" = "Instagram";
|
||||
"hostApp.x" = "X";
|
||||
@@ -865,10 +896,61 @@
|
||||
"hostApp.snapchat" = "Snapchat";
|
||||
"hostApp.reddit" = "Reddit";
|
||||
"hostApp.pinterest" = "Pinterest";
|
||||
"hostApp.zhihu" = "知乎";
|
||||
"hostApp.bilibili" = "哔哩哔哩";
|
||||
"hostApp.douyin" = "抖音";
|
||||
"hostApp.tiktok" = "TikTok";
|
||||
"hostApp.youtube" = "YouTube";
|
||||
"hostApp.linkedin" = "领英";
|
||||
"hostApp.tumblr" = "Tumblr";
|
||||
"hostApp.twitch" = "Twitch";
|
||||
"hostApp.spotify" = "Spotify";
|
||||
"hostApp.netflix" = "Netflix";
|
||||
"hostApp.capcut" = "CapCut";
|
||||
"hostApp.duolingo" = "多邻国";
|
||||
"hostApp.taobao" = "淘宝";
|
||||
"hostApp.tmall" = "天猫";
|
||||
"hostApp.jd" = "京东";
|
||||
"hostApp.pinduoduo" = "拼多多";
|
||||
"hostApp.xianyu" = "闲鱼";
|
||||
"hostApp.alibaba1688" = "阿里巴巴 1688";
|
||||
"hostApp.vipshop" = "唯品会";
|
||||
"hostApp.meituan" = "美团";
|
||||
"hostApp.meituanWaimai" = "美团外卖";
|
||||
"hostApp.eleme" = "淘宝闪购";
|
||||
"hostApp.dianping" = "大众点评";
|
||||
"hostApp.wuba" = "58同城";
|
||||
"hostApp.didi" = "滴滴出行";
|
||||
"hostApp.amap" = "高德地图";
|
||||
"hostApp.baiduMap" = "百度地图";
|
||||
"hostApp.tencentMap" = "腾讯地图";
|
||||
"hostApp.ctrip" = "携程旅行";
|
||||
"hostApp.baiduNetdisk" = "百度网盘";
|
||||
"hostApp.ucBrowser" = "UC浏览器";
|
||||
"hostApp.qqBrowser" = "QQ浏览器";
|
||||
"hostApp.alipay" = "支付宝";
|
||||
"hostApp.unionpay" = "云闪付";
|
||||
"hostApp.cmb" = "招商银行";
|
||||
"hostApp.ccb" = "中国建设银行";
|
||||
"hostApp.abc" = "中国农业银行";
|
||||
"hostApp.amazon" = "亚马逊";
|
||||
"hostApp.walmart" = "沃尔玛";
|
||||
"hostApp.ebay" = "eBay";
|
||||
"hostApp.aliexpress" = "速卖通";
|
||||
"hostApp.uber" = "Uber";
|
||||
"hostApp.lyft" = "Lyft";
|
||||
"hostApp.doordash" = "DoorDash";
|
||||
"hostApp.airbnb" = "爱彼迎";
|
||||
"hostApp.googleMaps" = "Google 地图";
|
||||
"hostApp.paypal" = "PayPal";
|
||||
"hostApp.venmo" = "Venmo";
|
||||
"hostApp.cashApp" = "Cash App";
|
||||
"hostApp.messages" = "信息";
|
||||
"hostApp.notes" = "备忘录";
|
||||
"hostApp.mail" = "邮件";
|
||||
"hostApp.reminders" = "提醒事项";
|
||||
"hostApp.calendar" = "日历";
|
||||
"hostApp.shortcuts" = "快捷指令";
|
||||
"hostApp.files" = "文件";
|
||||
"hostApp.maps" = "地图";
|
||||
"hostApp.appStore" = "App Store";
|
||||
"flow.warning.polishDegradedQuality" = "本次润色结果未通过校验,已插入保守处理版本。";
|
||||
"flow.error.editLastInputFailed" = "未能完成编辑,请重试。";
|
||||
"flow.error.aiQuestionFailed" = "AI 回答失败,请重试。";
|
||||
|
||||
Reference in New Issue
Block a user