mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-12 21:53:00 -06:00
fix(ios): preserve localized app display names
This commit is contained in:
@@ -15073,14 +15073,6 @@
|
||||
"surface": "android",
|
||||
"id": "native.android.709aff840be1f167"
|
||||
},
|
||||
{
|
||||
"kind": "plist-string",
|
||||
"line": 8,
|
||||
"path": "apps/ios/ActivityWidget/Info.plist",
|
||||
"source": "OpenClaw Activity",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.8f741d09cc1d5495"
|
||||
},
|
||||
{
|
||||
"kind": "ui-call",
|
||||
"line": 18,
|
||||
@@ -15201,14 +15193,6 @@
|
||||
"surface": "apple",
|
||||
"id": "native.apple.18d4f8a4eea7f930"
|
||||
},
|
||||
{
|
||||
"kind": "plist-string",
|
||||
"line": 8,
|
||||
"path": "apps/ios/ShareExtension/Info.plist",
|
||||
"source": "OpenClaw Share",
|
||||
"surface": "apple",
|
||||
"id": "native.apple.9168fcd110c3019a"
|
||||
},
|
||||
{
|
||||
"kind": "conditional-branch",
|
||||
"line": 236,
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Activity";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
"CFBundleDisplayName" = "OpenClaw Share";
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>$(OPENCLAW_APP_DISPLAY_NAME)</string>
|
||||
<string>OpenClaw</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIconName</key>
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "يستخدم OpenClaw تقويماتك لعرض الأحداث وسياق الجدولة عند تفعيل الوصول إلى التقويم.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw verwendet Ihre Kalender, um Ereignisse und Planungskontext anzuzeigen, wenn Sie den Kalenderzugriff aktivieren.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw usa tus calendarios para mostrar eventos y contexto de programación cuando activas el acceso al calendario.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw از تقویمهای شما استفاده میکند تا وقتی دسترسی به تقویم را فعال میکنید، رویدادها و زمینهٔ زمانبندی را نشان دهد.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw utilise vos calendriers pour afficher les événements et le contexte de planification lorsque vous activez l’accès au calendrier.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "जब आप कैलेंडर एक्सेस सक्षम करते हैं, तो OpenClaw इवेंट और शेड्यूलिंग संदर्भ दिखाने के लिए आपके कैलेंडर का उपयोग करता है.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw menggunakan kalender Anda untuk menampilkan acara dan konteks penjadwalan saat Anda mengaktifkan akses kalender.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw usa i tuoi calendari per mostrare eventi e contesto di pianificazione quando abiliti l'accesso al calendario.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClawは、カレンダーへのアクセスを有効にしたときに、イベントとスケジュールのコンテキストを表示するためにカレンダーを使用します。";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "캘린더 접근을 활성화하면 OpenClaw가 캘린더를 사용하여 이벤트와 일정 컨텍스트를 표시합니다.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw gebruikt je agenda’s om gebeurtenissen en planningscontext te tonen wanneer je agendatoegang inschakelt.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw używa Twoich kalendarzy do wyświetlania wydarzeń i kontekstu planowania, gdy włączysz dostęp do kalendarza.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "O OpenClaw usa seus calendários para mostrar eventos e contexto de agendamento quando você ativa o acesso ao calendário.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw использует ваши календари, чтобы показывать события и контекст расписания, когда вы включаете доступ к календарю.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw använder dina kalendrar för att visa händelser och schemaläggningssammanhang när du aktiverar kalenderåtkomst.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw ใช้ปฏิทินของคุณเพื่อแสดงกิจกรรมและบริบทการจัดกำหนดการเมื่อคุณเปิดใช้งานการเข้าถึงปฏิทิน";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw, takvim erişimini etkinleştirdiğinizde etkinlikleri ve planlama bağlamını göstermek için takvimlerinizi kullanır.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw використовує ваші календарі, щоб показувати події та контекст планування, коли ви надаєте доступ до календаря.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw sử dụng lịch của bạn để hiển thị sự kiện và ngữ cảnh lên lịch khi bạn bật quyền truy cập lịch.";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "当你启用日历访问权限时,OpenClaw 会使用你的日历来显示事件和日程安排上下文。";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
"CFBundleDisplayName" = "$(OPENCLAW_APP_DISPLAY_NAME)";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
"NSCalendarsFullAccessUsageDescription" = "OpenClaw 會在你啟用行事曆存取權限時,使用你的行事曆來顯示事件與排程情境。";
|
||||
/* OpenClaw source: "OpenClaw uses your calendars to show events and scheduling context when you enable calendar access." */
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "يربط OpenClaw ساعة Apple Watch هذه مباشرةً بـ Gateway الخاص بك على الشبكات المحلية الموثوقة.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw verbindet diese Apple Watch in vertrauenswürdigen lokalen Netzwerken direkt mit Ihrem Gateway.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw conecta este Apple Watch directamente a tu Gateway en redes locales de confianza.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw این Apple Watch را در شبکههای محلی مورد اعتماد مستقیماً به Gateway شما متصل میکند.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw connecte cette Apple Watch directement à votre Gateway sur les réseaux locaux de confiance.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw इस Apple Watch को विश्वसनीय लोकल नेटवर्क पर सीधे आपके Gateway से कनेक्ट करता है।";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw menyambungkan Apple Watch ini langsung ke Gateway Anda di jaringan lokal tepercaya.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw connette questo Apple Watch direttamente al tuo Gateway su reti locali attendibili.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw は信頼できるローカルネットワーク上で、この Apple Watch を Gateway に直接接続します。";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw는 신뢰할 수 있는 로컬 네트워크에서 이 Apple Watch를 Gateway에 직접 연결합니다.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw verbindt deze Apple Watch rechtstreeks met je Gateway op vertrouwde lokale netwerken.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw łączy ten Apple Watch bezpośrednio z Twoim Gateway w zaufanych sieciach lokalnych.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "O OpenClaw conecta este Apple Watch diretamente ao seu Gateway em redes locais confiáveis.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw подключает эти Apple Watch напрямую к вашему Gateway в доверенных локальных сетях.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw ansluter denna Apple Watch direkt till din Gateway på betrodda lokala nätverk.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw เชื่อมต่อ Apple Watch นี้เข้ากับ Gateway ของคุณโดยตรงบนเครือข่ายในพื้นที่ที่เชื่อถือได้";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw, bu Apple Watch'u güvenilir yerel ağlarda doğrudan Gateway'inize bağlar.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw підключає цей Apple Watch безпосередньо до вашого Gateway в довірених локальних мережах.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw kết nối Apple Watch này trực tiếp với Gateway của bạn trên các mạng cục bộ đáng tin cậy.";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "在受信任的本地网络上,OpenClaw 将此 Apple Watch 直接连接到您的 Gateway。";
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
"CFBundleDisplayName" = "OpenClaw";
|
||||
/* OpenClaw source: "OpenClaw connects this Apple Watch directly to your Gateway on trusted local networks." */
|
||||
"NSLocalNetworkUsageDescription" = "OpenClaw 會在受信任的本機網路上將此 Apple Watch 直接連線到您的 Gateway。";
|
||||
|
||||
@@ -114,7 +114,6 @@ targets:
|
||||
CODE_SIGN_STYLE: "$(OPENCLAW_CODE_SIGN_STYLE)"
|
||||
DEVELOPMENT_TEAM: "$(OPENCLAW_DEVELOPMENT_TEAM)"
|
||||
OPENCLAW_ACTIVE_APP_GROUP_ID: "$(OPENCLAW_APP_GROUP_ID)"
|
||||
OPENCLAW_APP_DISPLAY_NAME: OpenClaw
|
||||
OPENCLAW_URL_SCHEME: openclaw
|
||||
PRODUCT_BUNDLE_IDENTIFIER: "$(OPENCLAW_APP_BUNDLE_ID)"
|
||||
PROVISIONING_PROFILE_SPECIFIER: "$(OPENCLAW_APP_PROFILE)"
|
||||
@@ -129,7 +128,6 @@ targets:
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME: AppIconDebug
|
||||
CODE_SIGN_STYLE: Automatic
|
||||
OPENCLAW_ACTIVE_APP_GROUP_ID: "$(OPENCLAW_DEBUG_APP_GROUP_ID)"
|
||||
OPENCLAW_APP_DISPLAY_NAME: OpenClaw
|
||||
OPENCLAW_CODE_SIGN_ENTITLEMENTS: Sources/OpenClaw.entitlements
|
||||
OPENCLAW_APNS_ENTITLEMENT_ENVIRONMENT: development
|
||||
OPENCLAW_URL_SCHEME: openclaw-debug
|
||||
@@ -145,7 +143,7 @@ targets:
|
||||
info:
|
||||
path: Sources/Info.plist
|
||||
properties:
|
||||
CFBundleDisplayName: "$(OPENCLAW_APP_DISPLAY_NAME)"
|
||||
CFBundleDisplayName: OpenClaw
|
||||
CFBundleIconName: "$(ASSETCATALOG_COMPILER_APPICON_NAME)"
|
||||
CFBundleURLTypes:
|
||||
- CFBundleURLName: ai.openclawfoundation.app
|
||||
|
||||
@@ -481,9 +481,7 @@ function parseInfoPlistStrings(source: string): Array<{ key: string; source: str
|
||||
key: decodeXml(match[1] ?? ""),
|
||||
source: decodeXml(match[2] ?? ""),
|
||||
}))
|
||||
.filter(
|
||||
(entry) => entry.key === "CFBundleDisplayName" || entry.key.endsWith("UsageDescription"),
|
||||
);
|
||||
.filter((entry) => entry.key.endsWith("UsageDescription"));
|
||||
}
|
||||
|
||||
type InfoPlistTranslation = {
|
||||
@@ -855,9 +853,6 @@ async function syncIosInfoPlist(write: boolean): Promise<number> {
|
||||
const existing = parseStringsFile(existingSource ?? "");
|
||||
const artifact = translations.find((candidate) => candidate.locale === locale);
|
||||
const lines = sourceEntries.map(({ key, source }) => {
|
||||
if (key === "CFBundleDisplayName") {
|
||||
return `${stringsLiteral(key)} = ${stringsLiteral(source)};`;
|
||||
}
|
||||
const sourceId = sourceIds.get([target.sourcePath, source].join("\u0000"));
|
||||
if (!sourceId) {
|
||||
throw new Error(`missing native InfoPlist source id for ${target.sourcePath}:${key}`);
|
||||
|
||||
@@ -219,11 +219,28 @@ assert_build_provenance() {
|
||||
fi
|
||||
}
|
||||
|
||||
assert_localized_plists_resolve_build_settings() {
|
||||
local localized_plist
|
||||
local rendered
|
||||
while IFS= read -r -d '' localized_plist; do
|
||||
if ! rendered="$("${PLUTIL_BIN}" -convert xml1 -o - "${localized_plist}" 2>/dev/null)"; then
|
||||
echo "Invalid IPA: could not read localized plist ${localized_plist#"${app_path}/"}." >&2
|
||||
exit 1
|
||||
fi
|
||||
if grep -Eq '\$\([A-Za-z0-9_.-]+\)|\$\{[A-Za-z0-9_.-]+\}' <<<"${rendered}"; then
|
||||
echo "Invalid IPA: unresolved build setting in localized plist ${localized_plist#"${app_path}/"}." >&2
|
||||
exit 1
|
||||
fi
|
||||
done < <(find "${app_path}" -type f -path "*.lproj/InfoPlist.strings" -print0)
|
||||
}
|
||||
|
||||
assert_plist_string "${info_plist}" "CFBundleIdentifier" "${EXPECTED_BUNDLE_ID}" "bundle identifier mismatch"
|
||||
assert_plist_string "${info_plist}" "CFBundleDisplayName" "OpenClaw" "display name mismatch"
|
||||
assert_plist_string "${info_plist}" "OpenClawPushMode" "${EXPECTED_PUSH_MODE}" "push mode mismatch"
|
||||
assert_plist_nonempty_string "${info_plist}" "NSHealthShareUsageDescription" "Health share usage description"
|
||||
assert_plist_nonempty_string "${info_plist}" "NSHealthUpdateUsageDescription" "Health update usage description"
|
||||
assert_build_provenance
|
||||
assert_localized_plists_resolve_build_settings
|
||||
assert_plist_empty_or_absent "${info_plist}" "OpenClawPushRelayBaseURL" "push relay URL override"
|
||||
assert_plist_key_absent "${info_plist}" "OpenClawPushTransport" "legacy push transport"
|
||||
assert_plist_key_absent "${info_plist}" "OpenClawPushDistribution" "legacy push distribution"
|
||||
|
||||
@@ -166,7 +166,9 @@ const APPLE_BUILTIN_UI_CALLS = new Set([
|
||||
"Toggle",
|
||||
"searchable",
|
||||
]);
|
||||
const APPLE_PLIST_STRINGS = /<string>([\s\S]*?)<\/string>/gu;
|
||||
const APPLE_PLIST_KEYED_STRINGS = /<key>([^<]+)<\/key>\s*<string>([\s\S]*?)<\/string>/gu;
|
||||
// macOS uses this legacy privacy key instead of the *UsageDescription suffix.
|
||||
const APPLE_LOCALIZABLE_DESCRIPTION_KEYS = new Set(["NSScreenCaptureDescription"]);
|
||||
const GENERATED_PATH_RE = /(?:^|[\\/])(?:build|\.gradle|\.build|DerivedData)(?:$|[\\/])/u;
|
||||
const EXCLUDED_PATH_RE = /(?:^|[\\/])(?:Tests?|UITests?|test|Preview(?:s)?)(?:$|[\\/])/u;
|
||||
const EXCLUDED_FILE_RE = /(?:Tests?|UITests?|Previews?|Testing)\.(?:swift|kt|kts)$/u;
|
||||
@@ -196,6 +198,19 @@ function isAsciiAlphaNumeric(character: string): boolean {
|
||||
);
|
||||
}
|
||||
|
||||
function decodeXml(value: string): string {
|
||||
return value
|
||||
.replaceAll(""", '"')
|
||||
.replaceAll("'", "'")
|
||||
.replaceAll("<", "<")
|
||||
.replaceAll(">", ">")
|
||||
.replaceAll("&", "&");
|
||||
}
|
||||
|
||||
function isLocalizableApplePlistKey(key: string): boolean {
|
||||
return key.endsWith("UsageDescription") || APPLE_LOCALIZABLE_DESCRIPTION_KEYS.has(key);
|
||||
}
|
||||
|
||||
export function isConditionalBranchIdentifier(source: string): boolean {
|
||||
let index = 0;
|
||||
while (index < source.length && isAsciiLowercaseLetter(source.charAt(index))) {
|
||||
@@ -1058,15 +1073,18 @@ export function extractNativeI18nCandidates(
|
||||
}
|
||||
}
|
||||
if (surface === "apple" && repoPath.endsWith(".plist")) {
|
||||
for (const match of source.matchAll(APPLE_PLIST_STRINGS)) {
|
||||
if (match[1]) {
|
||||
for (const match of source.matchAll(APPLE_PLIST_KEYED_STRINGS)) {
|
||||
const key = match[1];
|
||||
const value = match[2];
|
||||
if (key && isLocalizableApplePlistKey(key) && value) {
|
||||
const valueOffset = (match.index ?? 0) + match[0].indexOf(value);
|
||||
addCandidate(
|
||||
entries,
|
||||
surface,
|
||||
repoPath,
|
||||
match[1],
|
||||
decodeXml(value),
|
||||
"plist-string",
|
||||
lineNumber(source, match.index ?? 0),
|
||||
lineNumber(source, valueOffset),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
||||
import { mkdtemp, readFile, readdir, rm } from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { describe, expect, it } from "vitest";
|
||||
@@ -464,7 +464,7 @@ describe("Apple app i18n catalogs", () => {
|
||||
]);
|
||||
});
|
||||
|
||||
it("generates InfoPlist localizations for every shipped iOS target", async () => {
|
||||
it("generates only localized usage descriptions for every shipped iOS target", async () => {
|
||||
const french = await readFile("apps/ios/Sources/fr.lproj/InfoPlist.strings", "utf8");
|
||||
const watchChinese = await readFile(
|
||||
"apps/ios/WatchApp/zh-Hans.lproj/InfoPlist.strings",
|
||||
@@ -483,8 +483,28 @@ describe("Apple app i18n catalogs", () => {
|
||||
expect(french).toContain('"NSMicrophoneUsageDescription" = ');
|
||||
expect(french).toContain('"NSHealthUpdateUsageDescription" = ');
|
||||
expect(watchChinese).toContain('"NSLocalNetworkUsageDescription" = ');
|
||||
expect(shareGerman).toContain('"CFBundleDisplayName" = "OpenClaw Share";');
|
||||
expect(activityJapanese).toContain('"CFBundleDisplayName" = "OpenClaw Activity";');
|
||||
expect(shareGerman.trim()).toBe("");
|
||||
expect(activityJapanese.trim()).toBe("");
|
||||
|
||||
for (const root of [
|
||||
"apps/ios/Sources",
|
||||
"apps/ios/WatchApp",
|
||||
"apps/ios/ShareExtension",
|
||||
"apps/ios/ActivityWidget",
|
||||
]) {
|
||||
const localeDirs = (await readdir(root, { withFileTypes: true })).filter(
|
||||
(entry) => entry.isDirectory() && entry.name.endsWith(".lproj"),
|
||||
);
|
||||
expect(localeDirs).toHaveLength(APPLE_I18N_LOCALES.length);
|
||||
for (const localeDir of localeDirs) {
|
||||
const localizedPlist = await readFile(
|
||||
path.join(root, localeDir.name, "InfoPlist.strings"),
|
||||
"utf8",
|
||||
);
|
||||
expect(localizedPlist).not.toContain("CFBundleDisplayName");
|
||||
expect(localizedPlist).not.toMatch(/\$\([^)]*\)|\$\{[^}]*\}/u);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
it("refreshes InfoPlist copy from translations for the current source", () => {
|
||||
|
||||
@@ -128,6 +128,10 @@ function writeFakePlutil(filePath: string): void {
|
||||
filePath,
|
||||
`#!/usr/bin/env node
|
||||
const { readFileSync } = require("node:fs");
|
||||
if (process.argv[2] === "-convert" && process.argv[3] === "xml1") {
|
||||
process.stdout.write(readFileSync(process.argv[process.argv.length - 1], "utf8"));
|
||||
process.exit(0);
|
||||
}
|
||||
const extractIndex = process.argv.indexOf("-extract");
|
||||
const expectIndex = process.argv.indexOf("-expect");
|
||||
if (extractIndex < 0 || expectIndex < 0 || process.argv[expectIndex + 1] !== "string") process.exit(2);
|
||||
@@ -209,6 +213,8 @@ async function writeValidFixture(
|
||||
buildCommit?: string;
|
||||
buildTimestamp?: string;
|
||||
healthUpdateUsage?: boolean | string | null;
|
||||
displayName?: string;
|
||||
localizedDisplayName?: string;
|
||||
pushMode?: string;
|
||||
legacyKey?: boolean;
|
||||
} = {},
|
||||
@@ -230,6 +236,7 @@ async function writeValidFixture(
|
||||
|
||||
const infoBody = [
|
||||
plistString("CFBundleIdentifier", "ai.openclawfoundation.app"),
|
||||
plistString("CFBundleDisplayName", options.displayName ?? "OpenClaw"),
|
||||
plistString("OpenClawGitCommit", options.buildCommit ?? BUILD_COMMIT),
|
||||
plistString("OpenClawBuildTimestamp", options.buildTimestamp ?? BUILD_TIMESTAMP),
|
||||
plistString("OpenClawPushMode", options.pushMode ?? "appStore"),
|
||||
@@ -249,6 +256,17 @@ async function writeValidFixture(
|
||||
options.legacyKey ? plistString("OpenClawPushRelayProfile", "production") : "",
|
||||
].join("");
|
||||
writeFileSync(path.join(appDir, "Info.plist"), plist(infoBody), "utf8");
|
||||
const localizedDir = path.join(appDir, "de.lproj");
|
||||
mkdirSync(localizedDir, { recursive: true });
|
||||
writeFileSync(
|
||||
path.join(localizedDir, "InfoPlist.strings"),
|
||||
plist(
|
||||
options.localizedDisplayName === undefined
|
||||
? plistString("NSCameraUsageDescription", "OpenClaw verwendet die Kamera.")
|
||||
: plistString("CFBundleDisplayName", options.localizedDisplayName),
|
||||
),
|
||||
"utf8",
|
||||
);
|
||||
writeFileSync(path.join(appDir, "embedded.mobileprovision"), "fixture profile", "utf8");
|
||||
|
||||
const entitlementsPath = path.join(fixturesDir, "entitlements.plist");
|
||||
@@ -406,6 +424,30 @@ describe("scripts/ios-validate-app-store-ipa.sh", () => {
|
||||
expect(result.stderr).toContain("Health update usage description must be a non-empty string");
|
||||
});
|
||||
|
||||
it("rejects an IPA with the wrong canonical display name", async () => {
|
||||
const root = mkdtempSync(path.join(os.tmpdir(), "openclaw-ios-ipa-"));
|
||||
tempDirs.push(root);
|
||||
const fixture = await writeValidFixture(root, { displayName: "OpenClaw Debug" });
|
||||
|
||||
const result = runValidator(fixture);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.stderr).toContain("display name mismatch");
|
||||
});
|
||||
|
||||
it("rejects unresolved build settings in localized plist resources", async () => {
|
||||
const root = mkdtempSync(path.join(os.tmpdir(), "openclaw-ios-ipa-"));
|
||||
tempDirs.push(root);
|
||||
const fixture = await writeValidFixture(root, {
|
||||
localizedDisplayName: "$(OPENCLAW_APP_DISPLAY_NAME)",
|
||||
});
|
||||
|
||||
const result = runValidator(fixture);
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.stderr).toContain("unresolved build setting in localized plist");
|
||||
});
|
||||
|
||||
it("rejects a non-string Health update purpose value", async () => {
|
||||
const root = mkdtempSync(path.join(os.tmpdir(), "openclaw-ios-ipa-"));
|
||||
tempDirs.push(root);
|
||||
|
||||
@@ -275,6 +275,25 @@ describe("native app i18n inventory", () => {
|
||||
expect(entries.map((entry) => entry.source)).toEqual(["Gateway ready"]);
|
||||
});
|
||||
|
||||
it("extracts only localizable usage descriptions from Apple plists", () => {
|
||||
const entries = extractNativeI18nCandidates(
|
||||
"apple",
|
||||
"apps/ios/Fixture/Info.plist",
|
||||
`<plist><dict>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>OpenClaw Fixture</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>OpenClaw uses the camera to scan setup codes & documents.</string>
|
||||
<key>OpenClawFixtureValue</key>
|
||||
<string>Runtime configuration value</string>
|
||||
</dict></plist>`,
|
||||
);
|
||||
|
||||
expect(entries.map((entry) => entry.source)).toEqual([
|
||||
"OpenClaw uses the camera to scan setup codes & documents.",
|
||||
]);
|
||||
});
|
||||
|
||||
it("respects non-translatable Android collections and retains lowercase choices", () => {
|
||||
const entries = extractNativeI18nCandidates(
|
||||
"android",
|
||||
|
||||
Reference in New Issue
Block a user