@redacto.io/consent-sdk-react 9.4.0-beta.0 → 9.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/.turbo/turbo-build.log +12 -12
  2. package/CHANGELOG.md +7 -0
  3. package/dist/privacy-center.d.mts +1 -0
  4. package/dist/privacy-center.d.ts +1 -0
  5. package/dist/privacy-center.js +1502 -1372
  6. package/dist/privacy-center.mjs +1185 -1055
  7. package/package.json +1 -1
  8. package/src/RedactoPrivacyCenter/components/AppShell/AppShell.tsx +5 -0
  9. package/src/RedactoPrivacyCenter/components/AppShell/UserMenu.tsx +6 -16
  10. package/src/RedactoPrivacyCenter/components/AppShell/usePrivacyCenterExitAction.ts +36 -0
  11. package/src/RedactoPrivacyCenter/components/PrivacyCenterSessionExpired.tsx +97 -0
  12. package/src/RedactoPrivacyCenter/context/AuthContext.tsx +23 -2
  13. package/src/RedactoPrivacyCenter/context/DataAvailabilityContext.session-expired.test.tsx +92 -0
  14. package/src/RedactoPrivacyCenter/context/DataAvailabilityContext.tsx +15 -3
  15. package/src/RedactoPrivacyCenter/context/types.ts +4 -0
  16. package/src/RedactoPrivacyCenter/lib/utils.session-expired.test.ts +109 -0
  17. package/src/RedactoPrivacyCenter/lib/utils.ts +55 -79
  18. package/src/RedactoPrivacyCenter/locales/as/translation.json +2 -0
  19. package/src/RedactoPrivacyCenter/locales/bho/translation.json +2 -0
  20. package/src/RedactoPrivacyCenter/locales/bn/translation.json +2 -0
  21. package/src/RedactoPrivacyCenter/locales/brx/translation.json +2 -0
  22. package/src/RedactoPrivacyCenter/locales/doi/translation.json +2 -0
  23. package/src/RedactoPrivacyCenter/locales/en/translation.json +2 -0
  24. package/src/RedactoPrivacyCenter/locales/gom/translation.json +2 -0
  25. package/src/RedactoPrivacyCenter/locales/gu/translation.json +2 -0
  26. package/src/RedactoPrivacyCenter/locales/hi/translation.json +2 -0
  27. package/src/RedactoPrivacyCenter/locales/kn/translation.json +2 -0
  28. package/src/RedactoPrivacyCenter/locales/ks/translation.json +2 -0
  29. package/src/RedactoPrivacyCenter/locales/mai/translation.json +2 -0
  30. package/src/RedactoPrivacyCenter/locales/ml/translation.json +2 -0
  31. package/src/RedactoPrivacyCenter/locales/mni-Mtei/translation.json +2 -0
  32. package/src/RedactoPrivacyCenter/locales/mr/translation.json +2 -0
  33. package/src/RedactoPrivacyCenter/locales/ne/translation.json +2 -0
  34. package/src/RedactoPrivacyCenter/locales/or/translation.json +2 -0
  35. package/src/RedactoPrivacyCenter/locales/pa/translation.json +2 -0
  36. package/src/RedactoPrivacyCenter/locales/sa/translation.json +2 -0
  37. package/src/RedactoPrivacyCenter/locales/sat/translation.json +2 -0
  38. package/src/RedactoPrivacyCenter/locales/sd/translation.json +2 -0
  39. package/src/RedactoPrivacyCenter/locales/ta/translation.json +2 -0
  40. package/src/RedactoPrivacyCenter/locales/te/translation.json +2 -0
  41. package/src/RedactoPrivacyCenter/locales/ur/translation.json +2 -0
@@ -28,6 +28,30 @@ let deadRefreshToken: string | null = null;
28
28
  let transientRefreshFailureUntil = 0;
29
29
  let transientRefreshBackoffMs = 0;
30
30
 
31
+ // ─── Terminal "session expired" signal ──────────────────────────────────────
32
+ // The circuit breaker above stops the *network* (a dead refresh token costs one
33
+ // request). This listener lets the React tree learn that the session is
34
+ // terminally over so it can show a dedicated "session expired" screen and gate
35
+ // every further fetch — instead of silently rendering empty/stale content or
36
+ // hard-navigating away. A single module-level listener, consistent with the
37
+ // single-instance breaker singleton above (one Privacy Center per page).
38
+ let sessionExpiredListener: (() => void) | null = null;
39
+
40
+ /**
41
+ * Register (or clear, with `null`) the callback fired when a refresh terminally
42
+ * fails — i.e. the refresh token is expired/invalid and re-authentication is
43
+ * required. AuthProvider registers its `markSessionExpired` here. Exported for
44
+ * that wiring and for tests; not part of the package's public API.
45
+ */
46
+ export const setSessionExpiredListener = (fn: (() => void) | null): void => {
47
+ sessionExpiredListener = fn;
48
+ };
49
+
50
+ /** Notify the React tree that the session has terminally expired. */
51
+ const notifySessionExpired = (): void => {
52
+ sessionExpiredListener?.();
53
+ };
54
+
31
55
  // Buffer time in seconds before token expiration to proactively refresh
32
56
  // Using 30 seconds to ensure tokens are refreshed before they expire
33
57
  const TOKEN_EXPIRY_BUFFER_SECONDS = 30;
@@ -350,8 +374,9 @@ export const checkAndRefreshAuth = async (
350
374
 
351
375
  const refreshToken = getStoredRefreshToken();
352
376
  if (!refreshToken) {
353
- // No refresh token available - user needs to sign in again
377
+ // No refresh token available - terminal: surface the session-expired screen.
354
378
  signOutPrivacyCenter();
379
+ notifySessionExpired();
355
380
  return false;
356
381
  }
357
382
 
@@ -376,6 +401,7 @@ export const checkAndRefreshAuth = async (
376
401
  console.error('Refreshed access token is already expired - clearing auth state');
377
402
  markRefreshTokenDead(refreshToken);
378
403
  signOutPrivacyCenter();
404
+ notifySessionExpired();
379
405
  return false;
380
406
  }
381
407
  sessionStorage.setItem('access_token', newAccessToken);
@@ -386,6 +412,7 @@ export const checkAndRefreshAuth = async (
386
412
  console.error('Refresh response missing access token - clearing auth state');
387
413
  markRefreshTokenDead(refreshToken);
388
414
  signOutPrivacyCenter();
415
+ notifySessionExpired();
389
416
  return false;
390
417
  }
391
418
 
@@ -401,10 +428,10 @@ export const checkAndRefreshAuth = async (
401
428
  }
402
429
  return isValid;
403
430
  } else {
404
- // Refresh token expired/revoked or server returned failure
405
- // This is an expected scenario - silently handle it
431
+ // Refresh token expired/revoked or server returned failure - terminal.
406
432
  markRefreshTokenDead(refreshToken);
407
433
  signOutPrivacyCenter();
434
+ notifySessionExpired();
408
435
  return false;
409
436
  }
410
437
  } catch (error: any) {
@@ -412,6 +439,7 @@ export const checkAndRefreshAuth = async (
412
439
  // Refresh token is expired / not found / already used - trip the breaker.
413
440
  markRefreshTokenDead(refreshToken);
414
441
  signOutPrivacyCenter();
442
+ notifySessionExpired();
415
443
  return false;
416
444
  }
417
445
 
@@ -559,7 +587,9 @@ export const ensureValidToken = async (
559
587
  const performTokenRefresh = async (
560
588
  organizationId?: string,
561
589
  workspaceId?: string,
562
- slug?: string,
590
+ // Retained for call-site compatibility; redirect-by-slug was removed in favor
591
+ // of the terminal "session expired" screen, so the value is intentionally unused.
592
+ _slug?: string,
563
593
  authContext?: {
564
594
  accessToken?: string;
565
595
  refreshToken?: string;
@@ -571,20 +601,15 @@ const performTokenRefresh = async (
571
601
  // Get organizationId and workspaceId from sessionStorage if not provided
572
602
  const orgId = organizationId || sessionStorage.getItem('pc_org_id') || '';
573
603
  const wsId = workspaceId || sessionStorage.getItem('pc_workspace_id') || '';
574
- const orgSlug = slug || sessionStorage.getItem('pc_org_slug') || '';
575
604
 
576
605
  if (!orgId || !wsId) {
577
606
  console.error('[Token Refresh] Missing organizationId or workspaceId');
578
607
  const error = new Error('Missing organizationId or workspaceId');
579
- // Call onError if provided, check return value before proceeding
580
- if (authContext?.onError) {
581
- const shouldProceed = authContext.onError(error);
582
- if (!shouldProceed) {
583
- return null;
584
- }
585
- }
608
+ // Inform the host (informational only — we no longer auto-navigate; the
609
+ // component surfaces a terminal "session expired" screen instead).
610
+ authContext?.onError?.(error);
586
611
  signOutPrivacyCenter();
587
- redirectToSignIn(orgSlug, authContext?.onError);
612
+ notifySessionExpired();
588
613
  return null;
589
614
  }
590
615
 
@@ -603,15 +628,10 @@ const performTokenRefresh = async (
603
628
  hasRefreshTokenInStorage: !!getStoredRefreshToken(),
604
629
  });
605
630
  const error = new Error('No refresh token available');
606
- // Call onError if provided, check return value before proceeding
607
- if (authContext?.onError) {
608
- const shouldProceed = authContext.onError(error);
609
- if (!shouldProceed) {
610
- return null;
611
- }
612
- }
631
+ // Inform the host (informational only — we no longer auto-navigate).
632
+ authContext?.onError?.(error);
613
633
  signOutPrivacyCenter();
614
- redirectToSignIn(orgSlug, authContext?.onError);
634
+ notifySessionExpired();
615
635
  return null;
616
636
  }
617
637
 
@@ -631,15 +651,10 @@ const performTokenRefresh = async (
631
651
  console.error('[Token Refresh] New access token is already expired');
632
652
  markRefreshTokenDead(refreshToken);
633
653
  const error = new Error('New access token is already expired');
634
- // Call onError if provided, check return value before proceeding
635
- if (authContext?.onError) {
636
- const shouldProceed = authContext.onError(error);
637
- if (!shouldProceed) {
638
- return null;
639
- }
640
- }
654
+ // Inform the host (informational only — we no longer auto-navigate).
655
+ authContext?.onError?.(error);
641
656
  signOutPrivacyCenter();
642
- redirectToSignIn(orgSlug, authContext?.onError);
657
+ notifySessionExpired();
643
658
  return null;
644
659
  }
645
660
 
@@ -662,47 +677,32 @@ const performTokenRefresh = async (
662
677
  console.error('[Token Refresh] Response missing access token');
663
678
  markRefreshTokenDead(refreshToken);
664
679
  const error = new Error('Response missing access token');
665
- // Call onError if provided, check return value before proceeding
666
- if (authContext?.onError) {
667
- const shouldProceed = authContext.onError(error);
668
- if (!shouldProceed) {
669
- return null;
670
- }
671
- }
680
+ // Inform the host (informational only — we no longer auto-navigate).
681
+ authContext?.onError?.(error);
672
682
  signOutPrivacyCenter();
673
- redirectToSignIn(orgSlug, authContext?.onError);
683
+ notifySessionExpired();
674
684
  return null;
675
685
  }
676
686
  } else {
677
- // Refresh token expired/revoked or server returned failure
687
+ // Refresh token expired/revoked or server returned failure - terminal.
678
688
  markRefreshTokenDead(refreshToken);
679
689
  const error = new Error('Refresh token expired or revoked');
680
- // Call onError if provided, check return value before proceeding
681
- if (authContext?.onError) {
682
- const shouldProceed = authContext.onError(error);
683
- if (!shouldProceed) {
684
- return null;
685
- }
686
- }
690
+ // Inform the host (informational only — we no longer auto-navigate).
691
+ authContext?.onError?.(error);
687
692
  signOutPrivacyCenter();
688
- redirectToSignIn(orgSlug, authContext?.onError);
693
+ notifySessionExpired();
689
694
  return null;
690
695
  }
691
696
  } catch (error: any) {
692
697
  if (isTerminalRefreshError(error)) {
693
698
  // Terminal: refresh token expired / not found / already used / 4xx. Trip the
694
- // breaker so this dead token is never re-submitted (onError controls
695
- // navigation only — the breaker has already tripped).
699
+ // breaker so this dead token is never re-submitted, then surface the
700
+ // session-expired screen (onError is informational; we no longer navigate).
696
701
  markRefreshTokenDead(refreshToken);
697
702
  const err = new Error('Refresh token expired or revoked');
698
- if (authContext?.onError) {
699
- const shouldProceed = authContext.onError(err);
700
- if (!shouldProceed) {
701
- return null;
702
- }
703
- }
703
+ authContext?.onError?.(err);
704
704
  signOutPrivacyCenter();
705
- redirectToSignIn(orgSlug, authContext?.onError);
705
+ notifySessionExpired();
706
706
  return null;
707
707
  }
708
708
 
@@ -718,30 +718,6 @@ const performTokenRefresh = async (
718
718
  }
719
719
  };
720
720
 
721
- /**
722
- * Helper to redirect to sign-in page
723
- */
724
- const redirectToSignIn = (slug?: string, onError?: (error: Error) => boolean): void => {
725
- if (typeof window === 'undefined') return;
726
-
727
- // If onError is provided, call it and check return value
728
- if (onError) {
729
- const error = new Error('Authentication failed - redirecting to sign-in');
730
- const shouldProceed = onError(error);
731
- if (!shouldProceed) {
732
- // User wants to handle navigation themselves
733
- return;
734
- }
735
- }
736
-
737
- const orgSlug = slug || sessionStorage.getItem('pc_org_slug') || '';
738
- if (orgSlug) {
739
- window.location.href = `/privacy-center/${orgSlug}/sign-in`;
740
- } else {
741
- window.location.href = '/privacy-center';
742
- }
743
- };
744
-
745
721
  // Activity helper functions
746
722
 
747
723
  export type ActivityBadgeStatus =
@@ -184,6 +184,8 @@
184
184
  "noData": "ডেটা নাই",
185
185
  "noDataTitle": "এতিয়ালৈকে দেখুৱাবলৈ একো নাই",
186
186
  "noDataDescription": "আপোনাৰ একাউণ্টৰ সৈতে সংযুক্ত কোনো সন্মতি, অনুৰোধ বা কাৰ্য্যাৱলী আমি এতিয়ালৈকে বিচাৰি পোৱা নাই। উপলব্ধ হোৱাৰ লগে লগে আপোনাৰ গোপনীয়তা ৰেকৰ্ডসমূহ ইয়াত দেখা যাব।",
187
+ "sessionExpiredTitle": "আপোনাৰ ছেচন শেষ হৈছে",
188
+ "sessionExpiredDescription": "অব্যাহত ৰাখিবলৈ অনুগ্ৰহ কৰি পুনৰ ছাইন ইন কৰক।",
187
189
  "rowsPerPage": "পৃষ্ঠাত শাৰী:",
188
190
  "pageOf": "পৃষ্ঠা {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}}-ৰ {{count}} শাৰী নিৰ্বাচিত",
@@ -184,6 +184,8 @@
184
184
  "noData": "कोनो डेटा नै",
185
185
  "noDataTitle": "अबहीं देखावे खातिर कुछ नइखे",
186
186
  "noDataDescription": "रउरा खाता से जुड़ल कवनो सहमति, अनुरोध, या गतिविधि अबहीं तक ना मिलल। रउरा गोपनीयता रिकॉर्ड उपलब्ध होते ई इहाँ देखाई दिही।",
187
+ "sessionExpiredTitle": "रउआ के सत्र खतम हो गइल बा",
188
+ "sessionExpiredDescription": "जारी रखे खातिर कृपया फेर से साइन इन करीं।",
187
189
  "rowsPerPage": "पृष्ठ प्रति पंक्ति:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} में से {{count}} पंक्ति चुनल गइल",
@@ -184,6 +184,8 @@
184
184
  "noData": "কোনো ডেটা নেই",
185
185
  "noDataTitle": "এখনো দেখানোর মতো কিছু নেই",
186
186
  "noDataDescription": "আপনার অ্যাকাউন্টের সাথে সম্পর্কিত কোনো সম্মতি, অনুরোধ বা ক্রিয়াকলাপ আমরা এখনো খুঁজে পাইনি। উপলব্ধ হওয়ার সাথে সাথেই আপনার গোপনীয়তা রেকর্ডগুলি এখানে প্রদর্শিত হবে।",
187
+ "sessionExpiredTitle": "আপনার সেশন মেয়াদ শেষ হয়ে গেছে",
188
+ "sessionExpiredDescription": "চালিয়ে যেতে অনুগ্রহ করে আবার সাইন ইন করুন।",
187
189
  "rowsPerPage": "প্রতি পৃষ্ঠায় সারি:",
188
190
  "pageOf": "পৃষ্ঠা {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}}-এর মধ্যে {{count}} সারি নির্বাচিত",
@@ -184,6 +184,8 @@
184
184
  "noData": "डेटा नंगौ",
185
185
  "noDataTitle": "दानो दिनथिनो थाखाय जेबो गैया",
186
186
  "noDataDescription": "दानो सम नोंथांनि एकाउन्टजों सोमोन्दो थानाय जेबो सहमति, हाबाय एबा खामानि जों मोननो हायाखै। नोंथांनि गोपनीयथा रिकर्डफोर मोननो हानाय बादि बेयावनो दिनथिजागोन।",
187
+ "sessionExpiredTitle": "नोंथांनि सेसन जोबबाय",
188
+ "sessionExpiredDescription": "सालायनो थाखाय अननानै फिन साइन इन खालाम।",
187
189
  "rowsPerPage": "पृष्ठनि पंक्ति:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} निफ्राय {{count}} पंक्ति सायख 'खै",
@@ -184,6 +184,8 @@
184
184
  "noData": "कोनो डेटा नै",
185
185
  "noDataTitle": "अजें दिक्खाने आस्तै किछ नेईं",
186
186
  "noDataDescription": "तुंदे खाते कन्नै जुड़ी दी कोई बी सहमति, बेनती जां गतिविधि अजें तक नेईं मिली। तुंदे गोपनीयता रिकॉर्ड उपलब्ध होंदे गै इत्थें दिक्खने गी मिलङन।",
187
+ "sessionExpiredTitle": "तुंदा सत्र खतम होई गेआ ऐ",
188
+ "sessionExpiredDescription": "जारी रक्खने आस्तै कृपा करियै फिरी साइन इन करो।",
187
189
  "rowsPerPage": "पृष्ठ प्रति पंक्ति:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} मध्ये {{count}} पंक्ति चुनल गेल",
@@ -200,6 +200,8 @@
200
200
  "noData": "No Data",
201
201
  "noDataTitle": "Nothing to show yet",
202
202
  "noDataDescription": "We couldn't find any consents, requests, or activity linked to your account yet. Your privacy records will appear here once they're available.",
203
+ "sessionExpiredTitle": "Your session has expired",
204
+ "sessionExpiredDescription": "Please sign in again to continue.",
203
205
  "rowsPerPage": "Rows per page:",
204
206
  "pageOf": "Page {{current}} of {{total}}",
205
207
  "rowsSelected": "{{count}} of {{total}} row(s) selected",
@@ -184,6 +184,8 @@
184
184
  "noData": "डेटा ना",
185
185
  "noDataTitle": "अजून दाखोवपाक कांय ना",
186
186
  "noDataDescription": "तुमच्या खात्याकडेन जोडिल्ली कसलीच संमती, मागण्यो वा कृती आमकां अजून मेळूंक नात. उपलब्ध जातकच तुमच्यो गोपनीयता नोंदी हांगा दिसतल्यो.",
187
+ "sessionExpiredTitle": "तुमचें सत्र सोंपलां",
188
+ "sessionExpiredDescription": "फुडें वचपाक उपकार करून परतून साइन इन करात.",
187
189
  "rowsPerPage": "पानाक पंक्ती:",
188
190
  "pageOf": "पान {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} मध्ये {{count}} पंक्ती निवडली",
@@ -184,6 +184,8 @@
184
184
  "noData": "ડેટા નથી",
185
185
  "noDataTitle": "હજુ સુધી બતાવવા માટે કંઈ નથી",
186
186
  "noDataDescription": "તમારા ખાતા સાથે જોડાયેલી કોઈ સંમતિઓ, વિનંતીઓ અથવા પ્રવૃત્તિ અમને હજુ સુધી મળી નથી. તમારા ગોપનીયતા રેકોર્ડ ઉપલબ્ધ થતાં જ અહીં દેખાશે.",
187
+ "sessionExpiredTitle": "તમારું સત્ર સમાપ્ત થઈ ગયું છે",
188
+ "sessionExpiredDescription": "ચાલુ રાખવા માટે કૃપા કરીને ફરીથી સાઇન ઇન કરો.",
187
189
  "rowsPerPage": "દર પૃષ્ઠ પંક્તિઓ:",
188
190
  "pageOf": "પૃષ્ઠ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} માંથી {{count}} પંક્તિ પસંદ",
@@ -187,6 +187,8 @@
187
187
  "noData": "कोई डेटा नहीं",
188
188
  "noDataTitle": "अभी दिखाने के लिए कुछ नहीं",
189
189
  "noDataDescription": "हमें अभी तक आपके खाते से जुड़ी कोई सहमति, अनुरोध या गतिविधि नहीं मिली। उपलब्ध होते ही आपके गोपनीयता रिकॉर्ड यहाँ दिखाई देंगे।",
190
+ "sessionExpiredTitle": "आपका सत्र समाप्त हो गया है",
191
+ "sessionExpiredDescription": "जारी रखने के लिए कृपया फिर से साइन इन करें।",
190
192
  "rowsPerPage": "प्रति पृष्ठ पंक्तियाँ:",
191
193
  "pageOf": "पृष्ठ {{current}} / {{total}}",
192
194
  "rowsSelected": "कुल {{total}} में से {{count}} पंक्तियाँ चयनित",
@@ -184,6 +184,8 @@
184
184
  "noData": "ಡೇಟಾ ಇಲ್ಲ",
185
185
  "noDataTitle": "ಇನ್ನೂ ತೋರಿಸಲು ಏನೂ ಇಲ್ಲ",
186
186
  "noDataDescription": "ನಿಮ್ಮ ಖಾತೆಗೆ ಸಂಬಂಧಿಸಿದ ಯಾವುದೇ ಸಮ್ಮತಿಗಳು, ವಿನಂತಿಗಳು ಅಥವಾ ಚಟುವಟಿಕೆ ನಮಗೆ ಇನ್ನೂ ಕಂಡುಬಂದಿಲ್ಲ. ನಿಮ್ಮ ಗೌಪ್ಯತಾ ದಾಖಲೆಗಳು ಲಭ್ಯವಾದ ತಕ್ಷಣ ಅವು ಇಲ್ಲಿ ಗೋಚರಿಸುತ್ತವೆ.",
187
+ "sessionExpiredTitle": "ನಿಮ್ಮ ಸೆಷನ್ ಅವಧಿ ಮುಗಿದಿದೆ",
188
+ "sessionExpiredDescription": "ಮುಂದುವರಿಸಲು ದಯವಿಟ್ಟು ಮತ್ತೆ ಸೈನ್ ಇನ್ ಮಾಡಿ.",
187
189
  "rowsPerPage": "ಪುಟಕ್ಕೆ ಸಾಲುಗಳು:",
188
190
  "pageOf": "ಪುಟ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} ರಲ್ಲಿ {{count}} ಸಾಲು ಆಯ್ಕೆಮಾಡಲಾಗಿದೆ",
@@ -184,6 +184,8 @@
184
184
  "noData": "ڈیٹا کانہہ",
185
185
  "noDataTitle": "ابٕ تام ہاوُن خٲطرٕ کانٛہہ نٕ",
186
186
  "noDataDescription": "اسہِ تُہنٛدِ اکاؤنٹَس سٕتۍ جُڑٕمٕژ کانٛہہِ رضامندی، درخواستٕ یا سرگرمی ابٕ تام نٕ لَب۔ تُہنٛد رازداری ریکارڈ یہِ دستیاب سپدِتھ یِتہِ کنہِ وُچھنہٕ یِیِہٕ۔",
187
+ "sessionExpiredTitle": "تُہنٛد سیشَن ختم گۄمُت",
188
+ "sessionExpiredDescription": "جاری رکھنہٕ خٲطرٕ مہربانی کرِتھ دوبارٕ سائن اِن کریو۔",
187
189
  "rowsPerPage": "صفحہ فی قطاراں:",
188
190
  "pageOf": "صفحہ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} منز {{count}} قطار چُنِت",
@@ -184,6 +184,8 @@
184
184
  "noData": "कोनो डेटा नै",
185
185
  "noDataTitle": "अखन तक देखाबय लेल किछु नहि",
186
186
  "noDataDescription": "अहाँक खाता सँ जुड़ल कोनो सहमति, अनुरोध, वा गतिविधि अखन तक नहि भेटल। उपलब्ध होइते अहाँक गोपनीयता रिकॉर्ड एतय देखाएत।",
187
+ "sessionExpiredTitle": "अहाँक सत्र समाप्त भऽ गेल अछि",
188
+ "sessionExpiredDescription": "जारी राखबाक लेल कृपया फेर सँ साइन इन करू।",
187
189
  "rowsPerPage": "पृष्ठ प्रति पंक्ति:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} मध्ये {{count}} पंक्ति चुनल गेल",
@@ -184,6 +184,8 @@
184
184
  "noData": "ഡാറ്റയില്ല",
185
185
  "noDataTitle": "ഇതുവരെ കാണിക്കാൻ ഒന്നുമില്ല",
186
186
  "noDataDescription": "നിങ്ങളുടെ അക്കൗണ്ടുമായി ബന്ധിപ്പിച്ച സമ്മതങ്ങളോ അഭ്യർത്ഥനകളോ പ്രവൃത്തിയോ ഇതുവരെ ഞങ്ങൾക്ക് കണ്ടെത്താനായില്ല. നിങ്ങളുടെ സ്വകാര്യതാ രേഖകൾ ലഭ്യമാകുമ്പോൾ അവ ഇവിടെ ദൃശ്യമാകും.",
187
+ "sessionExpiredTitle": "നിങ്ങളുടെ സെഷൻ കാലഹരണപ്പെട്ടു",
188
+ "sessionExpiredDescription": "തുടരാൻ ദയവായി വീണ്ടും സൈൻ ഇൻ ചെയ്യുക.",
187
189
  "rowsPerPage": "പേജിന് വരികൾ:",
188
190
  "pageOf": "പേജ് {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}}-ൽ {{count}} വരി തിരഞ്ഞെടുത്തു",
@@ -184,6 +184,8 @@
184
184
  "noData": "ꯗꯦꯇꯥ ꯂꯩꯇꯦ",
185
185
  "noDataTitle": "ꯍꯧꯖꯤꯛ ꯐꯥꯎꯕ ꯎꯠꯅꯕ ꯀꯔꯤꯁꯨ ꯂꯩꯇꯦ",
186
186
  "noDataDescription": "ꯍꯧꯖꯤꯛ ꯐꯥꯎꯕ ꯑꯗꯣꯝꯒꯤ ꯑꯀꯥꯎꯟꯇꯀ ꯁꯝꯅꯗꯨꯅ ꯀꯅꯁꯦꯟꯇ, ꯍꯧꯔꯛꯐꯝ, ꯅꯠꯇ꯭ꯔꯒ ꯈꯨꯗꯝꯕꯤꯠ ꯑꯃꯠꯇ ꯐꯪꯗꯔꯦ꯫ ꯑꯗꯣꯝꯒꯤ ꯄ꯭ꯔꯥꯏꯚꯦꯁꯤ ꯔꯤꯀꯣꯔꯗꯁꯤꯡ ꯐꯪꯂꯛꯄ ꯃꯇꯃꯗ ꯃꯐꯝ ꯑꯁꯤꯗ ꯎꯔꯛꯀꯅꯤ꯫",
187
+ "sessionExpiredTitle": "ꯑꯗꯣꯝꯒꯤ ꯁꯦꯁꯟ ꯂꯣꯏꯔꯦ",
188
+ "sessionExpiredDescription": "ꯃꯈꯥ ꯆꯠꯊꯔꯛꯅꯕ ꯆꯥꯅꯕꯤꯗꯨꯅ ꯑꯃꯨꯛ ꯍꯟꯅ ꯁꯥꯏꯟ ꯏꯟ ꯇꯧꯕꯤꯌꯨ꯫",
187
189
  "rowsPerPage": "ꯂꯦꯡꯒꯤ ꯃꯔꯨꯑꯣꯏꯕ:",
188
190
  "pageOf": "ꯂꯦꯡ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} ꯒꯤ ꯃꯔꯨꯑꯣꯏꯕ {{count}} ꯁꯤꯄ ꯈꯨꯟꯁꯥꯖꯈꯔꯦ",
@@ -184,6 +184,8 @@
184
184
  "noData": "डेटा नाही",
185
185
  "noDataTitle": "अद्याप दाखवण्यासारखे काही नाही",
186
186
  "noDataDescription": "तुमच्या खात्याशी संबंधित कोणत्याही संमती, विनंत्या किंवा क्रियाकलाप अद्याप आम्हाला आढळले नाहीत. उपलब्ध होताच तुमच्या गोपनीयता नोंदी येथे दिसतील.",
187
+ "sessionExpiredTitle": "तुमचे सत्र संपले आहे",
188
+ "sessionExpiredDescription": "सुरू ठेवण्यासाठी कृपया पुन्हा साइन इन करा.",
187
189
  "rowsPerPage": "प्रति पृष्ठ पंक्ती:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} पैकी {{count}} पंक्ती निवडली",
@@ -184,6 +184,8 @@
184
184
  "noData": "डेटा छैन",
185
185
  "noDataTitle": "अहिलेसम्म देखाउने केही छैन",
186
186
  "noDataDescription": "तपाईंको खातासँग जोडिएका कुनै सहमति, अनुरोध वा गतिविधि हामीले अहिलेसम्म फेला पारेनौं। उपलब्ध भएपछि तपाईंका गोपनीयता रेकर्डहरू यहाँ देखिनेछन्।",
187
+ "sessionExpiredTitle": "तपाईंको सत्र समाप्त भएको छ",
188
+ "sessionExpiredDescription": "जारी राख्न कृपया फेरि साइन इन गर्नुहोस्।",
187
189
  "rowsPerPage": "पृष्ठ प्रति पङ्क्तिहरू:",
188
190
  "pageOf": "पृष्ठ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} मध्ये {{count}} पङ्क्ति चयन गरियो",
@@ -184,6 +184,8 @@
184
184
  "noData": "ତଥ୍ୟ ନାହିଁ",
185
185
  "noDataTitle": "ଏପର୍ଯ୍ୟନ୍ତ ଦେଖାଇବାକୁ କିଛି ନାହିଁ",
186
186
  "noDataDescription": "ଆପଣଙ୍କ ଆକାଉଣ୍ଟ ସହିତ ସଂଯୁକ୍ତ କୌଣସି ସମ୍ମତି, ଅନୁରୋଧ କିମ୍ବା କାର୍ଯ୍ୟକଳାପ ଆମେ ଏପର୍ଯ୍ୟନ୍ତ ପାଇଲୁ ନାହିଁ। ଉପଲବ୍ଧ ହେବା ମାତ୍ରେ ଆପଣଙ୍କ ଗୋପନୀୟତା ରେକର୍ଡ ଏଠାରେ ଦେଖାଯିବ।",
187
+ "sessionExpiredTitle": "ଆପଣଙ୍କ ସେସନ୍ ସମାପ୍ତ ହୋଇଯାଇଛି",
188
+ "sessionExpiredDescription": "ଜାରି ରଖିବାକୁ ଦୟାକରି ପୁନର୍ବାର ସାଇନ୍ ଇନ୍ କରନ୍ତୁ।",
187
189
  "rowsPerPage": "ପୃଷ୍ଠାକୁ ଧାଡ଼ି:",
188
190
  "pageOf": "ପୃଷ୍ଠା {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} ରୁ {{count}} ଧାଡ଼ି ବାଛିଲେ",
@@ -184,6 +184,8 @@
184
184
  "noData": "ਕੋਈ ਡੇਟਾ ਨਹੀਂ",
185
185
  "noDataTitle": "ਅਜੇ ਦਿਖਾਉਣ ਲਈ ਕੁਝ ਨਹੀਂ",
186
186
  "noDataDescription": "ਅਸੀਂ ਤੁਹਾਡੇ ਖਾਤੇ ਨਾਲ ਜੁੜੀ ਕੋਈ ਸਹਿਮਤੀ, ਬੇਨਤੀ ਜਾਂ ਗਤੀਵਿਧੀ ਅਜੇ ਨਹੀਂ ਲੱਭ ਸਕੇ। ਤੁਹਾਡੇ ਗੋਪਨੀਯਤਾ ਰਿਕਾਰਡ ਉਪਲਬਧ ਹੁੰਦੇ ਹੀ ਇੱਥੇ ਦਿਖਾਈ ਦੇਣਗੇ।",
187
+ "sessionExpiredTitle": "ਤੁਹਾਡਾ ਸੈਸ਼ਨ ਸਮਾਪਤ ਹੋ ਗਿਆ ਹੈ",
188
+ "sessionExpiredDescription": "ਜਾਰੀ ਰੱਖਣ ਲਈ ਕਿਰਪਾ ਕਰਕੇ ਦੁਬਾਰਾ ਸਾਈਨ ਇਨ ਕਰੋ।",
187
189
  "rowsPerPage": "ਪੰਨੇ ਪ੍ਰਤੀ ਕਤਾਰਾਂ:",
188
190
  "pageOf": "ਪੰਨਾ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} ਵਿੱਚੋਂ {{count}} ਕਤਾਰ ਚੁਣੀ ਗਈ",
@@ -184,6 +184,8 @@
184
184
  "noData": "डेटा नास्ति",
185
185
  "noDataTitle": "अद्यापि किमपि दर्शयितुं नास्ति",
186
186
  "noDataDescription": "भवतः खातया सह सम्बद्धाः काश्चन सम्मतयः, अनुरोधाः, कार्यकलापाः वा अद्यापि अस्माभिः न प्राप्ताः। उपलब्धाः सति भवतः गोपनीयता-अभिलेखाः अत्र दर्शयिष्यन्ते।",
187
+ "sessionExpiredTitle": "भवतः सत्रं समाप्तम्",
188
+ "sessionExpiredDescription": "अनुवर्तनार्थं कृपया पुनः प्रवेशं करोतु।",
187
189
  "rowsPerPage": "पृष्ठे पंक्तयः:",
188
190
  "pageOf": "पृष्ठम् {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} मध्ये {{count}} पंक्तिः चिता",
@@ -184,6 +184,8 @@
184
184
  "noData": "ᱰᱮᱴᱟ ᱵᱟᱹᱱᱩᱜᱼᱟ",
185
185
  "noDataTitle": "ᱱᱤᱛ ᱛᱟᱠ ᱡᱟᱦᱟᱸ ᱫᱮᱠᱷᱟᱣ ᱞᱟᱹᱜᱤᱫ ᱵᱟᱝ",
186
186
  "noDataDescription": "ᱟᱞᱮ ᱱᱤᱛ ᱛᱟᱠ ᱟᱢᱟᱜ ᱮᱠᱟᱣᱩᱱᱴ ᱥᱟᱞᱟᱜ ᱡᱚᱲᱟᱣ ᱡᱟᱦᱟᱸ ᱥᱚᱦᱚᱢᱚᱛᱤ, ᱦᱟᱵᱟᱭ, ᱟᱨᱵᱟᱝ ᱠᱟᱹᱢᱤ ᱵᱟᱝ ᱧᱟᱢ ᱫᱟᱲᱮᱭᱟᱫᱼᱟ᱾ ᱟᱢᱟᱜ ᱯᱨᱟᱭᱣᱮᱥᱤ ᱨᱤᱠᱚᱨᱰ ᱠᱚ ᱧᱟᱢᱚᱜ ᱠᱷᱟᱱ ᱱᱚᱸᱰᱮ ᱫᱮᱠᱷᱟᱣᱚᱜᱼᱟ᱾",
187
+ "sessionExpiredTitle": "ᱟᱢᱟᱜ ᱥᱮᱥᱚᱱ ᱢᱩᱪᱟᱹᱫᱮᱱᱟ",
188
+ "sessionExpiredDescription": "ᱞᱟᱦᱟ ᱪᱟᱞᱟᱣ ᱞᱟᱹᱜᱤᱫ ᱫᱟᱭᱟ ᱠᱟᱛᱮ ᱫᱳᱦᱲᱟ ᱥᱟᱭᱱ ᱤᱱ ᱢᱮ᱾",
187
189
  "rowsPerPage": "ᱯᱮᱡᱽ ᱯᱤᱨᱤ ᱪᱷᱩᱴᱟᱹ:",
188
190
  "pageOf": "ᱯᱮᱡᱽ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} ᱠᱷᱚᱱ {{count}} ᱪᱷᱩᱴᱟᱹ ᱵᱟᱪᱷᱟᱣ",
@@ -184,6 +184,8 @@
184
184
  "noData": "ڊيٽا ڪانهي",
185
185
  "noDataTitle": "اڃا ڏيکارڻ لاءِ ڪجهه ناهي",
186
186
  "noDataDescription": "اسان کي اڃا تائين توهان جي اڪائونٽ سان لاڳاپيل ڪابه رضامندي، درخواست يا سرگرمي نه ملي. توهان جا رازداري رڪارڊ موجود ٿيندي ئي هتي ظاهر ٿيندا.",
187
+ "sessionExpiredTitle": "توهان جو سيشن ختم ٿي ويو آهي",
188
+ "sessionExpiredDescription": "جاري رکڻ لاءِ مهرباني ڪري ٻيهر سائن ان ڪريو.",
187
189
  "rowsPerPage": "صفحي في قطارون:",
188
190
  "pageOf": "صفحو {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}} مان {{count}} قطار چونڊيل",
@@ -184,6 +184,8 @@
184
184
  "noData": "தரவு இல்லை",
185
185
  "noDataTitle": "இன்னும் காட்ட எதுவும் இல்லை",
186
186
  "noDataDescription": "உங்கள் கணக்குடன் இணைக்கப்பட்ட ஒப்புதல்கள், கோரிக்கைகள் அல்லது செயல்பாடு எதையும் இன்னும் எங்களால் கண்டறிய முடியவில்லை. உங்கள் தனியுரிமை பதிவுகள் கிடைக்கும்போது அவை இங்கே தோன்றும்.",
187
+ "sessionExpiredTitle": "உங்கள் அமர்வு காலாவதியாகிவிட்டது",
188
+ "sessionExpiredDescription": "தொடர்வதற்கு தயவுசெய்து மீண்டும் உள்நுழையவும்.",
187
189
  "rowsPerPage": "பக்கத்திற்கு வரிசைகள்:",
188
190
  "pageOf": "பக்கம் {{current}} / {{total}}",
189
191
  "rowsSelected": "{{count}} / {{total}} வரிசைத் தேர்ந்தெடுக்கப்பட்டது",
@@ -184,6 +184,8 @@
184
184
  "noData": "డేటా లేదు",
185
185
  "noDataTitle": "చూపించడానికి ఇంకా ఏమీ లేదు",
186
186
  "noDataDescription": "మీ ఖాతాకు అనుసంధానించబడిన ఏ సమ్మతులు, అభ్యర్థనలు లేదా కార్యాచరణ ఇంకా మాకు కనుగొనబడలేదు. అందుబాటులోకి వచ్చిన తర్వాత మీ గోప్యతా రికార్డులు ఇక్కడ కనిపిస్తాయి.",
187
+ "sessionExpiredTitle": "మీ సెషన్ గడువు ముగిసింది",
188
+ "sessionExpiredDescription": "కొనసాగించడానికి దయచేసి మళ్లీ సైన్ ఇన్ చేయండి.",
187
189
  "rowsPerPage": "పేజీకి వరుసలు:",
188
190
  "pageOf": "పేజీ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{total}}లో {{count}} వరుస ఎంచుకోబడింది",
@@ -184,6 +184,8 @@
184
184
  "noData": "کوئی ڈیٹا نہیں",
185
185
  "noDataTitle": "ابھی دکھانے کے لیے کچھ نہیں",
186
186
  "noDataDescription": "ہمیں ابھی تک آپ کے اکاؤنٹ سے منسلک کوئی رضامندی، درخواست یا سرگرمی نہیں ملی۔ آپ کے پرائیویسی ریکارڈ دستیاب ہوتے ہی یہاں ظاہر ہو جائیں گے۔",
187
+ "sessionExpiredTitle": "آپ کا سیشن ختم ہو گیا ہے",
188
+ "sessionExpiredDescription": "جاری رکھنے کے لیے براہ کرم دوبارہ سائن اِن کریں۔",
187
189
  "rowsPerPage": "فی صفحہ قطاریں:",
188
190
  "pageOf": "صفحہ {{current}} / {{total}}",
189
191
  "rowsSelected": "{{count}} از {{total}} قطار منتخب",