ソースを参照

Localize paywall, PDF export, and purchase error alerts.

Route StoreKit and file failures through UserFacingErrorMessage so alert bodies use the app language instead of system descriptions, and drop developer-only subscription recovery text from customer-facing UI.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 2 日 前
コミット
803cfa2142

+ 7 - 15
App for Indeed/Controllers/PremiumPlansWindowController.swift

@@ -1243,7 +1243,7 @@ private final class PremiumPlansViewController: NSViewController {
1243 1243
             }
1244 1244
         } catch {
1245 1245
             await MainActor.run {
1246
-                self.presentPurchaseError(error)
1246
+                self.presentPurchaseError(error, context: .purchase)
1247 1247
             }
1248 1248
         }
1249 1249
     }
@@ -1278,26 +1278,18 @@ private final class PremiumPlansViewController: NSViewController {
1278 1278
             }
1279 1279
         } catch {
1280 1280
             await MainActor.run {
1281
-                self.presentPurchaseError(error)
1281
+                self.presentPurchaseError(error, context: .restore)
1282 1282
             }
1283 1283
         }
1284 1284
     }
1285 1285
 
1286
-    private func presentPurchaseError(_ error: Error) {
1286
+    private func presentPurchaseError(
1287
+        _ error: Error,
1288
+        context: UserFacingErrorMessage.PurchaseContext
1289
+    ) {
1287 1290
         let alert = NSAlert()
1288 1291
         alert.messageText = L("Something went wrong")
1289
-        if let localized = error as? LocalizedError {
1290
-            var parts: [String] = []
1291
-            if let description = localized.errorDescription {
1292
-                parts.append(description)
1293
-            }
1294
-            if let recovery = localized.recoverySuggestion {
1295
-                parts.append(recovery)
1296
-            }
1297
-            alert.informativeText = parts.isEmpty ? error.localizedDescription : parts.joined(separator: "\n\n")
1298
-        } else {
1299
-            alert.informativeText = error.localizedDescription
1300
-        }
1292
+        alert.informativeText = UserFacingErrorMessage.purchaseFailure(error, context: context)
1301 1293
         alert.alertStyle = .warning
1302 1294
         alert.addButton(withTitle: L("OK"))
1303 1295
         if let window = view.window {

+ 144 - 11
App for Indeed/Services/UserFacingErrorMessage.swift

@@ -1,23 +1,156 @@
1 1
 import Foundation
2
+import StoreKit
2 3
 
3
-/// Maps backend and network errors to short, safe copy for the UI.
4
+/// Maps backend, StoreKit, and file errors to short, safe copy for the UI (always via `L()`).
4 5
 enum UserFacingErrorMessage {
6
+    enum PurchaseContext {
7
+        case purchase
8
+        case restore
9
+    }
10
+
5 11
     static func jobSearchFailure(_ error: Error) -> String {
12
+        let ns = error as NSError
13
+        if ns.domain == "OpenAIJobSearchService", ns.code == 1 {
14
+            return L("Job search is unavailable.")
15
+        }
16
+        if let urlError = error as? URLError, urlError.code == .cancelled {
17
+            return L("The search was cancelled. Try again when you're ready.")
18
+        }
19
+        if let message = connectivityFailure(for: error) {
20
+            return message
21
+        }
22
+        return L("Something went wrong while searching. Please try again in a moment.")
23
+    }
24
+
25
+    static func purchaseFailure(_ error: Error, context: PurchaseContext = .purchase) -> String {
26
+        if let subscription = error as? SubscriptionStoreError {
27
+            return subscription.userFacingMessage
28
+        }
29
+        if let storeKit = error as? StoreKitError {
30
+            return message(for: storeKit, context: context)
31
+        }
32
+        if let purchase = error as? Product.PurchaseError {
33
+            return message(for: purchase)
34
+        }
35
+        if let message = connectivityFailure(for: error) {
36
+            return message
37
+        }
38
+        switch context {
39
+        case .purchase:
40
+            return L("We couldn't complete your purchase. Please try again.")
41
+        case .restore:
42
+            return L("We couldn't restore your purchases. Please try again.")
43
+        }
44
+    }
45
+
46
+    static func pdfSaveFailure(_ error: Error) -> String {
47
+        if let cocoa = error as? CocoaError {
48
+            switch cocoa.code {
49
+            case .fileWriteNoPermission:
50
+                return L("We don't have permission to save to that folder. Choose another location or grant access.")
51
+            case .fileWriteVolumeReadOnly:
52
+                return L("This disk is read-only. Choose another folder to save your PDF.")
53
+            case .fileWriteOutOfSpace:
54
+                return L("The disk is full. Free up space, then try again.")
55
+            default:
56
+                break
57
+            }
58
+        }
6 59
         if let urlError = error as? URLError {
7 60
             switch urlError.code {
8
-            case .notConnectedToInternet,
9
-                 .networkConnectionLost,
10
-                 .timedOut,
11
-                 .cannotFindHost,
12
-                 .cannotConnectToHost,
13
-                 .dnsLookupFailed:
14
-                return L("We couldn't reach the server. Check your internet connection and try again.")
15
-            case .cancelled:
16
-                return L("The search was cancelled. Try again when you're ready.")
61
+            case .fileDoesNotExist, .noPermissionsToReadFile:
62
+                return L("We don't have permission to save to that folder. Choose another location or grant access.")
17 63
             default:
18 64
                 break
19 65
             }
20 66
         }
21
-        return L("Something went wrong while searching. Please try again in a moment.")
67
+        let ns = error as NSError
68
+        if ns.domain == NSCocoaErrorDomain,
69
+           ns.code == NSFileWriteOutOfSpaceError || ns.code == NSFileWriteVolumeReadOnlyError {
70
+            if ns.code == NSFileWriteOutOfSpaceError {
71
+                return L("The disk is full. Free up space, then try again.")
72
+            }
73
+            return L("This disk is read-only. Choose another folder to save your PDF.")
74
+        }
75
+        if let message = connectivityFailure(for: error) {
76
+            return message
77
+        }
78
+        return L("We couldn't save the PDF. Try again or choose a different folder.")
79
+    }
80
+
81
+    private static func connectivityFailure(for error: Error) -> String? {
82
+        if let storeKit = error as? StoreKitError,
83
+           case .networkError(let urlError) = storeKit {
84
+            return connectivityFailure(for: urlError)
85
+        }
86
+        if let urlError = error as? URLError {
87
+            return connectivityFailure(for: urlError)
88
+        }
89
+        return nil
90
+    }
91
+
92
+    private static func connectivityFailure(for urlError: URLError) -> String? {
93
+        switch urlError.code {
94
+        case .notConnectedToInternet,
95
+             .networkConnectionLost,
96
+             .timedOut,
97
+             .cannotFindHost,
98
+             .cannotConnectToHost,
99
+             .dnsLookupFailed:
100
+            return L("We couldn't reach the server. Check your internet connection and try again.")
101
+        case .cancelled:
102
+            return L("The request was cancelled. Try again when you're ready.")
103
+        default:
104
+            return nil
105
+        }
106
+    }
107
+
108
+    private static func message(for error: StoreKitError, context: PurchaseContext) -> String {
109
+        switch error {
110
+        case .userCancelled:
111
+            return L("Purchase was cancelled.")
112
+        case .networkError(let urlError):
113
+            return connectivityFailure(for: urlError)
114
+                ?? (context == .restore
115
+                    ? L("We couldn't restore your purchases. Please try again.")
116
+                    : L("We couldn't complete your purchase. Please try again."))
117
+        case .notAvailableInStorefront:
118
+            return L("This subscription isn't available in your App Store region.")
119
+        case .notEntitled:
120
+            return L("The purchase couldn't be verified. Please try again.")
121
+        case .unsupported, .unknown, .systemError:
122
+            return context == .restore
123
+                ? L("We couldn't restore your purchases. Please try again.")
124
+                : L("We couldn't complete your purchase. Please try again.")
125
+        @unknown default:
126
+            return context == .restore
127
+                ? L("We couldn't restore your purchases. Please try again.")
128
+                : L("We couldn't complete your purchase. Please try again.")
129
+        }
130
+    }
131
+
132
+    private static func message(for error: Product.PurchaseError) -> String {
133
+        switch error {
134
+        case .productUnavailable:
135
+            return L("That subscription isn’t available from the App Store right now.")
136
+        case .purchaseNotAllowed:
137
+            return L("Purchases aren't allowed on this account or device.")
138
+        case .ineligibleForOffer:
139
+            return L("This introductory offer isn't available for your account.")
140
+        case .invalidQuantity, .invalidOfferIdentifier, .invalidOfferPrice,
141
+             .invalidOfferSignature, .missingOfferParameters:
142
+            return L("We couldn't complete your purchase. Please try again.")
143
+        @unknown default:
144
+            return L("We couldn't complete your purchase. Please try again.")
145
+        }
146
+    }
147
+}
148
+
149
+private extension SubscriptionStoreError {
150
+    var userFacingMessage: String {
151
+        switch self {
152
+        case .productUnavailable:
153
+            return L("That subscription isn’t available from the App Store right now.")
154
+        }
22 155
     }
23 156
 }

+ 2 - 10
App for Indeed/Subscription/SubscriptionStore.swift

@@ -161,14 +161,6 @@ enum SubscriptionStoreError: LocalizedError {
161 161
         }
162 162
     }
163 163
 
164
-    var recoverySuggestion: String? {
165
-        switch self {
166
-        case .productUnavailable:
167
-            return """
168
-            For local testing in Xcode: Product → Scheme → Edit Scheme → Run → Options → StoreKit Configuration → choose Paywall.storekit.
169
-
170
-            For TestFlight / App Store: In App Store Connect, create auto-renewable subscriptions whose Product IDs exactly match SubscriptionProductIDs.swift (same spelling as com.hwaccount.appforindeed.pro.*), then submit them with the app version.
171
-            """
172
-        }
173
-    }
164
+    /// Developer setup notes belong in docs or console logs—not in customer-facing alerts.
165
+    var recoverySuggestion: String? { nil }
174 166
 }

+ 1 - 1
App for Indeed/Views/CVFilledPreviewPageView.swift

@@ -316,7 +316,7 @@ final class CVFilledPreviewPageView: NSView {
316 316
         do {
317 317
             try data.write(to: url, options: .atomic)
318 318
         } catch {
319
-            presentExportError(error.localizedDescription)
319
+            presentExportError(UserFacingErrorMessage.pdfSaveFailure(error))
320 320
         }
321 321
     }
322 322
 

+ 12 - 0
App for Indeed/ar.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - الأخطاء
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "لم نتمكن من الوصول إلى الخادم. تحقق من اتصالك بالإنترنت وحاول مرة أخرى.";
349 349
 "The search was cancelled. Try again when you're ready." = "تم إلغاء البحث. حاول مرة أخرى عندما تكون مستعداً.";
350
+"The request was cancelled. Try again when you're ready." = "تم إلغاء الطلب. حاول مرة أخرى عندما تكون مستعداً.";
350 351
 "Something went wrong while searching. Please try again in a moment." = "حدث خطأ ما أثناء البحث. يرجى المحاولة مرة أخرى بعد قليل.";
351 352
 "Job search is unavailable." = "البحث عن الوظائف غير متوفر.";
353
+"We couldn't complete your purchase. Please try again." = "تعذر إكمال عملية الشراء. يرجى المحاولة مرة أخرى.";
354
+"We couldn't restore your purchases. Please try again." = "تعذر استعادة مشترياتك. يرجى المحاولة مرة أخرى.";
355
+"Purchase was cancelled." = "تم إلغاء الشراء.";
356
+"This subscription isn't available in your App Store region." = "هذا الاشتراك غير متوفر في منطقة متجر التطبيقات الخاصة بك.";
357
+"Purchases aren't allowed on this account or device." = "الشراء غير مسموح به على هذا الحساب أو الجهاز.";
358
+"This introductory offer isn't available for your account." = "عرض الترحيب هذا غير متاح لحسابك.";
359
+"The purchase couldn't be verified. Please try again." = "تعذر التحقق من الشراء. يرجى المحاولة مرة أخرى.";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "تعذر حفظ ملف بي دي إف. حاول مرة أخرى أو اختر مجلداً مختلفاً.";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "ليس لدينا إذن للحفظ في ذلك المجلد. اختر موقعاً آخر أو امنح الوصول.";
362
+"This disk is read-only. Choose another folder to save your PDF." = "هذا القرص للقراءة فقط. اختر مجلداً آخر لحفظ ملف بي دي إف.";
363
+"The disk is full. Free up space, then try again." = "القرص ممتلئ. حرر مساحة ثم حاول مرة أخرى.";
352 364
 
353 365
 // MARK: - التنبيهات
354 366
 "This profile will be removed from this Mac." = "سيتم إزالة هذا الملف الشخصي من جهاز ماك هذا.";

+ 12 - 0
App for Indeed/de.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - Fehler
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "Wir konnten den Server nicht erreichen. Überprüfen Sie Ihre Internetverbindung und versuchen Sie es erneut.";
349 349
 "The search was cancelled. Try again when you're ready." = "Die Suche wurde abgebrochen. Versuchen Sie es erneut, wenn Sie bereit sind.";
350
+"The request was cancelled. Try again when you're ready." = "Die Anfrage wurde abgebrochen. Versuchen Sie es erneut, wenn Sie bereit sind.";
350 351
 "Something went wrong while searching. Please try again in a moment." = "Bei der Suche ist etwas schiefgelaufen. Bitte versuchen Sie es in einem Moment erneut.";
351 352
 "Job search is unavailable." = "Jobsuche ist nicht verfügbar.";
353
+"We couldn't complete your purchase. Please try again." = "Ihr Kauf konnte nicht abgeschlossen werden. Bitte versuchen Sie es erneut.";
354
+"We couldn't restore your purchases. Please try again." = "Ihre Käufe konnten nicht wiederhergestellt werden. Bitte versuchen Sie es erneut.";
355
+"Purchase was cancelled." = "Kauf abgebrochen.";
356
+"This subscription isn't available in your App Store region." = "Dieses Abonnement ist in Ihrer App-Store-Region nicht verfügbar.";
357
+"Purchases aren't allowed on this account or device." = "Käufe sind für dieses Konto oder Gerät nicht erlaubt.";
358
+"This introductory offer isn't available for your account." = "Dieses Einführungsangebot ist für Ihr Konto nicht verfügbar.";
359
+"The purchase couldn't be verified. Please try again." = "Der Kauf konnte nicht verifiziert werden. Bitte versuchen Sie es erneut.";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "PDF konnte nicht gespeichert werden. Versuchen Sie es erneut oder wählen Sie einen anderen Ordner.";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "Keine Berechtigung zum Speichern in diesem Ordner. Wählen Sie einen anderen Speicherort oder gewähren Sie Zugriff.";
362
+"This disk is read-only. Choose another folder to save your PDF." = "Dieses Laufwerk ist schreibgeschützt. Wählen Sie einen anderen Ordner für Ihr PDF.";
363
+"The disk is full. Free up space, then try again." = "Der Speicher ist voll. Schaffen Sie Speicherplatz und versuchen Sie es erneut.";
352 364
 
353 365
 // MARK: - Benachrichtigungen
354 366
 "This profile will be removed from this Mac." = "Dieses Profil wird von diesem Mac entfernt.";

+ 12 - 0
App for Indeed/en.lproj/Localizable.strings

@@ -325,8 +325,20 @@
325 325
 // MARK: - Errors
326 326
 "We couldn't reach the server. Check your internet connection and try again." = "We couldn't reach the server. Check your internet connection and try again.";
327 327
 "The search was cancelled. Try again when you're ready." = "The search was cancelled. Try again when you're ready.";
328
+"The request was cancelled. Try again when you're ready." = "The request was cancelled. Try again when you're ready.";
328 329
 "Something went wrong while searching. Please try again in a moment." = "Something went wrong while searching. Please try again in a moment.";
329 330
 "Job search is unavailable." = "Job search is unavailable.";
331
+"We couldn't complete your purchase. Please try again." = "We couldn't complete your purchase. Please try again.";
332
+"We couldn't restore your purchases. Please try again." = "We couldn't restore your purchases. Please try again.";
333
+"Purchase was cancelled." = "Purchase was cancelled.";
334
+"This subscription isn't available in your App Store region." = "This subscription isn't available in your App Store region.";
335
+"Purchases aren't allowed on this account or device." = "Purchases aren't allowed on this account or device.";
336
+"This introductory offer isn't available for your account." = "This introductory offer isn't available for your account.";
337
+"The purchase couldn't be verified. Please try again." = "The purchase couldn't be verified. Please try again.";
338
+"We couldn't save the PDF. Try again or choose a different folder." = "We couldn't save the PDF. Try again or choose a different folder.";
339
+"We don't have permission to save to that folder. Choose another location or grant access." = "We don't have permission to save to that folder. Choose another location or grant access.";
340
+"This disk is read-only. Choose another folder to save your PDF." = "This disk is read-only. Choose another folder to save your PDF.";
341
+"The disk is full. Free up space, then try again." = "The disk is full. Free up space, then try again.";
330 342
 
331 343
 // MARK: - Alerts
332 344
 "This profile will be removed from this Mac." = "This profile will be removed from this Mac.";

+ 12 - 0
App for Indeed/fr-CA.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - Erreurs
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "Nous ne pouvons pas joindre le serveur. Vérifiez votre connexion Internet et réessayez.";
349 349
 "The search was cancelled. Try again when you're ready." = "La recherche a été annulée. Réessayez quand vous êtes prêt.";
350
+"The request was cancelled. Try again when you're ready." = "La requête a été annulée. Réessayez quand vous êtes prêt.";
350 351
 "Something went wrong while searching. Please try again in a moment." = "Une erreur s'est produite lors de la recherche. Veuillez réessayer dans un instant.";
351 352
 "Job search is unavailable." = "La recherche d'emploi n'est pas disponible.";
353
+"We couldn't complete your purchase. Please try again." = "Nous n'avons pas pu finaliser votre achat. Veuillez réessayer.";
354
+"We couldn't restore your purchases. Please try again." = "Nous n'avons pas pu restaurer vos achats. Veuillez réessayer.";
355
+"Purchase was cancelled." = "Achat annulé.";
356
+"This subscription isn't available in your App Store region." = "Cet abonnement n'est pas disponible dans votre région de l'App Store.";
357
+"Purchases aren't allowed on this account or device." = "Les achats ne sont pas autorisés sur ce compte ou cet appareil.";
358
+"This introductory offer isn't available for your account." = "Cette offre d'introduction n'est pas disponible pour votre compte.";
359
+"The purchase couldn't be verified. Please try again." = "L'achat n'a pas pu être vérifié. Veuillez réessayer.";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "Impossible d'enregistrer le PDF. Réessayez ou choisissez un autre dossier.";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "Nous n'avons pas l'autorisation d'enregistrer dans ce dossier. Choisissez un autre emplacement ou accordez l'accès.";
362
+"This disk is read-only. Choose another folder to save your PDF." = "Ce disque est en lecture seule. Choisissez un autre dossier pour enregistrer votre PDF.";
363
+"The disk is full. Free up space, then try again." = "Le disque est plein. Libérez de l'espace, puis réessayez.";
352 364
 
353 365
 // MARK: - Alertes
354 366
 "This profile will be removed from this Mac." = "Ce profil sera supprimé de ce Mac.";

+ 12 - 0
App for Indeed/fr.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - Erreurs
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "Nous ne pouvons pas joindre le serveur. Vérifiez votre connexion Internet et réessayez.";
349 349
 "The search was cancelled. Try again when you're ready." = "La recherche a été annulée. Réessayez quand vous êtes prêt.";
350
+"The request was cancelled. Try again when you're ready." = "La requête a été annulée. Réessayez quand vous êtes prêt.";
350 351
 "Something went wrong while searching. Please try again in a moment." = "Une erreur s'est produite lors de la recherche. Veuillez réessayer dans un instant.";
351 352
 "Job search is unavailable." = "La recherche d'emploi n'est pas disponible.";
353
+"We couldn't complete your purchase. Please try again." = "Nous n'avons pas pu finaliser votre achat. Veuillez réessayer.";
354
+"We couldn't restore your purchases. Please try again." = "Nous n'avons pas pu restaurer vos achats. Veuillez réessayer.";
355
+"Purchase was cancelled." = "Achat annulé.";
356
+"This subscription isn't available in your App Store region." = "Cet abonnement n'est pas disponible dans votre région de l'App Store.";
357
+"Purchases aren't allowed on this account or device." = "Les achats ne sont pas autorisés sur ce compte ou cet appareil.";
358
+"This introductory offer isn't available for your account." = "Cette offre d'introduction n'est pas disponible pour votre compte.";
359
+"The purchase couldn't be verified. Please try again." = "L'achat n'a pas pu être vérifié. Veuillez réessayer.";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "Impossible d'enregistrer le PDF. Réessayez ou choisissez un autre dossier.";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "Nous n'avons pas l'autorisation d'enregistrer dans ce dossier. Choisissez un autre emplacement ou accordez l'accès.";
362
+"This disk is read-only. Choose another folder to save your PDF." = "Ce disque est en lecture seule. Choisissez un autre dossier pour enregistrer votre PDF.";
363
+"The disk is full. Free up space, then try again." = "Le disque est plein. Libérez de l'espace, puis réessayez.";
352 364
 
353 365
 // MARK: - Alertes
354 366
 "This profile will be removed from this Mac." = "Ce profil sera supprimé de ce Mac.";

+ 12 - 0
App for Indeed/sv.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - Fel
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "Vi kunde inte nå servern. Kontrollera din internetanslutning och försök igen.";
349 349
 "The search was cancelled. Try again when you're ready." = "Sökningen avbröts. Försök igen när du är redo.";
350
+"The request was cancelled. Try again when you're ready." = "Begäran avbröts. Försök igen när du är redo.";
350 351
 "Something went wrong while searching. Please try again in a moment." = "Något gick fel under sökningen. Försök igen om en stund.";
351 352
 "Job search is unavailable." = "Jobbsökning är inte tillgänglig.";
353
+"We couldn't complete your purchase. Please try again." = "Vi kunde inte slutföra ditt köp. Försök igen.";
354
+"We couldn't restore your purchases. Please try again." = "Vi kunde inte återställa dina köp. Försök igen.";
355
+"Purchase was cancelled." = "Köpet avbröts.";
356
+"This subscription isn't available in your App Store region." = "Den här prenumerationen är inte tillgänglig i din App Store-region.";
357
+"Purchases aren't allowed on this account or device." = "Köp är inte tillåtna på det här kontot eller enheten.";
358
+"This introductory offer isn't available for your account." = "Det här introduktionserbjudandet är inte tillgängligt för ditt konto.";
359
+"The purchase couldn't be verified. Please try again." = "Köpet kunde inte verifieras. Försök igen.";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "Vi kunde inte spara PDF-filen. Försök igen eller välj en annan mapp.";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "Vi har inte behörighet att spara i den mappen. Välj en annan plats eller bevilja åtkomst.";
362
+"This disk is read-only. Choose another folder to save your PDF." = "Disken är skrivskyddad. Välj en annan mapp för din PDF.";
363
+"The disk is full. Free up space, then try again." = "Disken är full. Frigör utrymme och försök igen.";
352 364
 
353 365
 // MARK: - Aviseringar
354 366
 "This profile will be removed from this Mac." = "Den här profilen kommer att tas bort från den här Mac-datorn.";

+ 12 - 0
App for Indeed/zh-Hans.lproj/Localizable.strings

@@ -348,8 +348,20 @@
348 348
 // MARK: - 错误
349 349
 "We couldn't reach the server. Check your internet connection and try again." = "无法连接服务器。请检查您的网络连接后重试。";
350 350
 "The search was cancelled. Try again when you're ready." = "搜索已取消。准备就绪后请重试。";
351
+"The request was cancelled. Try again when you're ready." = "请求已取消。准备就绪后请重试。";
351 352
 "Something went wrong while searching. Please try again in a moment." = "搜索时出错。请稍后再试。";
352 353
 "Job search is unavailable." = "工作搜索不可用。";
354
+"We couldn't complete your purchase. Please try again." = "无法完成购买。请重试。";
355
+"We couldn't restore your purchases. Please try again." = "无法恢复购买。请重试。";
356
+"Purchase was cancelled." = "购买已取消。";
357
+"This subscription isn't available in your App Store region." = "此订阅在您的 App Store 地区不可用。";
358
+"Purchases aren't allowed on this account or device." = "此账户或设备不允许购买。";
359
+"This introductory offer isn't available for your account." = "此介绍性优惠不适用于您的账户。";
360
+"The purchase couldn't be verified. Please try again." = "无法验证购买。请重试。";
361
+"We couldn't save the PDF. Try again or choose a different folder." = "无法保存 PDF。请重试或选择其他文件夹。";
362
+"We don't have permission to save to that folder. Choose another location or grant access." = "无权保存到该文件夹。请选择其他位置或授予访问权限。";
363
+"This disk is read-only. Choose another folder to save your PDF." = "此磁盘为只读。请选择其他文件夹保存 PDF。";
364
+"The disk is full. Free up space, then try again." = "磁盘已满。请释放空间后重试。";
353 365
 
354 366
 // MARK: - 提示
355 367
 "This profile will be removed from this Mac." = "此个人资料将从这台 Mac 上移除。";

+ 12 - 0
App for Indeed/zh-Hant.lproj/Localizable.strings

@@ -347,8 +347,20 @@
347 347
 // MARK: - 錯誤
348 348
 "We couldn't reach the server. Check your internet connection and try again." = "無法連線到伺服器。請檢查您的網路連線後再試一次。";
349 349
 "The search was cancelled. Try again when you're ready." = "搜尋已取消。準備就緒後請再試一次。";
350
+"The request was cancelled. Try again when you're ready." = "請求已取消。準備就緒後請再試一次。";
350 351
 "Something went wrong while searching. Please try again in a moment." = "搜尋時發生錯誤。請稍後再試。";
351 352
 "Job search is unavailable." = "工作搜尋無法使用。";
353
+"We couldn't complete your purchase. Please try again." = "無法完成購買。請再試一次。";
354
+"We couldn't restore your purchases. Please try again." = "無法回復購買。請再試一次。";
355
+"Purchase was cancelled." = "購買已取消。";
356
+"This subscription isn't available in your App Store region." = "此訂閱在您的 App Store 地區不可用。";
357
+"Purchases aren't allowed on this account or device." = "此帳號或裝置不允許購買。";
358
+"This introductory offer isn't available for your account." = "此介紹性優惠不適用於您的帳號。";
359
+"The purchase couldn't be verified. Please try again." = "無法驗證購買。請再試一次。";
360
+"We couldn't save the PDF. Try again or choose a different folder." = "無法儲存 PDF。請再試一次或選擇其他資料夾。";
361
+"We don't have permission to save to that folder. Choose another location or grant access." = "沒有權限儲存到該資料夾。請選擇其他位置或授予存取權限。";
362
+"This disk is read-only. Choose another folder to save your PDF." = "此磁碟為唯讀。請選擇其他資料夾儲存 PDF。";
363
+"The disk is full. Free up space, then try again." = "磁碟已滿。請釋出空間後再試一次。";
352 364
 
353 365
 // MARK: - 提示
354 366
 "This profile will be removed from this Mac." = "此個人資料將從這台 Mac 上移除。";