mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 02:06:43 +00:00
feat(ios): Talk camera flip control and mic input selection (#111044)
* feat(ios): add Talk camera flip and mic selection * chore(ios): sync native i18n inventory and locale artifacts for talk camera/mic strings * chore(ios): commit regenerated Localizable.xcstrings for new talk strings * fix(ios): extract Talk composer controls * chore(ios): resync native i18n inventory and locale artifacts atop landed Android entries * fix(ios): repair Talk composer CI checks * chore(i18n): commit regenerated Android locale outputs from catalog reconciliation * chore(i18n): sync Android locale outputs after rebase
This commit is contained in:
@@ -1603,6 +1603,22 @@
|
||||
"連線中"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "it",
|
||||
"source": "Connecting...",
|
||||
"translations": [
|
||||
"Connessione in corso...",
|
||||
"Connessione..."
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "nl",
|
||||
"source": "Connecting...",
|
||||
"translations": [
|
||||
"Verbinden...",
|
||||
"Verbinding maken..."
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "zh-TW",
|
||||
"source": "Connecting...",
|
||||
@@ -3323,39 +3339,23 @@
|
||||
"source": "Gateway connected",
|
||||
"translations": [
|
||||
"Gateway متصل",
|
||||
"تم اتصال Gateway"
|
||||
"تم الاتصال بـ Gateway"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "fa",
|
||||
"locale": "tr",
|
||||
"source": "Gateway connected",
|
||||
"translations": [
|
||||
"Gateway متصل است",
|
||||
"Gateway متصل شد"
|
||||
"Gateway bağlandı",
|
||||
"Gateway bağlı"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "ja-JP",
|
||||
"locale": "vi",
|
||||
"source": "Gateway connected",
|
||||
"translations": [
|
||||
"Gateway に接続しました",
|
||||
"Gatewayに接続済み"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "pl",
|
||||
"source": "Gateway connected",
|
||||
"translations": [
|
||||
"Gateway połączony",
|
||||
"Połączono z Gateway"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "ru",
|
||||
"source": "Gateway connected",
|
||||
"translations": [
|
||||
"Gateway подключен",
|
||||
"Gateway подключён"
|
||||
"Gateway đã kết nối",
|
||||
"Đã kết nối Gateway"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -8680,6 +8680,14 @@
|
||||
"Статус"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "id",
|
||||
"source": "Stop",
|
||||
"translations": [
|
||||
"Berhenti",
|
||||
"Hentikan"
|
||||
]
|
||||
},
|
||||
{
|
||||
"locale": "ar",
|
||||
"source": "Technical details",
|
||||
|
||||
+179
-147
@@ -13923,7 +13923,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 189,
|
||||
"line": 193,
|
||||
"path": "apps/ios/Sources/Camera/CameraController.swift",
|
||||
"source": "Camera",
|
||||
"surface": "apple",
|
||||
@@ -13931,7 +13931,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 189,
|
||||
"line": 193,
|
||||
"path": "apps/ios/Sources/Camera/CameraController.swift",
|
||||
"source": "Microphone",
|
||||
"surface": "apple",
|
||||
@@ -17267,7 +17267,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 173,
|
||||
"line": 174,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Unable to Export Transcript",
|
||||
"surface": "apple",
|
||||
@@ -17275,7 +17275,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 177,
|
||||
"line": 178,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "OK",
|
||||
"surface": "apple",
|
||||
@@ -17283,7 +17283,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 181,
|
||||
"line": 182,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "OpenClaw could not prepare the Markdown file.",
|
||||
"surface": "apple",
|
||||
@@ -17291,7 +17291,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 203,
|
||||
"line": 204,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "What would you like to work on?",
|
||||
"surface": "apple",
|
||||
@@ -17299,7 +17299,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 223,
|
||||
"line": 224,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "The thread attaches once the gateway is ready.",
|
||||
"surface": "apple",
|
||||
@@ -17307,7 +17307,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 311,
|
||||
"line": 312,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Collapsed",
|
||||
"surface": "apple",
|
||||
@@ -17315,7 +17315,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 311,
|
||||
"line": 312,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Expanded",
|
||||
"surface": "apple",
|
||||
@@ -17323,7 +17323,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 381,
|
||||
"line": 382,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Opens Settings / Gateway",
|
||||
"surface": "apple",
|
||||
@@ -17331,7 +17331,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 384,
|
||||
"line": 385,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Hides the gateway status label",
|
||||
"surface": "apple",
|
||||
@@ -17339,7 +17339,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 385,
|
||||
"line": 386,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Shows the full gateway status label",
|
||||
"surface": "apple",
|
||||
@@ -17347,7 +17347,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 404,
|
||||
"line": 405,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Voice off",
|
||||
"surface": "apple",
|
||||
@@ -17355,7 +17355,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 545,
|
||||
"line": 568,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "New Chat",
|
||||
"surface": "apple",
|
||||
@@ -17363,7 +17363,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 558,
|
||||
"line": 581,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "New Chat in Worktree",
|
||||
"surface": "apple",
|
||||
@@ -17371,7 +17371,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 571,
|
||||
"line": 594,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Threads…",
|
||||
"surface": "apple",
|
||||
@@ -17379,7 +17379,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 584,
|
||||
"line": 607,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Background Tasks",
|
||||
"surface": "apple",
|
||||
@@ -17387,7 +17387,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 596,
|
||||
"line": 619,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Export Transcript",
|
||||
"surface": "apple",
|
||||
@@ -17395,7 +17395,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 609,
|
||||
"line": 632,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Gateway Settings",
|
||||
"surface": "apple",
|
||||
@@ -17403,7 +17403,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 620,
|
||||
"line": 643,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Show reasoning & tool activity",
|
||||
"surface": "apple",
|
||||
@@ -17411,7 +17411,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-modifier",
|
||||
"line": 629,
|
||||
"line": 652,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Chat actions",
|
||||
"surface": "apple",
|
||||
@@ -17419,7 +17419,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 731,
|
||||
"line": 754,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Connected",
|
||||
"surface": "apple",
|
||||
@@ -17427,7 +17427,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 731,
|
||||
"line": 754,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Unavailable",
|
||||
"surface": "apple",
|
||||
@@ -17435,7 +17435,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 744,
|
||||
"line": 767,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Message %@...",
|
||||
"surface": "apple",
|
||||
@@ -17443,7 +17443,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 749,
|
||||
"line": 772,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Message %@; sends when connected",
|
||||
"surface": "apple",
|
||||
@@ -17451,7 +17451,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 752,
|
||||
"line": 775,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Connect to a gateway",
|
||||
"surface": "apple",
|
||||
@@ -17459,7 +17459,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 841,
|
||||
"line": 864,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Check OpenClaw status",
|
||||
"surface": "apple",
|
||||
@@ -17467,7 +17467,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 842,
|
||||
"line": 865,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Summarize the current OpenClaw status and tell me what needs attention.",
|
||||
"surface": "apple",
|
||||
@@ -17475,7 +17475,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 845,
|
||||
"line": 868,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "What can I control here?",
|
||||
"surface": "apple",
|
||||
@@ -17483,7 +17483,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 846,
|
||||
"line": 869,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Show me which phone controls and device capabilities are available right now.",
|
||||
"surface": "apple",
|
||||
@@ -17491,7 +17491,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 849,
|
||||
"line": 872,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Help me start voice chat",
|
||||
"surface": "apple",
|
||||
@@ -17499,7 +17499,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 850,
|
||||
"line": 873,
|
||||
"path": "apps/ios/Sources/Design/ChatProTab.swift",
|
||||
"source": "Help me start a realtime voice session from this phone.",
|
||||
"surface": "apple",
|
||||
@@ -23819,7 +23819,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4087,
|
||||
"line": 4112,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Approval needed",
|
||||
"surface": "apple",
|
||||
@@ -23827,7 +23827,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4088,
|
||||
"line": 4113,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Action required",
|
||||
"surface": "apple",
|
||||
@@ -23835,7 +23835,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4803,
|
||||
"line": 4828,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Connecting...",
|
||||
"surface": "apple",
|
||||
@@ -23843,7 +23843,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4804,
|
||||
"line": 4829,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Reconnecting...",
|
||||
"surface": "apple",
|
||||
@@ -23851,7 +23851,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 5156,
|
||||
"line": 5181,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Connected",
|
||||
"surface": "apple",
|
||||
@@ -23859,7 +23859,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 5156,
|
||||
"line": 5181,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Offline",
|
||||
"surface": "apple",
|
||||
@@ -23867,7 +23867,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 6326,
|
||||
"line": 6351,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "No chat messages yet",
|
||||
"surface": "apple",
|
||||
@@ -23875,7 +23875,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 6525,
|
||||
"line": 6550,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Connecting…",
|
||||
"surface": "apple",
|
||||
@@ -23883,7 +23883,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 6525,
|
||||
"line": 6550,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Reconnecting…",
|
||||
"surface": "apple",
|
||||
@@ -23891,7 +23891,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8934,
|
||||
"line": 8959,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Approval",
|
||||
"surface": "apple",
|
||||
@@ -23899,7 +23899,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8934,
|
||||
"line": 8959,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "This approval was already",
|
||||
"surface": "apple",
|
||||
@@ -23907,7 +23907,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8940,
|
||||
"line": 8965,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "This approval was already set to Always Allow.",
|
||||
"surface": "apple",
|
||||
@@ -23915,7 +23915,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 8941,
|
||||
"line": 8966,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "Approval set to Always Allow.",
|
||||
"surface": "apple",
|
||||
@@ -23923,7 +23923,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 10278,
|
||||
"line": 10303,
|
||||
"path": "apps/ios/Sources/Model/NodeAppModel.swift",
|
||||
"source": "\\(urlText.prefix(500))…",
|
||||
"surface": "apple",
|
||||
@@ -25667,7 +25667,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 591,
|
||||
"line": 608,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Gateway relay ready",
|
||||
"surface": "apple",
|
||||
@@ -25675,7 +25675,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 593,
|
||||
"line": 610,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Realtime Voice, Gateway relay ready",
|
||||
"surface": "apple",
|
||||
@@ -25683,7 +25683,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 595,
|
||||
"line": 612,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Listening starts from this phone",
|
||||
"surface": "apple",
|
||||
@@ -25691,7 +25691,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 835,
|
||||
"line": 852,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Off",
|
||||
"surface": "apple",
|
||||
@@ -25699,7 +25699,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 838,
|
||||
"line": 855,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Not active",
|
||||
"surface": "apple",
|
||||
@@ -25707,7 +25707,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1024,
|
||||
"line": 1041,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Requesting permissions…",
|
||||
"surface": "apple",
|
||||
@@ -25715,7 +25715,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1053,
|
||||
"line": 1070,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Start failed: %@",
|
||||
"surface": "apple",
|
||||
@@ -25723,7 +25723,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1309,
|
||||
"line": 1326,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Microphone permission denied",
|
||||
"surface": "apple",
|
||||
@@ -25731,7 +25731,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1319,
|
||||
"line": 1336,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speech recognition",
|
||||
"surface": "apple",
|
||||
@@ -25739,7 +25739,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1450,
|
||||
"line": 1467,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Offline",
|
||||
"surface": "apple",
|
||||
@@ -25747,7 +25747,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1649,
|
||||
"line": 1666,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speech error: %@",
|
||||
"surface": "apple",
|
||||
@@ -25755,7 +25755,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 1964,
|
||||
"line": 1981,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Gateway not connected",
|
||||
"surface": "apple",
|
||||
@@ -25763,7 +25763,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 2008,
|
||||
"line": 2025,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Aborted",
|
||||
"surface": "apple",
|
||||
@@ -25771,7 +25771,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 2008,
|
||||
"line": 2025,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Chat error",
|
||||
"surface": "apple",
|
||||
@@ -25779,7 +25779,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2036,
|
||||
"line": 2053,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Talk failed: %@",
|
||||
"surface": "apple",
|
||||
@@ -25787,7 +25787,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2140,
|
||||
"line": 2157,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "No reply",
|
||||
"surface": "apple",
|
||||
@@ -25795,7 +25795,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2232,
|
||||
"line": 2252,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Paused",
|
||||
"surface": "apple",
|
||||
@@ -25803,7 +25803,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2644,
|
||||
"line": 2664,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Generating voice…",
|
||||
"surface": "apple",
|
||||
@@ -25811,7 +25811,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2782,
|
||||
"line": 2802,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speak failed: %@",
|
||||
"surface": "apple",
|
||||
@@ -25819,7 +25819,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 2881,
|
||||
"line": 2901,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speaking (System)…",
|
||||
"surface": "apple",
|
||||
@@ -25827,7 +25827,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3762,
|
||||
"line": 3782,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "iOS System Voice",
|
||||
"surface": "apple",
|
||||
@@ -25835,7 +25835,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3764,
|
||||
"line": 3784,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Realtime Voice",
|
||||
"surface": "apple",
|
||||
@@ -25843,7 +25843,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3768,
|
||||
"line": 3788,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Gateway Default",
|
||||
"surface": "apple",
|
||||
@@ -25851,7 +25851,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3827,
|
||||
"line": 3847,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Listening (Realtime)",
|
||||
"surface": "apple",
|
||||
@@ -25859,7 +25859,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3829,
|
||||
"line": 3849,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Thinking",
|
||||
"surface": "apple",
|
||||
@@ -25867,7 +25867,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3831,
|
||||
"line": 3851,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Thinking…",
|
||||
"surface": "apple",
|
||||
@@ -25875,7 +25875,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3833,
|
||||
"line": 3853,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Asking OpenClaw",
|
||||
"surface": "apple",
|
||||
@@ -25883,7 +25883,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3835,
|
||||
"line": 3855,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Still asking OpenClaw",
|
||||
"surface": "apple",
|
||||
@@ -25891,7 +25891,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3837,
|
||||
"line": 3857,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Updating OpenClaw",
|
||||
"surface": "apple",
|
||||
@@ -25899,7 +25899,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3839,
|
||||
"line": 3859,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speaking",
|
||||
"surface": "apple",
|
||||
@@ -25907,7 +25907,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3841,
|
||||
"line": 3861,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Speaking…",
|
||||
"surface": "apple",
|
||||
@@ -25915,7 +25915,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3843,
|
||||
"line": 3863,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Connecting",
|
||||
"surface": "apple",
|
||||
@@ -25923,7 +25923,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3845,
|
||||
"line": 3865,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Connecting realtime…",
|
||||
"surface": "apple",
|
||||
@@ -25931,7 +25931,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3847,
|
||||
"line": 3867,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Waiting for realtime…",
|
||||
"surface": "apple",
|
||||
@@ -25939,7 +25939,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3849,
|
||||
"line": 3869,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Ready",
|
||||
"surface": "apple",
|
||||
@@ -25947,7 +25947,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3851,
|
||||
"line": 3871,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Reconnecting",
|
||||
"surface": "apple",
|
||||
@@ -25955,7 +25955,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3853,
|
||||
"line": 3873,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Reconnecting…",
|
||||
"surface": "apple",
|
||||
@@ -25963,7 +25963,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3855,
|
||||
"line": 3875,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Realtime failed before connecting",
|
||||
"surface": "apple",
|
||||
@@ -25971,7 +25971,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3857,
|
||||
"line": 3877,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Realtime disconnected",
|
||||
"surface": "apple",
|
||||
@@ -25979,7 +25979,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3859,
|
||||
"line": 3879,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "OpenClaw unavailable",
|
||||
"surface": "apple",
|
||||
@@ -25987,7 +25987,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3899,
|
||||
"line": 3919,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "iOS Speech + TTS",
|
||||
"surface": "apple",
|
||||
@@ -25995,7 +25995,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3901,
|
||||
"line": 3921,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Listening",
|
||||
"surface": "apple",
|
||||
@@ -26003,7 +26003,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 3905,
|
||||
"line": 3925,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "iOS Speech fallback",
|
||||
"surface": "apple",
|
||||
@@ -26011,7 +26011,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4166,
|
||||
"line": 4186,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Gateway Relay",
|
||||
"surface": "apple",
|
||||
@@ -26019,7 +26019,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4168,
|
||||
"line": 4188,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Native WebRTC",
|
||||
"surface": "apple",
|
||||
@@ -26027,7 +26027,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4169,
|
||||
"line": 4189,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Native",
|
||||
"surface": "apple",
|
||||
@@ -26035,7 +26035,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4230,
|
||||
"line": 4250,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Gateway permission required",
|
||||
"surface": "apple",
|
||||
@@ -26043,7 +26043,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4252,
|
||||
"line": 4272,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Not loaded",
|
||||
"surface": "apple",
|
||||
@@ -26051,7 +26051,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4270,
|
||||
"line": 4290,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Approval requested",
|
||||
"surface": "apple",
|
||||
@@ -26059,7 +26059,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4693,
|
||||
"line": 4729,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Realtime unavailable",
|
||||
"surface": "apple",
|
||||
@@ -26067,7 +26067,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 4715,
|
||||
"line": 4751,
|
||||
"path": "apps/ios/Sources/Voice/TalkModeManager.swift",
|
||||
"source": "Listening (PTT)",
|
||||
"surface": "apple",
|
||||
@@ -36905,6 +36905,78 @@
|
||||
"surface": "apple",
|
||||
"id": "native.apple.d4f7cdeb3737a201"
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 36,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Switch to back camera",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.fc5931c1f0a6bbec"
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 38,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Switch to front camera",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.cce3b539e31701c0"
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 40,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Flip camera",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.f397daffdfd02ee0"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 73,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Stop",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.11f8de87ca3fcb11"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 73,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Talk",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.7c92bec1c8a83e43"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 118,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Start realtime chat",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.dae61543f9b416ca"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 118,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Stop realtime chat",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.d376b015a90792a9"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 203,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Connecting...",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.ac48dbe25ac4d40d"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 203,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatCameraFlipButton.swift",
|
||||
"source": "Gateway connected",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.ccce98756eb1dacd"
|
||||
},
|
||||
{
|
||||
"kind": "ui-localized-call",
|
||||
"line": 415,
|
||||
@@ -37059,31 +37131,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 813,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Talk",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.ee2c0d22f5861159"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 884,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Start realtime chat",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.5d5041aefe6dfddd"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 884,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Stop realtime chat",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.21a7d3a3386a2218"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 918,
|
||||
"line": 821,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Start",
|
||||
"surface": "apple",
|
||||
@@ -37091,7 +37139,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 918,
|
||||
"line": 821,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Stop",
|
||||
"surface": "apple",
|
||||
@@ -37099,7 +37147,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 1035,
|
||||
"line": 919,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Loading commands",
|
||||
"surface": "apple",
|
||||
@@ -37107,7 +37155,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 1044,
|
||||
"line": 928,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Commands unavailable",
|
||||
"surface": "apple",
|
||||
@@ -37115,7 +37163,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 1053,
|
||||
"line": 937,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Retry",
|
||||
"surface": "apple",
|
||||
@@ -37123,7 +37171,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 1062,
|
||||
"line": 946,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "No matching commands",
|
||||
"surface": "apple",
|
||||
@@ -37131,7 +37179,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-modifier",
|
||||
"line": 1294,
|
||||
"line": 1178,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Stop response",
|
||||
"surface": "apple",
|
||||
@@ -37139,7 +37187,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-modifier",
|
||||
"line": 1319,
|
||||
"line": 1203,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Send message",
|
||||
"surface": "apple",
|
||||
@@ -37147,7 +37195,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "ui-modifier",
|
||||
"line": 1333,
|
||||
"line": 1217,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Refresh",
|
||||
"surface": "apple",
|
||||
@@ -37155,23 +37203,7 @@
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 1458,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Connecting...",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.6c984c0e3ed3a69e"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 1458,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Gateway connected",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.898849eb2bcb0b53"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 1467,
|
||||
"line": 1343,
|
||||
"path": "apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatComposer.swift",
|
||||
"source": "Message…",
|
||||
"surface": "apple",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "التبديل إلى الكاميرا الخلفية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "التبديل إلى الكاميرا الأمامية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "عكس الكاميرا"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "إيقاف"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "تحدّث"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "بدء الدردشة الفورية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "إيقاف الدردشة الفورية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "جارٍ الاتصال..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "تم الاتصال بـ Gateway"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "المرفقات"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "تحدث"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "بدء دردشة فورية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "إيقاف الدردشة الفورية"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "تحديث"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "جارٍ الاتصال..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "تم اتصال Gateway"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Zur Rückkamera wechseln"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Zur Frontkamera wechseln"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Kamera wechseln"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Stopp"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Sprechen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Echtzeit-Chat starten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Echtzeit-Chat beenden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Verbindung wird hergestellt..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway verbunden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Anhänge"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Sprechen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Echtzeit-Chat starten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Echtzeit-Chat beenden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Aktualisieren"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Verbindung wird hergestellt..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway verbunden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Cambiar a la cámara trasera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Cambiar a la cámara frontal"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Voltear la cámara"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Detener"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Hablar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Iniciar chat en tiempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Detener chat en tiempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Conectando..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway conectado"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Archivos adjuntos"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Hablar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Iniciar chat en tiempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Detener chat en tiempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Actualizar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Conectando..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway conectado"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "تغییر به دوربین پشت"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "تغییر به دوربین جلو"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "برگرداندن دوربین"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "توقف"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "صحبت"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "شروع گفتوگوی همزمان"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "توقف گفتوگوی همزمان"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "در حال اتصال..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway متصل است"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "پیوستها"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "گفتگو"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "شروع گفتگوی بلادرنگ"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "توقف گفتگوی بلادرنگ"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "تازهسازی"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "در حال اتصال..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway متصل شد"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Passer à la caméra arrière"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Passer à la caméra avant"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Retourner la caméra"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Arrêter"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Parler"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Démarrer le chat en temps réel"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Arrêter le chat en temps réel"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Connexion..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway connecté"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Pièces jointes"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Parler"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Démarrer la discussion en temps réel"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Arrêter la discussion en temps réel"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Actualiser"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Connexion..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway connecté"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "पीछे वाले कैमरे पर स्विच करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "सामने वाले कैमरे पर स्विच करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "कैमरा पलटें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "रोकें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "बात करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "रीयल-टाइम चैट शुरू करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "रीयल-टाइम चैट रोकें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "कनेक्ट हो रहा है..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway कनेक्ट हो गया"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "अटैचमेंट"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "बात करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "रीयल-टाइम चैट शुरू करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "रीयल-टाइम चैट बंद करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "रीफ़्रेश करें"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "कनेक्ट हो रहा है..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway कनेक्ट हो गया"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Beralih ke kamera belakang"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Beralih ke kamera depan"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Balik kamera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Berhenti"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Bicara"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Mulai obrolan waktu nyata"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Hentikan obrolan waktu nyata"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Menghubungkan..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway terhubung"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Lampiran"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Bicara"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Mulai chat realtime"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Hentikan chat realtime"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Segarkan"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Menghubungkan..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway terhubung"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Passa alla fotocamera posteriore"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Passa alla fotocamera anteriore"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Capovolgi fotocamera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Interrompi"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Parla"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Avvia chat in tempo reale"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Interrompi chat in tempo reale"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Connessione..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway connesso"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Allegati"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Parla"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Avvia chat in tempo reale"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Interrompi chat in tempo reale"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Aggiorna"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Connessione in corso..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway connesso"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "背面カメラに切り替え"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "前面カメラに切り替え"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "カメラを反転"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "停止"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "話す"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "リアルタイムチャットを開始"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "リアルタイムチャットを停止"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "接続中..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gatewayに接続済み"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "添付ファイル"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "トーク"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "リアルタイムチャットを開始"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "リアルタイムチャットを停止"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "更新"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "接続中..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway に接続しました"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "후면 카메라로 전환"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "전면 카메라로 전환"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "카메라 전환"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "중지"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "말하기"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "실시간 채팅 시작"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "실시간 채팅 중지"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "연결 중..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 연결됨"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "첨부 파일"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "대화"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "실시간 채팅 시작"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "실시간 채팅 중지"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "새로 고침"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "연결 중..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 연결됨"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Schakel over naar de camera aan de achterkant"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Schakel over naar de camera aan de voorkant"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Camera omdraaien"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Stoppen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Praten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Realtimechat starten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Realtimechat stoppen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Verbinding maken..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway verbonden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Bijlagen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Praten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Realtime chat starten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Realtime chat stoppen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Vernieuwen"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Verbinden..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway verbonden"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Przełącz na tylny aparat"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Przełącz na przedni aparat"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Odwróć aparat"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Zatrzymaj"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Mów"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Rozpocznij czat w czasie rzeczywistym"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Zatrzymaj czat w czasie rzeczywistym"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Łączenie..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Połączono z Gateway"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Załączniki"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Rozmawiaj"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Rozpocznij czat w czasie rzeczywistym"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Zatrzymaj czat w czasie rzeczywistym"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Odśwież"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Łączenie..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway połączony"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Alternar para a câmera traseira"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Alternar para a câmera frontal"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Inverter câmera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Parar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Falar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Iniciar conversa em tempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Encerrar conversa em tempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Conectando..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway conectado"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Anexos"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Falar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Iniciar chat em tempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Parar chat em tempo real"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Atualizar"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Conectando..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway conectado"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Переключиться на заднюю камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Переключиться на фронтальную камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Сменить камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Остановить"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Говорить"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Начать чат в реальном времени"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Остановить чат в реальном времени"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Подключение..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway подключён"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Вложения"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Разговор"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Начать чат в реальном времени"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Остановить чат в реальном времени"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Обновить"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Подключение..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway подключен"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Byt till bakre kameran"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Byt till främre kameran"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Vänd kameran"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Stoppa"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Prata"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Starta realtidschatt"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Stoppa realtidschatt"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Ansluter..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway ansluten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Bilagor"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Prata"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Starta realtidschatt"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Stoppa realtidschatt"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Uppdatera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Ansluter..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway ansluten"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "สลับไปใช้กล้องหลัง"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "สลับไปใช้กล้องหน้า"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "สลับกล้อง"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "หยุด"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "พูด"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "เริ่มแชทแบบเรียลไทม์"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "หยุดแชทแบบเรียลไทม์"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "กำลังเชื่อมต่อ..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "เชื่อมต่อ Gateway แล้ว"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "ไฟล์แนบ"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "พูดคุย"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "เริ่มแชทแบบเรียลไทม์"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "หยุดแชทแบบเรียลไทม์"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "รีเฟรช"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "กำลังเชื่อมต่อ..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "เชื่อมต่อ Gateway แล้ว"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Arka kameraya geç"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Ön kameraya geç"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Kamerayı çevir"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Durdur"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Konuş"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Gerçek zamanlı sohbeti başlat"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Gerçek zamanlı sohbeti durdur"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Bağlanıyor..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway bağlandı"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Ekler"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Konuş"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Gerçek zamanlı sohbeti başlat"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Gerçek zamanlı sohbeti durdur"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Yenile"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Bağlanıyor..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway bağlı"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Перемкнути на задню камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Перемкнути на фронтальну камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Змінити камеру"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Зупинити"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Говорити"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Почати чат у реальному часі"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Зупинити чат у реальному часі"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Підключення..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway підключено"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Вкладення"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Говорити"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Почати чат у реальному часі"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Зупинити чат у реальному часі"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Оновити"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Підключення..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway підключено"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
+45
-25
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "Chuyển sang camera sau"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "Chuyển sang camera trước"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "Đổi chiều camera"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "Dừng"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "Nói"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Bắt đầu trò chuyện theo thời gian thực"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Dừng trò chuyện theo thời gian thực"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "Đang kết nối..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Đã kết nối Gateway"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "Tệp đính kèm"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "Nói chuyện"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "Bắt đầu trò chuyện thời gian thực"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "Dừng trò chuyện thời gian thực"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "Làm mới"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "Đang kết nối..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway đã kết nối"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "切换到后置摄像头"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "切换到前置摄像头"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "翻转摄像头"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "停止"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "说话"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "开始实时聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "停止实时聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "正在连接..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 已连接"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "附件"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "对话"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "开始实时聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "停止实时聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "刷新"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "正在连接..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 已连接"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
@@ -23068,6 +23068,51 @@
|
||||
"source": "<\\(tag)",
|
||||
"translated": "<\\(tag)"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.fc5931c1f0a6bbec",
|
||||
"source": "Switch to back camera",
|
||||
"translated": "切換至後置相機"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.cce3b539e31701c0",
|
||||
"source": "Switch to front camera",
|
||||
"translated": "切換至前置相機"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.f397daffdfd02ee0",
|
||||
"source": "Flip camera",
|
||||
"translated": "翻轉相機"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.11f8de87ca3fcb11",
|
||||
"source": "Stop",
|
||||
"translated": "停止"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.7c92bec1c8a83e43",
|
||||
"source": "Talk",
|
||||
"translated": "說話"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.dae61543f9b416ca",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "開始即時聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.d376b015a90792a9",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "停止即時聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ac48dbe25ac4d40d",
|
||||
"source": "Connecting...",
|
||||
"translated": "連線中..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ccce98756eb1dacd",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 已連線"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.03aca5cfee32f12d",
|
||||
"source": "Context %@%% used",
|
||||
@@ -23163,21 +23208,6 @@
|
||||
"source": "Attachments",
|
||||
"translated": "附件"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.ee2c0d22f5861159",
|
||||
"source": "Talk",
|
||||
"translated": "說話"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.5d5041aefe6dfddd",
|
||||
"source": "Start realtime chat",
|
||||
"translated": "開始即時聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.21a7d3a3386a2218",
|
||||
"source": "Stop realtime chat",
|
||||
"translated": "停止即時聊天"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.88c2de261ddae511",
|
||||
"source": "Start",
|
||||
@@ -23223,16 +23253,6 @@
|
||||
"source": "Refresh",
|
||||
"translated": "重新整理"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.6c984c0e3ed3a69e",
|
||||
"source": "Connecting...",
|
||||
"translated": "正在連線..."
|
||||
},
|
||||
{
|
||||
"id": "native.apple.898849eb2bcb0b53",
|
||||
"source": "Gateway connected",
|
||||
"translated": "Gateway 已連線"
|
||||
},
|
||||
{
|
||||
"id": "native.apple.b6adfcd17a6e73d7",
|
||||
"source": "Message…",
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"تعبير Cron، مثل 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"العودة إلى الصوت"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"تحدث"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"تحدّث"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s/%2$s متصلة"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"يُسمح لـ %1$s تطبيقات بإعادة التوجيه."</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"الدردشة"</string>
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"عبارت cron، مثلاً 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"بازگشت به صدا"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"گفتگو"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"صحبت"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s/%2$s آنلاین"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s برنامه مجاز به بازارسال."</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"گفتوگو"</string>
|
||||
|
||||
@@ -1204,7 +1204,7 @@
|
||||
<string name="native_ca1fd4548524cb2e" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Folder kosong"</string>
|
||||
<string name="native_ca7981b46ecf2c17" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Nonaktif"</string>
|
||||
<string name="native_cab94aba84f97f7f" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Tipografi"</string>
|
||||
<string name="native_cae7d57bc067a514" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Hentikan"</string>
|
||||
<string name="native_cae7d57bc067a514" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Berhenti"</string>
|
||||
<string name="native_cae98462b30650eb" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Belum ada utas yang cocok."</string>
|
||||
<string name="native_cba62d81f910c7f0" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Pemasangan Gateway berhasil.\nSetujui kapabilitas node ponsel ini dari UI operator."</string>
|
||||
<string name="native_cc4b66e7e22230c3" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Skill ini sudah terinstal, tetapi saat ini belum memenuhi syarat untuk dijalankan. Gunakan desktop atau CLI untuk mengubah konfigurasi."</string>
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Wyrażenie cron, np. 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Powrót do głosu"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Rozmawiaj"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Mów"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s/%2$s online"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Zezwolono %1$s aplikacjom na przekazywanie."</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Czat"</string>
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Cron-выражение, например 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Вернуться к голосу"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Разговор"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Говорить"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"В сети: %1$s/%2$s"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Разрешена переадресация для %1$s приложений."</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Чат"</string>
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"นิพจน์ cron เช่น 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"กลับไปที่เสียง"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"พูดคุย"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"พูด"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"ออนไลน์ %1$s/%2$s"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"อนุญาตให้ส่งต่อ %1$s แอป"</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"แชท"</string>
|
||||
|
||||
@@ -421,7 +421,7 @@
|
||||
<string name="native_4441146b0fe1d5c6" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"screenshot"</string>
|
||||
<string name="native_4481c2190a1b4bca" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Biểu thức cron, ví dụ 0 9 * * *"</string>
|
||||
<string name="native_4499e7b7e1c9ddbc" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Quay lại giọng nói"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Nói chuyện"</string>
|
||||
<string name="native_449f5a775762cdc5" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Nói"</string>
|
||||
<string name="native_45a64dc17588f2ca" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s/%2$s đang trực tuyến"</string>
|
||||
<string name="native_45a8847c4a6b2c81" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"%1$s ứng dụng được phép chuyển tiếp."</string>
|
||||
<string name="native_460b3a7da007b7af" formatted="false" tools:ignore="Typos,TypographyDashes,TypographyEllipsis">"Trò chuyện"</string>
|
||||
|
||||
@@ -68409,6 +68409,142 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Flip camera": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Flip camera"
|
||||
}
|
||||
},
|
||||
"zh-CN": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "翻转摄像头"
|
||||
}
|
||||
},
|
||||
"zh-TW": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "翻轉相機"
|
||||
}
|
||||
},
|
||||
"pt-BR": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Inverter câmera"
|
||||
}
|
||||
},
|
||||
"de": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Kamera wechseln"
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Cambiar de cámara"
|
||||
}
|
||||
},
|
||||
"ja-JP": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "カメラを切り替える"
|
||||
}
|
||||
},
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "카메라 전환"
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Inverser la caméra"
|
||||
}
|
||||
},
|
||||
"hi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "कैमरा पलटें"
|
||||
}
|
||||
},
|
||||
"ar": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "تبديل الكاميرا"
|
||||
}
|
||||
},
|
||||
"it": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Inverti fotocamera"
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Kamerayı çevir"
|
||||
}
|
||||
},
|
||||
"uk": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Змінити камеру"
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Balik kamera"
|
||||
}
|
||||
},
|
||||
"pl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Odwróć aparat"
|
||||
}
|
||||
},
|
||||
"th": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "สลับกล้อง"
|
||||
}
|
||||
},
|
||||
"vi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Đổi camera"
|
||||
}
|
||||
},
|
||||
"nl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Wissel van camera"
|
||||
}
|
||||
},
|
||||
"fa": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "تعویض دوربین"
|
||||
}
|
||||
},
|
||||
"ru": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Сменить камеру"
|
||||
}
|
||||
},
|
||||
"sv": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Vänd kameran"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"For local iOS app development": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
@@ -164289,6 +164425,278 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"Switch to back camera": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Switch to back camera"
|
||||
}
|
||||
},
|
||||
"zh-CN": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "切换到后置摄像头"
|
||||
}
|
||||
},
|
||||
"zh-TW": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "切換至後置相機"
|
||||
}
|
||||
},
|
||||
"pt-BR": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Alternar para a câmera traseira"
|
||||
}
|
||||
},
|
||||
"de": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Zur rückseitigen Kamera wechseln"
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Cambiar a la cámara trasera"
|
||||
}
|
||||
},
|
||||
"ja-JP": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "背面カメラに切り替える"
|
||||
}
|
||||
},
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "후면 카메라로 전환"
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Passer à la caméra arrière"
|
||||
}
|
||||
},
|
||||
"hi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "पीछे वाले कैमरे पर स्विच करें"
|
||||
}
|
||||
},
|
||||
"ar": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "التبديل إلى الكاميرا الخلفية"
|
||||
}
|
||||
},
|
||||
"it": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Passa alla fotocamera posteriore"
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Arka kameraya geç"
|
||||
}
|
||||
},
|
||||
"uk": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Перемкнутися на задню камеру"
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Beralih ke kamera belakang"
|
||||
}
|
||||
},
|
||||
"pl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Przełącz na tylny aparat"
|
||||
}
|
||||
},
|
||||
"th": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "สลับไปใช้กล้องหลัง"
|
||||
}
|
||||
},
|
||||
"vi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Chuyển sang camera sau"
|
||||
}
|
||||
},
|
||||
"nl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Schakel over naar de camera aan de achterkant"
|
||||
}
|
||||
},
|
||||
"fa": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "تغییر به دوربین پشتی"
|
||||
}
|
||||
},
|
||||
"ru": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Переключиться на заднюю камеру"
|
||||
}
|
||||
},
|
||||
"sv": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Byt till den bakre kameran"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Switch to front camera": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Switch to front camera"
|
||||
}
|
||||
},
|
||||
"zh-CN": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "切换到前置摄像头"
|
||||
}
|
||||
},
|
||||
"zh-TW": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "切換至前置相機"
|
||||
}
|
||||
},
|
||||
"pt-BR": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Alternar para a câmera frontal"
|
||||
}
|
||||
},
|
||||
"de": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Zur Frontkamera wechseln"
|
||||
}
|
||||
},
|
||||
"es": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Cambiar a la cámara frontal"
|
||||
}
|
||||
},
|
||||
"ja-JP": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "前面カメラに切り替える"
|
||||
}
|
||||
},
|
||||
"ko": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "전면 카메라로 전환"
|
||||
}
|
||||
},
|
||||
"fr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Passer à la caméra avant"
|
||||
}
|
||||
},
|
||||
"hi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "सामने वाले कैमरे पर स्विच करें"
|
||||
}
|
||||
},
|
||||
"ar": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "التبديل إلى الكاميرا الأمامية"
|
||||
}
|
||||
},
|
||||
"it": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Passa alla fotocamera anteriore"
|
||||
}
|
||||
},
|
||||
"tr": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Ön kameraya geç"
|
||||
}
|
||||
},
|
||||
"uk": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Перемкнутися на фронтальну камеру"
|
||||
}
|
||||
},
|
||||
"id": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Beralih ke kamera depan"
|
||||
}
|
||||
},
|
||||
"pl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Przełącz na przedni aparat"
|
||||
}
|
||||
},
|
||||
"th": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "สลับไปใช้กล้องหน้า"
|
||||
}
|
||||
},
|
||||
"vi": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Chuyển sang camera trước"
|
||||
}
|
||||
},
|
||||
"nl": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Schakel over naar de camera aan de voorkant"
|
||||
}
|
||||
},
|
||||
"fa": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "تغییر به دوربین جلو"
|
||||
}
|
||||
},
|
||||
"ru": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Переключиться на фронтальную камеру"
|
||||
}
|
||||
},
|
||||
"sv": {
|
||||
"stringUnit": {
|
||||
"state": "translated",
|
||||
"value": "Byt till den främre kameran"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"Switching to %@…": {
|
||||
"localizations": {
|
||||
"en": {
|
||||
|
||||
@@ -37,13 +37,15 @@ actor CameraController {
|
||||
}
|
||||
}
|
||||
|
||||
func snap(params: OpenClawCameraSnapParams) async throws -> (
|
||||
func snap(
|
||||
params: OpenClawCameraSnapParams,
|
||||
defaultFacing: OpenClawCameraFacing = .front) async throws -> (
|
||||
format: String,
|
||||
base64: String,
|
||||
width: Int,
|
||||
height: Int)
|
||||
{
|
||||
let facing = params.facing ?? .front
|
||||
let facing = Self.resolveFacing(params.facing, defaultFacing: defaultFacing)
|
||||
let format = params.format ?? .jpg
|
||||
// Default to a reasonable max width to keep gateway payload sizes manageable.
|
||||
// If you need the full-res photo, explicitly request a larger maxWidth.
|
||||
@@ -102,13 +104,15 @@ actor CameraController {
|
||||
height: res.heightPx)
|
||||
}
|
||||
|
||||
func clip(params: OpenClawCameraClipParams) async throws -> (
|
||||
func clip(
|
||||
params: OpenClawCameraClipParams,
|
||||
defaultFacing: OpenClawCameraFacing = .front) async throws -> (
|
||||
format: String,
|
||||
base64: String,
|
||||
durationMs: Int,
|
||||
hasAudio: Bool)
|
||||
{
|
||||
let facing = params.facing ?? .front
|
||||
let facing = Self.resolveFacing(params.facing, defaultFacing: defaultFacing)
|
||||
let durationMs = Self.clampDurationMs(params.durationMs)
|
||||
let includeAudio = params.includeAudio ?? true
|
||||
let format = params.format ?? .mp4
|
||||
@@ -247,6 +251,13 @@ actor CameraController {
|
||||
return min(60000, max(250, v))
|
||||
}
|
||||
|
||||
nonisolated static func resolveFacing(
|
||||
_ explicitFacing: OpenClawCameraFacing?,
|
||||
defaultFacing: OpenClawCameraFacing) -> OpenClawCameraFacing
|
||||
{
|
||||
explicitFacing ?? defaultFacing
|
||||
}
|
||||
|
||||
private nonisolated static func exportToMP4(inputURL: URL, outputURL: URL) async throws {
|
||||
try Task.checkCancellation()
|
||||
let asset = AVURLAsset(url: inputURL)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import AVFAudio
|
||||
import OpenClawChatUI
|
||||
import OpenClawProtocol
|
||||
import SwiftUI
|
||||
@@ -499,12 +500,34 @@ struct ChatProTab: View {
|
||||
statusText: self.appModel.talkMode.statusText,
|
||||
providerLabel: self.appModel.talkMode.gatewayTalkProviderLabel,
|
||||
level: self.talkLevel,
|
||||
inputDevices: self.talkInputDevices,
|
||||
selectedInputDeviceID: self.selectedTalkInputDeviceID,
|
||||
selectInputDevice: { deviceID in
|
||||
self.appModel.talkMode.selectInputDevice(deviceID)
|
||||
},
|
||||
cameraFacing: self.appModel.preferredCameraFacing == .front ? .front : .back,
|
||||
flipCamera: {
|
||||
self.appModel.flipPreferredCameraFacing()
|
||||
},
|
||||
toggle: { sessionKey in
|
||||
self.appModel.focusChatSession(sessionKey)
|
||||
self.appModel.setTalkEnabled(!self.appModel.talkMode.isEnabled)
|
||||
})
|
||||
}
|
||||
|
||||
private var talkInputDevices: [OpenClawChatAudioInputDevice] {
|
||||
(AVAudioSession.sharedInstance().availableInputs ?? []).map { input in
|
||||
OpenClawChatAudioInputDevice(id: input.uid, name: input.portName)
|
||||
}
|
||||
}
|
||||
|
||||
private var selectedTalkInputDeviceID: String? {
|
||||
guard let preferredID = self.appModel.talkMode.preferredInputDeviceID,
|
||||
self.talkInputDevices.contains(where: { $0.id == preferredID })
|
||||
else { return nil }
|
||||
return preferredID
|
||||
}
|
||||
|
||||
private var dictationControl: OpenClawChatDictationControl {
|
||||
OpenClawChatDictationControl(
|
||||
isActive: self.appModel.isChatDictationActive,
|
||||
|
||||
@@ -405,6 +405,7 @@ final class NodeAppModel {
|
||||
var isBackgrounded: Bool = false
|
||||
let screen: ScreenController
|
||||
private let camera: any CameraServicing
|
||||
private(set) var preferredCameraFacing: OpenClawCameraFacing
|
||||
private let screenRecorder: any ScreenRecordingServicing
|
||||
private var watchGatewayConnectionStatus: OpenClawWatchAppStatusCode?
|
||||
var gatewayStatusText: String = "Offline" {
|
||||
@@ -804,6 +805,7 @@ final class NodeAppModel {
|
||||
private static let watchExecApprovalBridgeStateKey = "watch.execApproval.bridge.state.v1"
|
||||
private static let backgroundAliveLastSuccessAtMsKey = "gateway.backgroundAlive.lastSuccessAtMs"
|
||||
private static let backgroundAliveLastTriggerKey = "gateway.backgroundAlive.lastTrigger"
|
||||
private static let preferredCameraFacingKey = "camera.preferredFacing"
|
||||
private static let foregroundResumeHealthTimeoutSeconds = 1
|
||||
private static let watchChatCompletionWaitMs = 75000
|
||||
private static let watchChatRunWaitSliceMs = 60000
|
||||
@@ -839,6 +841,8 @@ final class NodeAppModel {
|
||||
{
|
||||
self.screen = screen
|
||||
self.camera = camera
|
||||
self.preferredCameraFacing = Self.cameraFacingPreference(
|
||||
rawValue: UserDefaults.standard.string(forKey: Self.preferredCameraFacingKey))
|
||||
self.screenRecorder = screenRecorder
|
||||
self.locationService = locationService
|
||||
self.notificationCenter = notificationCenter
|
||||
@@ -2391,8 +2395,11 @@ final class NodeAppModel {
|
||||
triggerCameraFlash()
|
||||
let params = (try? Self.decodeParams(OpenClawCameraSnapParams.self, from: req.paramsJSON)) ??
|
||||
OpenClawCameraSnapParams()
|
||||
let defaultFacing = self.preferredCameraFacing
|
||||
let res = try await self.withForegroundCapture {
|
||||
try await self.camera.snap(params: params)
|
||||
try await self.camera.snap(
|
||||
params: params,
|
||||
defaultFacing: defaultFacing)
|
||||
}
|
||||
|
||||
struct Payload: Codable {
|
||||
@@ -2415,11 +2422,14 @@ final class NodeAppModel {
|
||||
OpenClawCameraClipParams()
|
||||
|
||||
let includeAudio = params.includeAudio ?? true
|
||||
let defaultFacing = self.preferredCameraFacing
|
||||
showCameraHUD(ownerID: req.id, text: "Recording…", kind: .recording)
|
||||
let res = try await self.withForegroundCapture(
|
||||
audioOwner: includeAudio ? .cameraClip : nil)
|
||||
{
|
||||
try await self.camera.clip(params: params)
|
||||
try await self.camera.clip(
|
||||
params: params,
|
||||
defaultFacing: defaultFacing)
|
||||
}
|
||||
|
||||
struct Payload: Codable {
|
||||
@@ -3440,6 +3450,21 @@ extension NodeAppModel {
|
||||
return UserDefaults.standard.bool(forKey: "camera.enabled")
|
||||
}
|
||||
|
||||
nonisolated static func cameraFacingPreference(rawValue: String?) -> OpenClawCameraFacing {
|
||||
rawValue.flatMap(OpenClawCameraFacing.init(rawValue:)) ?? .front
|
||||
}
|
||||
|
||||
func setPreferredCameraFacing(_ facing: OpenClawCameraFacing) {
|
||||
guard self.preferredCameraFacing != facing else { return }
|
||||
self.preferredCameraFacing = facing
|
||||
UserDefaults.standard.set(facing.rawValue, forKey: Self.preferredCameraFacingKey)
|
||||
}
|
||||
|
||||
func flipPreferredCameraFacing() {
|
||||
self.setPreferredCameraFacing(self.preferredCameraFacing == .front ? .back : .front)
|
||||
UIImpactFeedbackGenerator(style: .light).impactOccurred()
|
||||
}
|
||||
|
||||
private func triggerCameraFlash() {
|
||||
self.cameraFlashNonce &+= 1
|
||||
}
|
||||
|
||||
@@ -8,8 +8,12 @@ typealias OpenClawCameraClipResult = (format: String, base64: String, durationMs
|
||||
|
||||
protocol CameraServicing: Sendable {
|
||||
func listDevices() async -> [CameraController.CameraDeviceInfo]
|
||||
func snap(params: OpenClawCameraSnapParams) async throws -> OpenClawCameraSnapResult
|
||||
func clip(params: OpenClawCameraClipParams) async throws -> OpenClawCameraClipResult
|
||||
func snap(
|
||||
params: OpenClawCameraSnapParams,
|
||||
defaultFacing: OpenClawCameraFacing) async throws -> OpenClawCameraSnapResult
|
||||
func clip(
|
||||
params: OpenClawCameraClipParams,
|
||||
defaultFacing: OpenClawCameraFacing) async throws -> OpenClawCameraClipResult
|
||||
}
|
||||
|
||||
protocol ScreenRecordingServicing: Sendable {
|
||||
|
||||
@@ -133,6 +133,7 @@ final class TalkModeManager: NSObject {
|
||||
private static let defaultSilenceTimeoutMs = TalkDefaults.silenceTimeoutMs
|
||||
private static let redactedConfigSentinel = "__OPENCLAW_REDACTED__"
|
||||
private static let realtimePrefetchExpiryLeewaySeconds: TimeInterval = 30
|
||||
private static let preferredInputDeviceIDKey = "talk.preferredInputDeviceID"
|
||||
var isEnabled: Bool = false
|
||||
var isListening: Bool = false
|
||||
var isSpeaking: Bool = false
|
||||
@@ -156,6 +157,7 @@ final class TalkModeManager: NSObject {
|
||||
/// voice path exposes no real level (system voice, compressed streaming); the
|
||||
/// waveform then falls back to a synthetic pulse.
|
||||
var playbackLevel: Double?
|
||||
private(set) var preferredInputDeviceID: String?
|
||||
var gatewayTalkConfigLoaded: Bool = false
|
||||
var gatewayTalkApiKeyConfigured: Bool = false
|
||||
var gatewayTalkDefaultModelId: String?
|
||||
@@ -480,9 +482,24 @@ final class TalkModeManager: NSObject {
|
||||
self.allowSimulatorCapture = allowSimulatorCapture
|
||||
self.gatewaySpeechSynthesizerOverride = gatewaySpeechSynthesizer
|
||||
self.audioSessionDeactivationAction = audioSessionDeactivationAction
|
||||
self.preferredInputDeviceID = UserDefaults.standard.string(
|
||||
forKey: Self.preferredInputDeviceIDKey)
|
||||
super.init()
|
||||
}
|
||||
|
||||
func selectInputDevice(_ deviceID: String?) {
|
||||
let normalizedID = deviceID.flatMap { $0.isEmpty ? nil : $0 }
|
||||
self.preferredInputDeviceID = normalizedID
|
||||
if let normalizedID {
|
||||
UserDefaults.standard.set(normalizedID, forKey: Self.preferredInputDeviceIDKey)
|
||||
} else {
|
||||
UserDefaults.standard.removeObject(forKey: Self.preferredInputDeviceIDKey)
|
||||
}
|
||||
|
||||
guard self.audioSessionIsActive else { return }
|
||||
Self.applyPreferredInput(normalizedID, to: AVAudioSession.sharedInstance())
|
||||
}
|
||||
|
||||
func attachGateway(_ gateway: GatewayNodeSession) {
|
||||
if let current = self.gateway, current !== gateway {
|
||||
// Local dictation has no gateway owner, so a route replacement must
|
||||
@@ -2200,6 +2217,9 @@ final class TalkModeManager: NSObject {
|
||||
session.stop()
|
||||
return .ignored
|
||||
}
|
||||
// WebRTC configures the shared session and may force speaker + built-in mic.
|
||||
// Apply the user's input last so the explicit microphone selection wins.
|
||||
Self.applyPreferredInput(self.preferredInputDeviceID, to: AVAudioSession.sharedInstance())
|
||||
self.markRealtimeSessionReady()
|
||||
GatewayDiagnostics.log(
|
||||
"talk.timeline realtime start ready elapsedMs=\(Self.elapsedMs(since: startedAt))")
|
||||
@@ -4287,12 +4307,12 @@ extension TalkModeManager {
|
||||
}
|
||||
|
||||
private func configureOwnedAudioSession() throws {
|
||||
try Self.configureAudioSession()
|
||||
try Self.configureAudioSession(preferredInputDeviceID: self.preferredInputDeviceID)
|
||||
self.audioSessionIsActive = true
|
||||
}
|
||||
|
||||
private func configureOwnedRealtimeAudioSession() throws {
|
||||
try Self.configureRealtimeAudioSession()
|
||||
try Self.configureRealtimeAudioSession(preferredInputDeviceID: self.preferredInputDeviceID)
|
||||
self.audioSessionIsActive = true
|
||||
}
|
||||
|
||||
@@ -4320,7 +4340,7 @@ extension TalkModeManager {
|
||||
}
|
||||
}
|
||||
|
||||
static func configureAudioSession() throws {
|
||||
static func configureAudioSession(preferredInputDeviceID: String? = nil) throws {
|
||||
let session = AVAudioSession.sharedInstance()
|
||||
let forceSpeaker = TalkDefaults.speakerphoneEnabled()
|
||||
let options = TalkAudioRoute.categoryOptions(speakerphoneEnabled: forceSpeaker)
|
||||
@@ -4337,10 +4357,12 @@ extension TalkModeManager {
|
||||
} else {
|
||||
try? session.overrideOutputAudioPort(.none)
|
||||
}
|
||||
// A speaker override also forces the built-in microphone; apply an explicit input last.
|
||||
self.applyPreferredInput(preferredInputDeviceID, to: session)
|
||||
GatewayDiagnostics.log("talk audio: session speakerphone=\(forceSpeaker) \(Self.describeAudioSession())")
|
||||
}
|
||||
|
||||
static func configureRealtimeAudioSession() throws {
|
||||
static func configureRealtimeAudioSession(preferredInputDeviceID: String? = nil) throws {
|
||||
let session = AVAudioSession.sharedInstance()
|
||||
let forceSpeaker = TalkDefaults.speakerphoneEnabled()
|
||||
let options = TalkAudioRoute.categoryOptions(speakerphoneEnabled: forceSpeaker)
|
||||
@@ -4358,10 +4380,24 @@ extension TalkModeManager {
|
||||
} else {
|
||||
try? session.overrideOutputAudioPort(.none)
|
||||
}
|
||||
// A speaker override also forces the built-in microphone; apply an explicit input last.
|
||||
self.applyPreferredInput(preferredInputDeviceID, to: session)
|
||||
GatewayDiagnostics.log(
|
||||
"talk realtime audio: session speakerphone=\(forceSpeaker) \(Self.describeAudioSession())")
|
||||
}
|
||||
|
||||
private static func applyPreferredInput(_ deviceID: String?, to session: AVAudioSession) {
|
||||
let input = deviceID.flatMap { id in
|
||||
session.availableInputs?.first(where: { $0.uid == id })
|
||||
}
|
||||
do {
|
||||
try session.setPreferredInput(input)
|
||||
} catch {
|
||||
try? session.setPreferredInput(nil)
|
||||
GatewayDiagnostics.log("talk audio: preferred input update failed: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
private static func describeAudioSession() -> String {
|
||||
let session = AVAudioSession.sharedInstance()
|
||||
let inputs = session.currentRoute.inputs
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import Testing
|
||||
@testable import OpenClaw
|
||||
|
||||
@Suite struct CameraControllerClampTests {
|
||||
@Test func clampQualityDefaultsAndBounds() {
|
||||
struct CameraControllerClampTests {
|
||||
@Test func `clamp quality defaults and bounds`() {
|
||||
#expect(CameraController.clampQuality(nil) == 0.9)
|
||||
#expect(CameraController.clampQuality(0.0) == 0.05)
|
||||
#expect(CameraController.clampQuality(0.049) == 0.05)
|
||||
@@ -12,7 +12,7 @@ import Testing
|
||||
#expect(CameraController.clampQuality(1.1) == 1.0)
|
||||
}
|
||||
|
||||
@Test func clampDurationDefaultsAndBounds() {
|
||||
@Test func `clamp duration defaults and bounds`() {
|
||||
#expect(CameraController.clampDurationMs(nil) == 3000)
|
||||
#expect(CameraController.clampDurationMs(0) == 250)
|
||||
#expect(CameraController.clampDurationMs(249) == 250)
|
||||
@@ -21,4 +21,11 @@ import Testing
|
||||
#expect(CameraController.clampDurationMs(60000) == 60000)
|
||||
#expect(CameraController.clampDurationMs(60001) == 60000)
|
||||
}
|
||||
|
||||
@Test func `preferred facing defaults and explicit override`() {
|
||||
#expect(NodeAppModel.cameraFacingPreference(rawValue: nil) == .front)
|
||||
#expect(NodeAppModel.cameraFacingPreference(rawValue: "back") == .back)
|
||||
#expect(CameraController.resolveFacing(nil, defaultFacing: .back) == .back)
|
||||
#expect(CameraController.resolveFacing(.front, defaultFacing: .back) == .front)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,11 +34,17 @@ private actor CancellingCameraService: CameraServicing {
|
||||
[]
|
||||
}
|
||||
|
||||
func snap(params _: OpenClawCameraSnapParams) async throws -> OpenClawCameraSnapResult {
|
||||
func snap(
|
||||
params _: OpenClawCameraSnapParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraSnapResult
|
||||
{
|
||||
throw CancellationError()
|
||||
}
|
||||
|
||||
func clip(params _: OpenClawCameraClipParams) async throws -> OpenClawCameraClipResult {
|
||||
func clip(
|
||||
params _: OpenClawCameraClipParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraClipResult
|
||||
{
|
||||
throw CancellationError()
|
||||
}
|
||||
}
|
||||
@@ -50,11 +56,17 @@ private actor RecordingCameraService: CameraServicing {
|
||||
[]
|
||||
}
|
||||
|
||||
func snap(params _: OpenClawCameraSnapParams) async throws -> OpenClawCameraSnapResult {
|
||||
func snap(
|
||||
params _: OpenClawCameraSnapParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraSnapResult
|
||||
{
|
||||
(format: "jpg", base64: "", width: 1, height: 1)
|
||||
}
|
||||
|
||||
func clip(params _: OpenClawCameraClipParams) async throws -> OpenClawCameraClipResult {
|
||||
func clip(
|
||||
params _: OpenClawCameraClipParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraClipResult
|
||||
{
|
||||
self.clipCalls += 1
|
||||
return (format: "mp4", base64: "", durationMs: 1, hasAudio: true)
|
||||
}
|
||||
@@ -105,11 +117,17 @@ private actor BlockingAudioCameraService: CameraServicing {
|
||||
[]
|
||||
}
|
||||
|
||||
func snap(params _: OpenClawCameraSnapParams) async throws -> OpenClawCameraSnapResult {
|
||||
func snap(
|
||||
params _: OpenClawCameraSnapParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraSnapResult
|
||||
{
|
||||
(format: "jpg", base64: "", width: 1, height: 1)
|
||||
}
|
||||
|
||||
func clip(params _: OpenClawCameraClipParams) async throws -> OpenClawCameraClipResult {
|
||||
func clip(
|
||||
params _: OpenClawCameraClipParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraClipResult
|
||||
{
|
||||
await self.barrier.suspendFirstPreparation()
|
||||
try Task.checkCancellation()
|
||||
return (format: "mp4", base64: "", durationMs: 1, hasAudio: true)
|
||||
@@ -186,7 +204,10 @@ private actor OverlappingCameraService: CameraServicing {
|
||||
[]
|
||||
}
|
||||
|
||||
func snap(params _: OpenClawCameraSnapParams) async throws -> OpenClawCameraSnapResult {
|
||||
func snap(
|
||||
params _: OpenClawCameraSnapParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraSnapResult
|
||||
{
|
||||
self.snapCount += 1
|
||||
if self.snapCount == 1 {
|
||||
self.firstStarted.yield()
|
||||
@@ -201,7 +222,10 @@ private actor OverlappingCameraService: CameraServicing {
|
||||
return (format: "jpg", base64: "", width: 1, height: 1)
|
||||
}
|
||||
|
||||
func clip(params _: OpenClawCameraClipParams) async throws -> OpenClawCameraClipResult {
|
||||
func clip(
|
||||
params _: OpenClawCameraClipParams,
|
||||
defaultFacing _: OpenClawCameraFacing) async throws -> OpenClawCameraClipResult
|
||||
{
|
||||
throw CancellationError()
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,214 @@
|
||||
import Foundation
|
||||
import SwiftUI
|
||||
|
||||
@MainActor
|
||||
struct ChatCameraFlipButton: View {
|
||||
let control: OpenClawChatTalkControl
|
||||
let size: CGFloat
|
||||
|
||||
static func isAvailable(for control: OpenClawChatTalkControl) -> Bool {
|
||||
control.isEnabled && control.cameraFacing != nil && control.flipCamera != nil
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
self.control.flipCamera?()
|
||||
} label: {
|
||||
Image(systemName: "arrow.triangle.2.circlepath.camera")
|
||||
.font(OpenClawChatTypography.body(size: 14, weight: .semibold, relativeTo: .subheadline))
|
||||
.foregroundStyle(.primary)
|
||||
.frame(width: self.size, height: self.size)
|
||||
.background {
|
||||
Circle()
|
||||
.fill(OpenClawChatTheme.accent.opacity(0.12))
|
||||
}
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.accessibilityLabel(self.accessibilityLabel)
|
||||
.accessibilityIdentifier("chat-camera-flip")
|
||||
.help(self.accessibilityLabel)
|
||||
}
|
||||
|
||||
private var accessibilityLabel: String {
|
||||
switch self.control.cameraFacing {
|
||||
case .front:
|
||||
String(localized: "Switch to back camera")
|
||||
case .back:
|
||||
String(localized: "Switch to front camera")
|
||||
case nil:
|
||||
String(localized: "Flip camera")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
struct ChatTalkButton: View {
|
||||
enum Style {
|
||||
case full
|
||||
case compact(controlHeight: CGFloat, iconControlSize: CGFloat)
|
||||
}
|
||||
|
||||
let control: OpenClawChatTalkControl
|
||||
let sessionKey: String
|
||||
let helpText: String
|
||||
let style: Style
|
||||
|
||||
var body: some View {
|
||||
switch self.style {
|
||||
case .full:
|
||||
self.fullButton
|
||||
case let .compact(controlHeight, iconControlSize):
|
||||
self.compactButton(controlHeight: controlHeight, iconControlSize: iconControlSize)
|
||||
}
|
||||
}
|
||||
|
||||
private var fullButton: some View {
|
||||
Button {
|
||||
self.control.toggle(self.sessionKey)
|
||||
} label: {
|
||||
HStack(spacing: 6) {
|
||||
ChatTalkButtonGlyph(control: self.control)
|
||||
.font(OpenClawChatTypography.captionSemiBold)
|
||||
Text(self.control.isEnabled ? "Stop" : "Talk")
|
||||
.font(OpenClawChatTypography.captionSemiBold)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.foregroundStyle(self.control.isEnabled ? .white : .primary)
|
||||
.padding(.horizontal, 10)
|
||||
.frame(height: 32)
|
||||
.background {
|
||||
Capsule()
|
||||
.fill(self.fill)
|
||||
}
|
||||
.overlay {
|
||||
Capsule()
|
||||
.strokeBorder(self.stroke, lineWidth: 1)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(!self.control.isGatewayConnected && !self.control.isEnabled)
|
||||
.accessibilityLabel(self.control.isEnabled ? "Stop realtime chat" : "Start realtime chat")
|
||||
.accessibilityValue(self.accessibilityValue)
|
||||
.accessibilityIdentifier("chat-realtime-control")
|
||||
.help(self.helpText)
|
||||
.chatTalkInputDeviceMenu(self.control)
|
||||
}
|
||||
|
||||
private func compactButton(controlHeight: CGFloat, iconControlSize: CGFloat) -> some View {
|
||||
Button {
|
||||
self.control.toggle(self.sessionKey)
|
||||
} label: {
|
||||
ChatTalkButtonGlyph(control: self.control)
|
||||
.font(OpenClawChatTypography.body(size: 14, weight: .semibold, relativeTo: .subheadline))
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: iconControlSize, height: iconControlSize)
|
||||
// Prominent filled circle so the mic reads as the primary action,
|
||||
// mirroring the send button it swaps with once a draft exists.
|
||||
.background {
|
||||
Circle()
|
||||
.fill(self.control.isEnabled ? self.fill : AnyShapeStyle(OpenClawChatTheme.accent))
|
||||
.opacity(self.control.isGatewayConnected || self.control.isEnabled ? 1 : 0.4)
|
||||
}
|
||||
.frame(width: controlHeight, height: controlHeight)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(!self.control.isGatewayConnected && !self.control.isEnabled)
|
||||
.accessibilityLabel(self.control.isEnabled ? "Stop realtime chat" : "Start realtime chat")
|
||||
.accessibilityValue(self.accessibilityValue)
|
||||
.accessibilityIdentifier("chat-realtime-control")
|
||||
.help(self.helpText)
|
||||
.chatTalkInputDeviceMenu(self.control)
|
||||
}
|
||||
|
||||
private var fill: AnyShapeStyle {
|
||||
if self.control.isEnabled {
|
||||
return AnyShapeStyle(OpenClawChatTheme.userBubble)
|
||||
}
|
||||
if !self.control.isGatewayConnected {
|
||||
return AnyShapeStyle(Color.secondary.opacity(0.12))
|
||||
}
|
||||
return OpenClawChatTheme.subtleCard
|
||||
}
|
||||
|
||||
private var stroke: Color {
|
||||
if self.control.isEnabled {
|
||||
return Color.white.opacity(0.18)
|
||||
}
|
||||
return OpenClawChatTheme.composerBorder
|
||||
}
|
||||
|
||||
private var accessibilityValue: String {
|
||||
let status = self.control.statusText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let provider = self.control.providerLabel.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return [status, provider].filter { !$0.isEmpty }.joined(separator: ", ")
|
||||
}
|
||||
}
|
||||
|
||||
extension OpenClawChatComposer {
|
||||
/// Local capture and realtime Talk share one microphone, so the Talk affordance
|
||||
/// must yield until dictation or voice-note capture releases audio ownership.
|
||||
nonisolated static func showsCompactTalkControl(
|
||||
hasDraftToSend: Bool,
|
||||
hasBlockingRunActivity: Bool,
|
||||
isLocalVoiceCaptureActive: Bool) -> Bool
|
||||
{
|
||||
!hasDraftToSend && !hasBlockingRunActivity && !isLocalVoiceCaptureActive
|
||||
}
|
||||
}
|
||||
|
||||
@MainActor
|
||||
enum ChatDictationActions {
|
||||
static func start(
|
||||
_ control: OpenClawChatDictationControl,
|
||||
task: Binding<Task<Void, Never>?>,
|
||||
viewModel: OpenClawChatViewModel)
|
||||
{
|
||||
guard task.wrappedValue == nil else { return }
|
||||
let session = viewModel.currentSessionSnapshot()
|
||||
task.wrappedValue = Task { @MainActor in
|
||||
defer { task.wrappedValue = nil }
|
||||
do {
|
||||
guard let transcript = try await control.start(), !transcript.isEmpty else { return }
|
||||
try Task.checkCancellation()
|
||||
viewModel.appendDictationTranscript(transcript, for: session)
|
||||
} catch is CancellationError {
|
||||
return
|
||||
} catch {
|
||||
guard !Task.isCancelled else { return }
|
||||
viewModel.setDictationError(error, for: session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static func cancel(
|
||||
task: Binding<Task<Void, Never>?>,
|
||||
control: OpenClawChatDictationControl?)
|
||||
{
|
||||
guard task.wrappedValue != nil else { return }
|
||||
task.wrappedValue?.cancel()
|
||||
control?.cancel()
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatConnectionPill: View {
|
||||
let isConnected: Bool
|
||||
|
||||
var body: some View {
|
||||
HStack(spacing: 6) {
|
||||
Circle()
|
||||
.fill(self.isConnected ? .green : .orange)
|
||||
.frame(width: 7, height: 7)
|
||||
Text(self.isConnected ? "Gateway connected" : "Connecting...")
|
||||
.font(OpenClawChatTypography.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 4)
|
||||
.background {
|
||||
Capsule()
|
||||
.fill(OpenClawChatTheme.subtleCard)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,7 +186,7 @@ struct OpenClawChatComposer: View {
|
||||
private var lifecycleComposer: some View {
|
||||
self.recorderLifecycleComposer
|
||||
.onChange(of: self.presentationOwner) { _, _ in
|
||||
self.cancelActiveDictation()
|
||||
ChatDictationActions.cancel(task: self.$dictationTask, control: self.dictationControl)
|
||||
#if !os(macOS)
|
||||
self.showsPhotoPicker = false
|
||||
self.showsFileImporter = false
|
||||
@@ -204,7 +204,7 @@ struct OpenClawChatComposer: View {
|
||||
self.stageCompletedVoiceNoteIfNeeded()
|
||||
}
|
||||
.onDisappear {
|
||||
self.cancelActiveDictation()
|
||||
ChatDictationActions.cancel(task: self.$dictationTask, control: self.dictationControl)
|
||||
#if !os(macOS)
|
||||
self.showsPhotoPicker = false
|
||||
self.showsFileImporter = false
|
||||
@@ -696,10 +696,18 @@ struct OpenClawChatComposer: View {
|
||||
|
||||
HStack(alignment: .center, spacing: 8) {
|
||||
if let talkControl {
|
||||
self.talkButton(talkControl)
|
||||
ChatTalkButton(
|
||||
control: talkControl,
|
||||
sessionKey: self.viewModel.sessionKey,
|
||||
helpText: self.talkHelpText(talkControl),
|
||||
style: .full)
|
||||
if ChatCameraFlipButton.isAvailable(for: talkControl) {
|
||||
ChatCameraFlipButton(control: talkControl, size: 32)
|
||||
}
|
||||
}
|
||||
if self.showsConnectionPill {
|
||||
self.connectionPill
|
||||
ChatConnectionPill(
|
||||
isConnected: self.viewModel.healthOK || (self.talkControl?.isGatewayConnected ?? false))
|
||||
}
|
||||
Spacer(minLength: 0)
|
||||
self.sendButton
|
||||
@@ -756,15 +764,22 @@ struct OpenClawChatComposer: View {
|
||||
isComposerEnabled: self.isComposerEnabled,
|
||||
isAttachmentInputEnabled: self.isAttachmentInputEnabled,
|
||||
onCancelDictation: {
|
||||
self.cancelActiveDictation()
|
||||
ChatDictationActions.cancel(task: self.$dictationTask, control: self.dictationControl)
|
||||
},
|
||||
onStartDictation: {
|
||||
if let dictationControl = self.dictationControl {
|
||||
self.startDictation(dictationControl)
|
||||
ChatDictationActions.start(
|
||||
dictationControl,
|
||||
task: self.$dictationTask,
|
||||
viewModel: self.viewModel)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if let talkControl, ChatCameraFlipButton.isAvailable(for: talkControl) {
|
||||
ChatCameraFlipButton(control: talkControl, size: self.cleanControlHeight)
|
||||
}
|
||||
|
||||
self.cleanTrailingControl
|
||||
}
|
||||
}
|
||||
@@ -779,7 +794,13 @@ struct OpenClawChatComposer: View {
|
||||
isLocalVoiceCaptureActive: self.isLocalVoiceCaptureActive),
|
||||
let talkControl
|
||||
{
|
||||
self.compactTalkButton(talkControl)
|
||||
ChatTalkButton(
|
||||
control: talkControl,
|
||||
sessionKey: self.viewModel.sessionKey,
|
||||
helpText: self.talkHelpText(talkControl),
|
||||
style: .compact(
|
||||
controlHeight: self.cleanControlHeight,
|
||||
iconControlSize: self.cleanIconControlSize))
|
||||
} else {
|
||||
sendButton
|
||||
.frame(width: cleanControlHeight, height: cleanControlHeight)
|
||||
@@ -793,124 +814,6 @@ struct OpenClawChatComposer: View {
|
||||
self.voiceNoteControl?.recorder.isRequestingPermission == true
|
||||
}
|
||||
|
||||
/// Local capture and realtime Talk share one microphone, so the Talk affordance
|
||||
/// must yield until dictation or voice-note capture releases audio ownership.
|
||||
nonisolated static func showsCompactTalkControl(
|
||||
hasDraftToSend: Bool,
|
||||
hasBlockingRunActivity: Bool,
|
||||
isLocalVoiceCaptureActive: Bool) -> Bool
|
||||
{
|
||||
!hasDraftToSend && !hasBlockingRunActivity && !isLocalVoiceCaptureActive
|
||||
}
|
||||
|
||||
private func talkButton(_ talkControl: OpenClawChatTalkControl) -> some View {
|
||||
Button {
|
||||
talkControl.toggle(self.viewModel.sessionKey)
|
||||
} label: {
|
||||
HStack(spacing: 6) {
|
||||
ChatTalkButtonGlyph(control: talkControl)
|
||||
.font(OpenClawChatTypography.captionSemiBold)
|
||||
Text(talkControl.isEnabled ? "Stop" : "Talk")
|
||||
.font(OpenClawChatTypography.captionSemiBold)
|
||||
.lineLimit(1)
|
||||
}
|
||||
.foregroundStyle(talkControl.isEnabled ? .white : .primary)
|
||||
.padding(.horizontal, 10)
|
||||
.frame(height: 32)
|
||||
.background {
|
||||
Capsule()
|
||||
.fill(self.talkButtonFill(talkControl))
|
||||
}
|
||||
.overlay {
|
||||
Capsule()
|
||||
.strokeBorder(self.talkButtonStroke(talkControl), lineWidth: 1)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(!talkControl.isGatewayConnected && !talkControl.isEnabled)
|
||||
.accessibilityLabel(talkControl.isEnabled ? "Stop realtime chat" : "Start realtime chat")
|
||||
.accessibilityValue(self.talkAccessibilityValue(talkControl))
|
||||
.accessibilityIdentifier("chat-realtime-control")
|
||||
.help(self.talkHelpText(talkControl))
|
||||
.chatTalkInputDeviceMenu(talkControl)
|
||||
}
|
||||
|
||||
private func startDictation(_ control: OpenClawChatDictationControl) {
|
||||
guard self.dictationTask == nil else { return }
|
||||
let session = self.viewModel.currentSessionSnapshot()
|
||||
self.dictationTask = Task { @MainActor in
|
||||
defer { self.dictationTask = nil }
|
||||
do {
|
||||
guard let transcript = try await control.start(), !transcript.isEmpty else { return }
|
||||
try Task.checkCancellation()
|
||||
self.viewModel.appendDictationTranscript(transcript, for: session)
|
||||
} catch is CancellationError {
|
||||
return
|
||||
} catch {
|
||||
guard !Task.isCancelled else { return }
|
||||
self.viewModel.setDictationError(error, for: session)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func cancelActiveDictation() {
|
||||
guard self.dictationTask != nil else { return }
|
||||
self.dictationTask?.cancel()
|
||||
self.dictationControl?.cancel()
|
||||
}
|
||||
|
||||
private func compactTalkButton(_ talkControl: OpenClawChatTalkControl) -> some View {
|
||||
Button {
|
||||
talkControl.toggle(self.viewModel.sessionKey)
|
||||
} label: {
|
||||
ChatTalkButtonGlyph(control: talkControl)
|
||||
.font(OpenClawChatTypography.body(size: 14, weight: .semibold, relativeTo: .subheadline))
|
||||
.foregroundStyle(.white)
|
||||
.frame(width: self.cleanIconControlSize, height: self.cleanIconControlSize)
|
||||
// Prominent filled circle so the mic reads as the primary action,
|
||||
// mirroring the send button it swaps with once a draft exists.
|
||||
.background {
|
||||
Circle()
|
||||
.fill(talkControl.isEnabled
|
||||
? self.talkButtonFill(talkControl)
|
||||
: AnyShapeStyle(OpenClawChatTheme.accent))
|
||||
.opacity(talkControl.isGatewayConnected || talkControl.isEnabled ? 1 : 0.4)
|
||||
}
|
||||
.frame(width: self.cleanControlHeight, height: self.cleanControlHeight)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(!talkControl.isGatewayConnected && !talkControl.isEnabled)
|
||||
.accessibilityLabel(talkControl.isEnabled ? "Stop realtime chat" : "Start realtime chat")
|
||||
.accessibilityValue(self.talkAccessibilityValue(talkControl))
|
||||
.accessibilityIdentifier("chat-realtime-control")
|
||||
.help(self.talkHelpText(talkControl))
|
||||
.chatTalkInputDeviceMenu(talkControl)
|
||||
}
|
||||
|
||||
private func talkButtonFill(_ talkControl: OpenClawChatTalkControl) -> AnyShapeStyle {
|
||||
if talkControl.isEnabled {
|
||||
return AnyShapeStyle(OpenClawChatTheme.userBubble)
|
||||
}
|
||||
if !talkControl.isGatewayConnected {
|
||||
return AnyShapeStyle(Color.secondary.opacity(0.12))
|
||||
}
|
||||
return OpenClawChatTheme.subtleCard
|
||||
}
|
||||
|
||||
private func talkButtonStroke(_ talkControl: OpenClawChatTalkControl) -> Color {
|
||||
if talkControl.isEnabled {
|
||||
return Color.white.opacity(0.18)
|
||||
}
|
||||
return OpenClawChatTheme.composerBorder
|
||||
}
|
||||
|
||||
private func talkAccessibilityValue(_ talkControl: OpenClawChatTalkControl) -> String {
|
||||
let status = talkControl.statusText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
let provider = talkControl.providerLabel.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||
return [status, provider].filter { !$0.isEmpty }.joined(separator: ", ")
|
||||
}
|
||||
|
||||
private func talkHelpText(_ talkControl: OpenClawChatTalkControl) -> String {
|
||||
if !talkControl.isGatewayConnected, !talkControl.isEnabled {
|
||||
return "Connect the gateway before starting realtime chat"
|
||||
@@ -919,25 +822,6 @@ struct OpenClawChatComposer: View {
|
||||
return "\(action) realtime chat for \(self.activeSessionLabel)"
|
||||
}
|
||||
|
||||
private var connectionPill: some View {
|
||||
HStack(spacing: 6) {
|
||||
Circle()
|
||||
.fill(self.connectionOK ? .green : .orange)
|
||||
.frame(width: 7, height: 7)
|
||||
Text(self.connectionStatusText)
|
||||
.font(OpenClawChatTypography.caption2)
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
.padding(.horizontal, self.composerChrome == .clean ? 0 : 8)
|
||||
.padding(.vertical, self.composerChrome == .clean ? 0 : 4)
|
||||
.background {
|
||||
if self.composerChrome == .full {
|
||||
Capsule()
|
||||
.fill(OpenClawChatTheme.subtleCard)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var activeSessionLabel: String {
|
||||
let match = self.viewModel.sessions.first { $0.key == self.viewModel.sessionKey }
|
||||
let trimmed = match?.displayName?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
@@ -1454,14 +1338,6 @@ extension OpenClawChatComposer {
|
||||
recorder.cancel()
|
||||
}
|
||||
|
||||
private var connectionStatusText: String {
|
||||
self.connectionOK ? "Gateway connected" : "Connecting..."
|
||||
}
|
||||
|
||||
private var connectionOK: Bool {
|
||||
self.viewModel.healthOK || (self.talkControl?.isGatewayConnected ?? false)
|
||||
}
|
||||
|
||||
private var placeholderText: String {
|
||||
let trimmed = self.messagePlaceholder?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
|
||||
return trimmed.isEmpty ? "Message…" : trimmed
|
||||
|
||||
@@ -8,6 +8,11 @@ public struct OpenClawChatAudioInputDevice: Equatable, Identifiable, Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
public enum OpenClawCameraFacingSelection: String, Equatable, Sendable {
|
||||
case back
|
||||
case front
|
||||
}
|
||||
|
||||
public struct OpenClawChatTalkControl {
|
||||
public var isEnabled: Bool
|
||||
public var isListening: Bool
|
||||
@@ -21,6 +26,8 @@ public struct OpenClawChatTalkControl {
|
||||
public var inputDevices: [OpenClawChatAudioInputDevice]
|
||||
public var selectedInputDeviceID: String?
|
||||
public var selectInputDevice: (@MainActor (_ deviceID: String?) -> Void)?
|
||||
public var cameraFacing: OpenClawCameraFacingSelection?
|
||||
public var flipCamera: (@MainActor () -> Void)?
|
||||
public var toggle: @MainActor (_ sessionKey: String) -> Void
|
||||
|
||||
public init(
|
||||
@@ -36,6 +43,8 @@ public struct OpenClawChatTalkControl {
|
||||
inputDevices: [OpenClawChatAudioInputDevice] = [],
|
||||
selectedInputDeviceID: String? = nil,
|
||||
selectInputDevice: (@MainActor (_ deviceID: String?) -> Void)? = nil,
|
||||
cameraFacing: OpenClawCameraFacingSelection? = nil,
|
||||
flipCamera: (@MainActor () -> Void)? = nil,
|
||||
toggle: @escaping @MainActor (_ sessionKey: String) -> Void)
|
||||
{
|
||||
self.isEnabled = isEnabled
|
||||
@@ -50,6 +59,8 @@ public struct OpenClawChatTalkControl {
|
||||
self.inputDevices = inputDevices
|
||||
self.selectedInputDeviceID = selectedInputDeviceID
|
||||
self.selectInputDevice = selectInputDevice
|
||||
self.cameraFacing = cameraFacing
|
||||
self.flipCamera = flipCamera
|
||||
self.toggle = toggle
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,13 @@ struct ChatTalkControlTests {
|
||||
#expect(control.inputDevices.isEmpty)
|
||||
#expect(control.selectedInputDeviceID == nil)
|
||||
#expect(control.selectInputDevice == nil)
|
||||
#expect(control.cameraFacing == nil)
|
||||
#expect(control.flipCamera == nil)
|
||||
}
|
||||
|
||||
@Test func `feedback and input selection fields preserve supplied values`() {
|
||||
var selectedID: String? = "unchanged"
|
||||
var flipCount = 0
|
||||
let devices = [OpenClawChatAudioInputDevice(id: "mic-1", name: "Desk Mic")]
|
||||
let control = OpenClawChatTalkControl(
|
||||
isEnabled: true,
|
||||
@@ -37,9 +40,12 @@ struct ChatTalkControlTests {
|
||||
inputDevices: devices,
|
||||
selectedInputDeviceID: "mic-1",
|
||||
selectInputDevice: { selectedID = $0 },
|
||||
cameraFacing: .back,
|
||||
flipCamera: { flipCount += 1 },
|
||||
toggle: { _ in })
|
||||
|
||||
control.selectInputDevice?(nil)
|
||||
control.flipCamera?()
|
||||
|
||||
#expect(control.level == 0.6)
|
||||
#expect(control.partialTranscript == "hello")
|
||||
@@ -47,6 +53,8 @@ struct ChatTalkControlTests {
|
||||
#expect(control.inputDevices == devices)
|
||||
#expect(control.selectedInputDeviceID == "mic-1")
|
||||
#expect(selectedID == nil)
|
||||
#expect(control.cameraFacing == .back)
|
||||
#expect(flipCount == 1)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user