@dialstack/sdk-native 0.2.0 → 0.2.1
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.
- package/dist/index.d.ts +10 -1
- package/dist/index.js +95 -19
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -646,6 +646,7 @@ declare class Call {
|
|
|
646
646
|
* otherwise prepareAnswerForOffer does it when the offer lands.
|
|
647
647
|
*/
|
|
648
648
|
private acquireDeferredCapture;
|
|
649
|
+
private reportAnswerFailure;
|
|
649
650
|
/** Set by the owner to surface a late mic failure, since `Call` has no error event. */
|
|
650
651
|
private reportCaptureFailure;
|
|
651
652
|
onCaptureFailure(report: (e: unknown) => void): void;
|
|
@@ -664,7 +665,6 @@ declare class Call {
|
|
|
664
665
|
/** Route this call's ringback tone to `deviceId` (null = OS default). */
|
|
665
666
|
setAudioOutputDevice(deviceId: string | null): void;
|
|
666
667
|
private watchCaptureTrack;
|
|
667
|
-
private get isFinished();
|
|
668
668
|
private issueReqId;
|
|
669
669
|
on<K extends keyof CallEventMap>(event: K, handler: Listener$1<K>): void;
|
|
670
670
|
off<K extends keyof CallEventMap>(event: K, handler?: Listener$1<K>): void;
|
|
@@ -988,6 +988,7 @@ declare class DialStackPhone {
|
|
|
988
988
|
private fetchIceServers;
|
|
989
989
|
private handleMessage;
|
|
990
990
|
private handleIncoming;
|
|
991
|
+
private answerFailureReporter;
|
|
991
992
|
private emit;
|
|
992
993
|
}
|
|
993
994
|
|
|
@@ -1736,9 +1737,16 @@ declare const en: {
|
|
|
1736
1737
|
extensionPlaceholder: string;
|
|
1737
1738
|
addUser: string;
|
|
1738
1739
|
removeUser: string;
|
|
1740
|
+
removePhoneAccess: string;
|
|
1741
|
+
adminBadge: string;
|
|
1739
1742
|
noUsers: string;
|
|
1740
1743
|
atLeastOne: string;
|
|
1741
1744
|
duplicateEmail: string;
|
|
1745
|
+
extensionRequired: string;
|
|
1746
|
+
extensionTaken: string;
|
|
1747
|
+
noPhoneService: string;
|
|
1748
|
+
givePhoneAccess: string;
|
|
1749
|
+
givingPhoneAccess: string;
|
|
1742
1750
|
};
|
|
1743
1751
|
location: {
|
|
1744
1752
|
heading: string;
|
|
@@ -2011,6 +2019,7 @@ declare const en: {
|
|
|
2011
2019
|
focDateTooSoon: string;
|
|
2012
2020
|
focDateTooFar: string;
|
|
2013
2021
|
focTimeRequired: string;
|
|
2022
|
+
focTimeOutOfWindow: string;
|
|
2014
2023
|
billCopyRequired: string;
|
|
2015
2024
|
signatureRequired: string;
|
|
2016
2025
|
eligibilityError: string;
|
package/dist/index.js
CHANGED
|
@@ -683,6 +683,7 @@ class Call {
|
|
|
683
683
|
// True until answer() acquires the mic this call deliberately did not take on
|
|
684
684
|
// arrival. Cleared there so a later device switch takes the ordinary path.
|
|
685
685
|
this.captureDeferred = false;
|
|
686
|
+
this.reportAnswerFailure = () => { };
|
|
686
687
|
/** Set by the owner to surface a late mic failure, since `Call` has no error event. */
|
|
687
688
|
this.reportCaptureFailure = () => { };
|
|
688
689
|
this.id = init.id;
|
|
@@ -731,11 +732,17 @@ class Call {
|
|
|
731
732
|
// only need the success path. A rejection is swallowed so it cannot surface as
|
|
732
733
|
// an unhandled rejection before the owner attaches.
|
|
733
734
|
void this.localMediaReady.then(async () => {
|
|
734
|
-
if (this.
|
|
735
|
+
if (this.isFinished || this.answerSent || !this.remoteDescriptionSet)
|
|
735
736
|
return;
|
|
736
|
-
|
|
737
|
+
// Nothing awaits this build, so its failure would otherwise vanish as an
|
|
738
|
+
// unhandled rejection and leave the call ringing with no answer sent.
|
|
739
|
+
await this.buildAnswer().catch(this.reportAnswerFailure);
|
|
737
740
|
}, this.reportCaptureFailure);
|
|
738
741
|
}
|
|
742
|
+
/** @internal Set by the owner to surface an answer built off the offer path failing. */
|
|
743
|
+
onAnswerFailure(report) {
|
|
744
|
+
this.reportAnswerFailure = report;
|
|
745
|
+
}
|
|
739
746
|
onCaptureFailure(report) {
|
|
740
747
|
this.reportCaptureFailure = report;
|
|
741
748
|
}
|
|
@@ -757,10 +764,17 @@ class Call {
|
|
|
757
764
|
// let the OS choose. Skipped for a permission denial (re-prompts, same answer)
|
|
758
765
|
// and for a locked mic (no device of the kind is readable, so there is nothing
|
|
759
766
|
// looser constraints could find).
|
|
760
|
-
|
|
767
|
+
// A retry for a call that is already over would prompt again for nothing.
|
|
768
|
+
if (!preferred || !isRetryableWithoutDevice(e) || this.isFinished)
|
|
761
769
|
throw e;
|
|
762
770
|
stream = await getUserMedia({ audio: true });
|
|
763
771
|
}
|
|
772
|
+
// The call ended while the prompt was open: releaseMedia already ran and can't
|
|
773
|
+
// see these tracks; unstopped, the mic indicator stays lit.
|
|
774
|
+
if (this.isFinished) {
|
|
775
|
+
stream.getTracks().forEach(stopTrack$1);
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
764
778
|
stream.getTracks().forEach((t) => {
|
|
765
779
|
this.localStream.addTrack(t);
|
|
766
780
|
this.watchCaptureTrack(t);
|
|
@@ -910,8 +924,10 @@ class Call {
|
|
|
910
924
|
this.emit('audioInputLost');
|
|
911
925
|
});
|
|
912
926
|
}
|
|
913
|
-
|
|
914
|
-
|
|
927
|
+
/**
|
|
928
|
+
* @internal True once the call is over by either path: the server's call.ended
|
|
929
|
+
* (which sets endedSettled) or a local dispose().
|
|
930
|
+
*/
|
|
915
931
|
get isFinished() {
|
|
916
932
|
return this.endedSettled || this.state === 'ended';
|
|
917
933
|
}
|
|
@@ -957,7 +973,8 @@ class Call {
|
|
|
957
973
|
callId: this.id,
|
|
958
974
|
});
|
|
959
975
|
}
|
|
960
|
-
|
|
976
|
+
// A stale tap on a call that already ended must not take the mic for it.
|
|
977
|
+
if (this.answerSent || this.isFinished)
|
|
961
978
|
return;
|
|
962
979
|
// Deferred capture is taken HERE, not on arrival: the OS owns the audio
|
|
963
980
|
// session and only activates it on answer, so acquiring earlier fails and
|
|
@@ -981,7 +998,7 @@ class Call {
|
|
|
981
998
|
// call has ended, or the answer SDP isn't ready. Called from answer() (when
|
|
982
999
|
// ready) and from prepareAnswerForOffer() (to flush a deferred answer).
|
|
983
1000
|
sendAnswer() {
|
|
984
|
-
if (this.answerSent || this.
|
|
1001
|
+
if (this.answerSent || this.isFinished || !this.pendingAnswerSdp)
|
|
985
1002
|
return;
|
|
986
1003
|
this.transport.send({ type: 'call.answer', req_id: this.issueReqId(), call_id: this.id });
|
|
987
1004
|
this.transport.send({ type: 'sdp.answer', call_id: this.id, sdp: this.pendingAnswerSdp });
|
|
@@ -1222,9 +1239,23 @@ class Call {
|
|
|
1222
1239
|
// buffered while the mic prompt was open can be applied, then wait for the
|
|
1223
1240
|
// local mic before building the answer — the offer may have arrived while
|
|
1224
1241
|
// getUserMedia was still pending.
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1242
|
+
//
|
|
1243
|
+
// The call can end at any of these awaits — the caller hangs up, another
|
|
1244
|
+
// device in a ring group answers, the user declines — and teardown closes the
|
|
1245
|
+
// peer connection, which then throws on every operation. That is not a
|
|
1246
|
+
// failure to report: the call is simply over, so stop without rejecting.
|
|
1247
|
+
if (this.isFinished)
|
|
1248
|
+
return;
|
|
1249
|
+
try {
|
|
1250
|
+
await this.peerConnection.setRemoteDescription({ type: 'offer', sdp });
|
|
1251
|
+
this.remoteDescriptionSet = true;
|
|
1252
|
+
await this.flushPendingRemoteCandidates();
|
|
1253
|
+
}
|
|
1254
|
+
catch (e) {
|
|
1255
|
+
if (this.isFinished)
|
|
1256
|
+
return;
|
|
1257
|
+
throw e;
|
|
1258
|
+
}
|
|
1228
1259
|
try {
|
|
1229
1260
|
await this.localMediaReady;
|
|
1230
1261
|
}
|
|
@@ -1235,6 +1266,8 @@ class Call {
|
|
|
1235
1266
|
// same denial.
|
|
1236
1267
|
return;
|
|
1237
1268
|
}
|
|
1269
|
+
if (this.isFinished)
|
|
1270
|
+
return;
|
|
1238
1271
|
await this.buildAnswer();
|
|
1239
1272
|
}
|
|
1240
1273
|
// Builds (or rebuilds) the answer from an already-set remote description. Split
|
|
@@ -1259,11 +1292,20 @@ class Call {
|
|
|
1259
1292
|
try {
|
|
1260
1293
|
await this.buildAnswerOnce();
|
|
1261
1294
|
}
|
|
1295
|
+
catch (e) {
|
|
1296
|
+
// Teardown mid-build rejects whichever await was in flight (a closed peer
|
|
1297
|
+
// connection, or the ICE wait releaseMedia aborts); see prepareAnswerForOffer.
|
|
1298
|
+
if (!this.isFinished)
|
|
1299
|
+
throw e;
|
|
1300
|
+
}
|
|
1262
1301
|
finally {
|
|
1263
1302
|
this.buildingAnswer = false;
|
|
1264
1303
|
}
|
|
1265
1304
|
}
|
|
1266
1305
|
async buildAnswerOnce() {
|
|
1306
|
+
// Rechecked after every await: the call may have ended while it was pending.
|
|
1307
|
+
if (this.isFinished)
|
|
1308
|
+
return;
|
|
1267
1309
|
// setRemoteDescription(offer) above already created a track-less sender for
|
|
1268
1310
|
// each offered m-line, so getSenders() is non-empty here even though no mic
|
|
1269
1311
|
// is attached yet. Guard on whether a sender actually has a track — keying
|
|
@@ -1277,10 +1319,16 @@ class Call {
|
|
|
1277
1319
|
}
|
|
1278
1320
|
this.attachDtmfSender();
|
|
1279
1321
|
const answer = await this.peerConnection.createAnswer();
|
|
1322
|
+
if (this.isFinished)
|
|
1323
|
+
return;
|
|
1280
1324
|
await this.peerConnection.setLocalDescription(answer);
|
|
1325
|
+
if (this.isFinished)
|
|
1326
|
+
return;
|
|
1281
1327
|
// Same requirement as startOutbound: the answer must carry at least one
|
|
1282
1328
|
// candidate, or the negotiated session has no ICE.
|
|
1283
1329
|
await this.waitForIceGatheringComplete();
|
|
1330
|
+
if (this.isFinished)
|
|
1331
|
+
return;
|
|
1284
1332
|
this.pendingAnswerSdp = this.peerConnection.localDescription?.sdp ?? answer.sdp ?? null;
|
|
1285
1333
|
// Flush a deferred answer: answer() may have been clicked before the SDP
|
|
1286
1334
|
// was ready, in which case it set wantsAnswer instead of sending.
|
|
@@ -1349,11 +1397,26 @@ class Call {
|
|
|
1349
1397
|
return true;
|
|
1350
1398
|
}
|
|
1351
1399
|
async acceptRemoteAnswer(sdp) {
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1400
|
+
// As in prepareAnswerForOffer: an end landing mid-apply closes the connection,
|
|
1401
|
+
// and that is not a failure to report.
|
|
1402
|
+
if (this.isFinished)
|
|
1403
|
+
return;
|
|
1404
|
+
try {
|
|
1405
|
+
await this.peerConnection.setRemoteDescription({ type: 'answer', sdp });
|
|
1406
|
+
this.remoteDescriptionSet = true;
|
|
1407
|
+
await this.flushPendingRemoteCandidates();
|
|
1408
|
+
}
|
|
1409
|
+
catch (e) {
|
|
1410
|
+
if (this.isFinished)
|
|
1411
|
+
return;
|
|
1412
|
+
throw e;
|
|
1413
|
+
}
|
|
1355
1414
|
}
|
|
1356
1415
|
async addRemoteCandidate(candidate, sdpMid, sdpMLineIndex) {
|
|
1416
|
+
// A disposed call stays routable, but its closed connection rejects every
|
|
1417
|
+
// candidate, and the caller does not await this.
|
|
1418
|
+
if (this.isFinished)
|
|
1419
|
+
return;
|
|
1357
1420
|
const init = candidate == null
|
|
1358
1421
|
? null
|
|
1359
1422
|
: { candidate, sdpMid: sdpMid ?? undefined, sdpMLineIndex: sdpMLineIndex ?? undefined };
|
|
@@ -3238,11 +3301,7 @@ class DialStackPhone {
|
|
|
3238
3301
|
// is swallowed inside prepareAnswerForOffer, so it is not double-emitted
|
|
3239
3302
|
// here.
|
|
3240
3303
|
if (call) {
|
|
3241
|
-
void call.prepareAnswerForOffer(msg.sdp).catch(
|
|
3242
|
-
code: 'call_failed',
|
|
3243
|
-
message: `Failed to prepare answer for incoming call: ${e.message}`,
|
|
3244
|
-
callId: msg.call_id,
|
|
3245
|
-
})));
|
|
3304
|
+
void call.prepareAnswerForOffer(msg.sdp).catch(this.answerFailureReporter(call));
|
|
3246
3305
|
}
|
|
3247
3306
|
return;
|
|
3248
3307
|
}
|
|
@@ -3352,6 +3411,9 @@ class DialStackPhone {
|
|
|
3352
3411
|
// through onCaptureFailure if the mic is still unavailable on answer.
|
|
3353
3412
|
if (e instanceof CaptureDeferred)
|
|
3354
3413
|
return;
|
|
3414
|
+
// A prompt dismissed after the call ended failed nothing: the call is over.
|
|
3415
|
+
if (call.isFinished)
|
|
3416
|
+
return;
|
|
3355
3417
|
this.emit('error', new PhoneError({
|
|
3356
3418
|
code: 'call_failed',
|
|
3357
3419
|
message: `Microphone unavailable for incoming call: ${e.message}`,
|
|
@@ -3359,8 +3421,22 @@ class DialStackPhone {
|
|
|
3359
3421
|
}));
|
|
3360
3422
|
};
|
|
3361
3423
|
call.onCaptureFailure(reportMicFailure);
|
|
3424
|
+
call.onAnswerFailure(this.answerFailureReporter(call));
|
|
3362
3425
|
call.whenLocalMediaReady().catch(reportMicFailure);
|
|
3363
3426
|
}
|
|
3427
|
+
answerFailureReporter(call) {
|
|
3428
|
+
return (e) => {
|
|
3429
|
+
// Backstop for the guards inside Call: whatever an ended call's answer
|
|
3430
|
+
// build throws, the call is over and nothing failed.
|
|
3431
|
+
if (call.isFinished)
|
|
3432
|
+
return;
|
|
3433
|
+
this.emit('error', new PhoneError({
|
|
3434
|
+
code: 'call_failed',
|
|
3435
|
+
message: `Failed to prepare answer for incoming call: ${e.message}`,
|
|
3436
|
+
callId: call.id,
|
|
3437
|
+
}));
|
|
3438
|
+
};
|
|
3439
|
+
}
|
|
3364
3440
|
emit(event, ...args) {
|
|
3365
3441
|
this.listeners[event]?.forEach((h) => {
|
|
3366
3442
|
h(...args);
|
|
@@ -5779,7 +5855,7 @@ function resolveSoftphonePalette(appearance) {
|
|
|
5779
5855
|
};
|
|
5780
5856
|
}
|
|
5781
5857
|
|
|
5782
|
-
"function"==typeof SuppressedError&&SuppressedError;const v={common:{loading:"Loading...",error:"Error",noResults:"No results",delete:"Delete",call:"Call",cancel:"Cancel",confirm:"Confirm",previous:"Previous",next:"Next",perPage:"Per page",showing:"Showing {start}-{end} of {total}",play:"Play",pause:"Pause"},softphone:{title:"Softphone",destinationPlaceholder:"Enter a number",call:"Call",backspace:"Delete",connecting:"Connecting…",reconnecting:"Reconnecting…",disconnected:"Disconnected",connectionError:"Connection error",callError:"Call failed",micPermissionError:"Microphone access is required — allow it and try again",dismiss:"Dismiss",unknownCaller:"Unknown",incomingCall:"Incoming call",answer:"Answer",decline:"Decline",hangUp:"Hang up",mute:"Mute",unmute:"Unmute",hold:"Hold",resume:"Resume",keypad:"Keypad",transfer:"Transfer",transferPlaceholder:"Transfer to…",transferSend:"Transfer",transferNow:"Transfer now",transferConsult:"Consult first",transferComplete:"Complete transfer",transferConsulting:"Consulting…",transferOriginalOnHold:"On hold",addCall:"Add call",addCallPlaceholder:"Number to dial",addCallSend:"Call",merge:"Merge calls",split:"Split",conferenceLabel:"Conference",cancel:"Cancel",stateTrying:"Calling…",stateRinging:"Ringing…",stateActive:"In call",stateHeld:"On hold",stateEnded:"Call ended",done:"Done",audioDevices:"Audio",audioMicrophone:"Microphone",audioSpeaker:"Speaker",audioSystemDefault:"System default",audioUnnamedDevice:"Unnamed device",audioLabelsHidden:"Allow microphone access to see device names",audioDevicesUnsupported:"This browser cannot list audio devices",audioSpeakerUnsupported:"Choose your speaker in your device settings",audioMicrophoneLost:"Your microphone was disconnected — choose another",switchToCall:"Switch to this call",heldCallsLabel:"On hold",callWaiting:"Call waiting",emergencyPrompt:"Set your emergency location",emergencyHint:"Confirm your location before placing calls — required by 911 regulations for internet calling.",emergencyConfirm:"Yes, I'm here",emergencyNewLocation:"Set a new location",emergencyUseLocation:"Use my current location",emergencyLocating:"Getting your location…",emergencyNumber:"Number",emergencyStreet:"Street",emergencyUnit:"Unit (optional)",emergencyCity:"City",emergencyState:"State",emergencyPostalCode:"Postal code",emergencySave:"Confirm location",emergencySaving:"Saving…",emergencyBack:"Back"},aiAgent:{loading:"Loading Managed VoiceAI agent…",loadFailed:"Failed to load Managed VoiceAI agent: {message}",fields:{name:"Name",namePlaceholder:"Front Desk Agent",nameHint:"Internal label shown in lists and call logs. Not heard by callers.",extensionNumber:"Extension",extensionNumberPlaceholder:"700",extensionNumberHint:"Dial this extension from any phone on the account to reach the agent.",extensionChecking:"Checking extension...",personaName:"Persona name",personaNamePlaceholder:"e.g. Receptionist",personaNameHint:"How the agent introduces itself on calls.",greetingName:"Greeting name",greetingNamePlaceholder:"Your business name",greetingNameHintWithName:'Used in the call greeting (e.g. "Thanks for calling {name}").',greetingNameHintGeneric:'Used in the call greeting (e.g. "Thanks for calling [your business]").',instructions:"Instructions",instructionsPlaceholder:"Provide additional instructions for how the Managed VoiceAI agent should behave during calls...",instructionsHint:"Plain-English guidance for the agent: tone, what to do, what to escalate.",faq:"FAQ",faqEmpty:"No FAQ entries yet. Add one to teach the agent a recurring question.",faqEntry:"Entry {index}",faqQuestion:"Question",faqAnswer:"Answer",faqQuestionLabel:"FAQ entry {index} question",faqAnswerLabel:"FAQ entry {index} answer",faqRemove:"Remove",faqRemoveLabel:"Remove FAQ entry {index}",faqAdd:"Add FAQ entry",scheduling:"Scheduling",schedulingHint:"Connect your Managed VoiceAI agent to an external scheduling system. Clear the URL to disable scheduling.",webhookUrl:"Webhook URL",webhookUrlHint:"Base URL for scheduling webhooks. DialStack appends tool-call paths automatically.",webhookUrlPlaceholder:"https://example.com/api/dialstack/webhooks",secret:"Webhook secret",secretHint:"Used to verify tool-call webhooks sent from this Managed VoiceAI agent to your integration.",copySecret:"Copy webhook secret",rotateSecret:"Rotate secret"},save:"Save",saving:"Saving…",saved:"Saved.",errors:{nameRequired:"Name is required.",nameMaxLength:"Name must be {max} characters or fewer.",personaNameMaxLength:"Persona name must be {max} characters or fewer.",greetingNameMaxLength:"Greeting name must be {max} characters or fewer.",instructionsMaxLength:"Instructions must be {max} characters or fewer.",faqMaxItems:"FAQ supports up to {max} entries.",faqIncompleteEntry:"Every FAQ entry needs both a question and an answer.",faqFieldMaxLength:"FAQ fields must be {max} characters or fewer.",extensionNumeric:"Extension must contain only digits.",extensionUnavailable:"Extension number is already in use.",schedulingUrlMaxLength:"Webhook URL must be {max} characters or fewer.",schedulingUrlHttpsRequired:"Webhook URL must start with https://.",hostCreateRequired:"This form is waiting for the host app to create the Managed VoiceAI agent.",hostSaveRequired:"This form is waiting for the host app to save the Managed VoiceAI agent."}},voicemails:{title:"Voicemails",loading:"Loading voicemails...",empty:"No voicemails",noUserId:"Please set a user ID to load voicemails",transcription:"Transcription",summary:"Summary",sentiment:"Sentiment",sentimentPositive:"Positive",sentimentNeutral:"Neutral",sentimentNegative:"Negative",sentimentMixed:"Mixed",transcript:"Full Transcript",transcriptLoading:"Loading transcript...",transcriptNotAvailable:"Transcript not available",deleteConfirm:"Delete this voicemail?",deleteTitle:"Delete Voicemail",progress:"Playback progress"},callLogs:{title:"Call Logs",loading:"Loading call logs...",empty:"No call logs found",columns:{date:"Date",direction:"Direction",from:"From",to:"To",duration:"Duration",status:"Status",quality:"MOS"},directions:{inbound:"Inbound",outbound:"Outbound",internal:"Internal"},routedTo:"Routed to:",calledBy:"Called by:",statuses:{completed:"Completed",noAnswer:"No Answer",busy:"Busy",failed:"Failed",voicemail:"Voicemail"},quality:{good:"Good",fair:"Fair",poor:"Poor",unavailable:"N/A",unavailableTooltip:"No quality data available"}},callHistory:{title:"Call History",loading:"Loading call history...",empty:"No call history",noPhoneNumber:"Please set a phone number to load call history",error:"Unable to load call history",clickToCall:"Click to call",summaryNotAvailable:"Summary not available",relativeTime:{justNow:"Just now",minuteAgo:"1 min ago",minutesAgo:"{count} min ago",hourAgo:"1 hour ago",hoursAgo:"{count} hours ago",yesterday:"Yesterday"}},phoneNumberOrdering:{title:"Order Phone Numbers",steps:{search:"Search",select:"Select",confirm:"Confirm",route:"Route",done:"Done",stepOf:"Step {current} of {total}"},search:{title:"Search Available Numbers",subtitle:"Find available phone numbers by entering an area code or ZIP code.",searchType:"Search by",areaCode:"Area Code",zip:"ZIP Code",areaCodeLabel:"Area Code",areaCodePlaceholder:"e.g. 212",zipLabel:"ZIP Code",zipPlaceholder:"e.g. 10001",numberOfResults:"Quantity to display",search:"Search"},results:{title:"Available Numbers",phoneNumber:"Phone Number",state:"State",selectAll:"Select all",selected:"{count} selected",noResults:"No numbers available for this search",continue:"Continue",backToSearch:"Back to Search"},confirm:{title:"Confirm Order",subtitleOne:"You are about to order 1 phone number",subtitleOther:"You are about to order {count} phone numbers",description:"Your order will be submitted to the carrier for fulfillment. This usually completes within seconds but may take longer.",placeOrder:"Place Order",continue:"Continue",back:"Back",billing:{label:"Billing impact",headline:"Adds {amount}/month to this account's bill",detail:"{count} phone numbers at {rate} each per month.",detail_one:"{count} phone number at {rate} per month.",detail_other:"{count} phone numbers at {rate} each per month.",timing:"Billing starts when each number activates.",taxesAndFees:"Taxes and fees are additional.",noPrice:"These numbers are billable on this account.",noPrice_one:"This number is billable on this account.",noPrice_other:"These numbers are billable on this account.",notBilled:"This account is not billed, so ordering these numbers costs nothing."}},route:{title:"Choose call routing",subtitle:"Pick where these numbers should send calls once they activate. You can change this any time, or set it up later.",later:"Set up routing later",laterHint:"Configure each number from its detail page after it activates.",noTargets:"No routing destinations exist yet. You can set up routing after the numbers are added.",unnamed:"Untitled",extension:"ext. {ext}",back:"Back",type:{user:"User",dial_plan:"Dial plan",voice_app:"Voice app",queue:"Queue",ring_group:"Ring group",shared_voicemail:"Shared voicemail"}},ordering:{title:"Placing Order..."},complete:{titlePendingOne:"Order Submitted",titlePendingOther:"Order Submitted",titleCompleteOne:"Number Ready",titleCompleteOther:"Numbers Ready",titlePartialOne:"Partially Fulfilled",titlePartialOther:"Partially Fulfilled",descriptionPendingOne:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",descriptionPendingOther:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",descriptionCompleteOne:"Your phone number is now in your inventory and ready to be configured.",descriptionCompleteOther:"Your phone numbers are now in your inventory and ready to be configured.",descriptionPartialOne:"Some numbers could not be fulfilled by the carrier.",descriptionPartialOther:"Some numbers could not be fulfilled by the carrier.",checking:"Checking order status...",assignmentHint:"Numbers added to your inventory still need to be assigned to an extension or dial plan before they can receive calls.",orderMore:"Order More Numbers"},error:{title:"Order Failed",description:"The carrier was unable to fulfill your order.",tryAgain:"Try Again"},statuses:{pending:"Pending",complete:"Complete",partial:"Partial",failed:"Failed"}},phoneNumbers:{title:"Phone Numbers",loading:"Loading phone numbers...",empty:"No phone numbers",filterLabel:"Filter by status",search:{placeholder:"Search phone numbers...",noResults:"No phone numbers match your search"},filters:{active:"Active",in_progress:"In Progress",cancelled:"Cancelled"},columns:{phoneNumber:"Phone Number",status:"Status",callerID:"Outbound Caller ID",callerIDPrefix:"Inbound Caller ID Prefix",outbound:"Usage",carrier:"Carrier",transferDate:"Transfer Date",routingTarget:"Call Routing",cancelledDate:"Date Cancelled"},statuses:{active:"Active",inactive:"Inactive",released:"Released",ordering:"Ordering",orderFailed:"Order Failed",portingDraft:"Port Draft",portingApproved:"Ready to Submit",portingSubmitted:"Port Submitted",portingException:"Port Issue",portingFoc:"Port Scheduled"},badges:{temporary:"Temporary"},outbound:{enabled:"Two-way",disabled:"Inbound only",fax:"Fax"},routingTarget:{notSet:"Not set",setAction:"Set routing",faxNotApplicable:"Not applicable"},routingTargetTypes:{user:"User",dialPlan:"Dial Plan",voiceApp:"Voice App",ringGroup:"Ring Group"}},accountOnboarding:{billing:{label:"Billing impact",headline:"Adds {amount}/month to this account's bill",detail:{userSeat:{one:"{count} user seat at {rate} per month.",other:"{count} user seats at {rate} each per month."},phoneNumber:{one:"{count} phone number at {rate} per month.",other:"{count} phone numbers at {rate} each per month."}},noPrice:{userSeat:{one:"Adds {count} billable user seat to this account.",other:"Adds {count} billable user seats to this account."},phoneNumber:{one:"Adds {count} billable phone number to this account.",other:"Adds {count} billable phone numbers to this account."}},rateHeadline:{userSeat:"{rate}/month per user seat",phoneNumber:"{rate}/month per phone number"},rateDetail:{userSeat:"Each team member you add is billed at this rate.",phoneNumber:"Each number you add is billed at this rate."},noPriceRate:{userSeat:"Each team member you add is billable on this account.",phoneNumber:"Each number you add is billable on this account."},startsOnActivation:"Billing starts when each number activates.",taxesAndFees:"Taxes and fees are additional.",notBilled:"This account is not billed, so this costs nothing."},title:"Account Onboarding",breadcrumbAriaLabel:"Onboarding progress",loading:"Loading...",error:{title:"Unable to Load",description:"Something went wrong loading the onboarding wizard.",retry:"Try Again"},steps:{account:"Account Setup",numbers:"Phone Numbers",hardware:"Hardware Setup",complete:"Complete"},sidebar:{businessDetails:"Business Details",businessDetailsDesc:"Enter your company information",teamMembers:"Team Members",teamMembersDesc:"Add users and assign extensions",numberOptions:"Number Options",numberOptionsDesc:"Choose to port existing or get new numbers",callerId:"Caller ID",callerIdDesc:"Set caller ID for your numbers",directoryListing:"Directory Listing",directoryListingDesc:"Configure 411 directory listing",numberSetup:"Number Setup",numberSetupDesc:"Configure your phone numbers",verification:"Verification",verificationDesc:"Verify number status",deviceAssignment:"Device Assignment",deviceAssignmentDesc:"Assign devices to users"},account:{title:"Business Details",subtitle:"Enter your company information",details:{heading:"Account Details",companyNameLabel:"Company Name",companyNamePlaceholder:"Acme Corp",companyNameRequired:"Company name is required",emailLabel:"Primary Contact Email",emailPlaceholder:"admin@company.com",emailRequired:"Primary contact email is required",emailInvalid:"Enter a valid email address",phoneLabel:"Primary Contact Phone Number",phonePlaceholder:"(555) 123-4567",phoneRequired:"Primary contact phone number is required",phoneInvalid:"Enter a valid US phone number",primaryContactLabel:"Primary Contact",primaryContactPlaceholder:"Jane Doe",primaryContactRequired:"Primary contact is required",regionLabel:"Region",regionPlaceholder:"Select a region",timezoneLabel:"Timezone",timezonePlaceholder:"Select a timezone",timezoneRequired:"Timezone is required"},users:{heading:"Team Members",description:"Add users who will have phone extensions",nameLabel:"Full name",namePlaceholder:"John Doe",nameRequired:"Name is required",emailLabel:"Email",emailPlaceholder:"john@company.com",extensionLabel:"Extension",extensionPlaceholder:"ex. 103",addUser:"Add User",removeUser:"Remove",noUsers:"No team members added yet.",atLeastOne:"Add at least one team member to continue.",duplicateEmail:"A user with this email already exists."},location:{heading:"Business Location",description:"Add your business address for E911 and caller ID.",nameLabel:"Location Name",namePlaceholder:"Main Office",nameRequired:"Location name is required",addressLabel:"Address",searchPlaceholder:"Start typing an address...",searching:"Searching...",noResults:"No addresses found",enterManually:"Enter manually",searchInstead:"Search instead",edit:"Edit",addressRequired:"Address is required",houseNumberLabel:"#",houseNumberPlaceholder:"123",streetLabel:"Street",streetPlaceholder:"Main St",cityLabel:"City",cityPlaceholder:"New York",stateLabel:"State",statePlaceholder:"Select",postalCodeLabel:"ZIP",postalCodePlaceholder:"10001"},saving:"Saving...",saveError:"Failed to save. Please try again."},numbers:{title:"Phone Numbers",subtitle:"Choose how you'd like to set up your business numbers",defaultDialPlanName:"Onboarding Dial Plan",callerId:{title:"Caller ID Setup",subtitle:"Configure the name displayed when making outbound calls",inputLabel:"Caller ID Name",inputPlaceholder:"e.g. ACME Corp",inputHelp:"Max 15 characters. Letters, numbers, spaces, and hyphens only.",charCount:"{count}/15",submit:"Set Caller ID",submitting:"Submitting...",submittingAll:"Submitting caller IDs...",submitted:"Submitted",alreadySet:"Already configured",submitAll:"Set All Caller IDs",skipCallerId:"Skip",partialError:"Some caller IDs could not be set. Fix errors and retry, or skip.",validation:{required:"Caller ID name is required",tooLong:"Must be 15 characters or fewer",invalidChars:"Only letters, numbers, spaces, and hyphens allowed"},error:{submitFailed:"Failed to set caller ID. Please try again.",conflict:"A caller ID update is already in progress for this number."},directoryListing:{title:"Directory Listing (DA/DL)",info:"To update your directory listing, contact {platformName} support."},noDIDs:"No active phone numbers to configure."},directoryListing:{title:"Directory Listing",subtitle:"A directory listing feeds your business information into online directories and data aggregators, helping customers find you. It also reduces the chance of your outbound calls being flagged as spam by call-screening apps.",selectPrompt:"Select which number should be listed:",noneOption:"None — skip directory listing",noDIDs:"No eligible phone numbers to configure.",businessName:"Business Name",businessNamePlaceholder:"Enter business name for listing",businessNameHelp:"The name shown in directory listings and used for caller verification. Max 200 characters.",validation:{nameRequired:"Business name is required for the directory listing."}},overview:{heading:"Your Numbers",empty:"No telephone numbers yet. Request new numbers or port your existing ones.",requestNew:"Request New Numbers",requestNewDesc:"Get new business phone numbers instantly. Choose from available numbers in your area.",portExisting:"Port Existing Number",portExistingDesc:"Transfer your current business number to {platformName}. This typically takes 5–10 business days.",phoneNumber:"Phone Number",type:"Type",status:"Status",source:"Source",temporaryBanner:"A temporary number has been assigned to your account while you set up your permanent numbers.",loadError:"Failed to load telephone numbers. Please try again.",retry:"Retry"},status:{active:"Active",inactive:"Inactive",released:"Released",ordering:"Ordering",order_failed:"Order Failed",porting_draft:"Port Draft",porting_submitted:"Port Submitted",porting_exception:"Port Exception",porting_foc:"Port Scheduled",porting_approved:"Ready to Submit"},source:{did:"Account",didTemporary:"Temporary",number_order:"New Order",port_order:"Port"},order:{searchTitle:"Search Available Numbers",searchSubtitle:"Find available numbers by entering an area code or ZIP code",searchByAreaCode:"Area Code",searchByZip:"ZIP Code",areaCodeLabel:"Area Code",areaCodePlaceholder:"212",zipLabel:"ZIP Code",zipPlaceholder:"10001",quantityLabel:"Quantity",search:"Search",searching:"Searching...",resultsTitle:"Available Numbers",resultsSubtitle:"Select the numbers you would like to order.",noResults:"No numbers found. Try a different search.",selectAll:"Select All",deselectAll:"Deselect All",selected:"selected",state:"State",confirmTitle:"Confirm Your Order",confirmSubtitle:"You are about to order {count} phone numbers",confirmSubtitle_one:"You are about to order {count} phone number",confirmSubtitle_other:"You are about to order {count} phone numbers",carrierNote:"Your order will be submitted to the carrier for fulfillment. This usually completes within seconds but may take longer.",placeOrder:"Place Order",placing:"Placing Order...",ordering:"Ordering...",statusTitle:"Order Submitted",statusPending:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",statusStalled:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",statusComplete:"Your numbers have been activated.",statusFailed:"The order could not be completed.",statusPartial:"Some numbers were activated, but others failed.",done:"Done",orderMore:"Order More Numbers",continue:"Continue",error:"An error occurred while placing the order."},port:{numbersTitle:"Numbers to Port",numbersSubtitle:"Enter the numbers you want to transfer to {platformName}, or paste a whole list into any row.",phoneLabel:"Phone Number",phonePlaceholder:"(555) 123-4567",addAnother:"Add another number",numberLabel:"Phone number {row}",removeNumber:"Remove phone number {row}",duplicateOfRow:"Duplicate of row {row}",pasteHint:"Press Enter for another row. Pasting a list — one per line, commas, or a spreadsheet column — fills a row for each number.",readyCountZero:"No numbers yet",readyCountOne:"{count} number ready",readyCountOther:"{count} numbers ready",needsAttentionOne:"{count} row needs attention before you can continue",needsAttentionOther:"{count} rows need attention before you can continue",reasonInvalid:"Not a valid US phone number",reasonNotUs:"Only US numbers can be ported",reasonTollFree:"Toll-free numbers cannot be ported",reasonAmbiguous:"Too many digits for one number — if this is several, put one per row",reasonHasExtension:"Remove the extension",maxPerOrder:"{count} numbers — the maximum is {max} per order. Move {excess} into a second port order.",notPortableWithDetail:"{label} ({detail})",accountLimit:"You've reached the number of phone numbers this account can hold. Contact support to raise the limit, then try again.",numbersUnavailable:"Some of these numbers are already in use and can't be ported. The ones affected are marked above.",conflictAlreadyOnAccount:"You already have this number",conflictInServiceElsewhere:"Already in service — contact support to transfer it",checkEligibility:"Check Eligibility",checking:"Checking...",eligibilityTitle:"Port Eligibility",eligibilitySubtitle:"Review which numbers can be ported.",portable:"Portable",notPortable:"Not Portable",carrier:"Current Carrier",wireless:"Wireless",wirelessYes:"Yes",wirelessNo:"No",accountRequired:"Account # Required",continueWithPortable:"Continue with Portable Numbers",noPortable:"None of the entered numbers are eligible for porting.",subscriberTitle:"Subscriber Information",subscriberSubtitle:"Enter the details exactly as they appear on your current phone bill.",btnLabel:"Billing Telephone Number (BTN)",btnPlaceholder:"(555) 123-4567",businessNameLabel:"Business Name",businessNamePlaceholder:"Acme Corp",approverNameLabel:"Authorized Contact",approverNamePlaceholder:"John Doe",accountNumberLabel:"Account Number",accountNumberPlaceholder:"From your current carrier",pinLabel:"Account PIN",pinPlaceholder:"1234",addressHeading:"Service Address",houseNumberLabel:"Street Number",houseNumberPlaceholder:"123",streetNameLabel:"Street Name",streetNamePlaceholder:"Main St",line2Label:"Suite / Unit",line2Placeholder:"Suite 100",cityLabel:"City",cityPlaceholder:"New York",stateLabel:"State",statePlaceholder:"Select state",zipLabel:"ZIP Code",zipPlaceholder:"10001",focTitle:"Requested Port Date",focSubtitle:"Choose when you want the numbers transferred. Must be at least 5 business days out.",focDateLabel:"Port Date",focTimeLabel:"Port Time (Eastern)",focTimePlaceholder:"Select time",documentsTitle:"Supporting Documents",documentsSubtitle:"Upload your latest phone bill and optionally a Customer Service Record (CSR).",billCopyLabel:"Phone Bill Copy",billCopyDesc:"A recent bill from your current carrier showing the numbers to be ported.",billCopyRequired:"Required",csrLabel:"Customer Service Record (CSR)",csrDesc:"Optional but recommended — speeds up the porting process.",csrOptional:"Optional",uploadFile:"Choose File",fileSelected:"Selected:",noFileSelected:"No file selected",uploading:"Uploading...",reviewTitle:"Review & Approve",reviewSubtitle:"Verify all details before submitting your port request.",numbersSection:"Numbers",subscriberSection:"Subscriber",focSection:"Port Date",documentsSection:"Documents",signatureLabel:"Electronic Signature",signaturePlaceholder:"Type your full legal name",signatureHelp:"By signing, you authorize the transfer of the listed numbers to {platformName}.",approve:"Approve & Submit",submitting:"Submitting...",submittedTitle:"Port Request Submitted",submittedSubtitle:"Your port request has been submitted and is being processed.",submittedStatus:"Status",backToOverview:"Back to Numbers",carrierGroupsTitle:"Carrier Groups",carrierGroupsSubtitle:"Your numbers are with different carriers. Each carrier requires a separate port request.",carrierStart:"Start",carrierContinue:"Continue",carrierSubmitted:"Submitted",numberSingular:"number",numberPlural:"numbers"},validation:{areaCodeRequired:"Area code is required.",areaCodeFormat:"Enter a 3-digit area code.",cityRequired:"City is required.",stateRequired:"State is required.",zipRequired:"ZIP code is required.",zipFormat:"Enter a 5-digit ZIP code.",selectAtLeastOne:"Select at least one number.",phoneRequired:"At least one phone number is required.",phoneInvalid:"Enter a valid US phone number.",phoneDuplicate:"This number has already been entered.",btnRequired:"BTN is required.",btnInvalid:"Enter a valid US phone number.",businessNameRequired:"Business name is required.",approverNameRequired:"Authorized contact name is required.",houseNumberRequired:"Street number is required.",streetNameRequired:"Street name is required.",focDateRequired:"Port date is required.",focDateTooSoon:"Port date must be at least 5 business days from today.",focDateTooFar:"Port date must be within 30 days.",focTimeRequired:"Port time is required.",billCopyRequired:"A phone bill copy is required.",signatureRequired:"Signature is required.",eligibilityError:"Failed to check eligibility. Please try again.",submitError:"Failed to submit port request. Please try again."},nav:{back:"Back",next:"Next",cancel:"Cancel",backToSearch:"Back to Search",confirm:"Confirm"},gate:{noDIDsAvailable:"You need at least one phone number before selecting a primary number. Order or port a number first.",primaryRequired:"Please select a primary number to continue."}},hardware:{title:"Assign Devices",shippingAddress:"Shipping Address",subtitle:"Drag and drop devices to assign them to team members",noUsers:"No team members found. Add team members in the Account step first.",noDevices:"No devices are available for your account at the moment.",isDectBase:"This is a cordless handset base station",userLabel:"Team Member",selectUser:"Select a team member",selectUserRequired:"Please select a team member.",macLabel:"MAC Address",macPlaceholder:"00:04:13:AA:BB:CC",invalidMac:"Enter a valid 12-digit MAC address.",ipeiLabel:"Handset IPEI",ipeiPlaceholder:"03AABB1234567890CCDD",invalidIpei:"Enter a valid IPEI (hex digits only).",ipeiNotMac:"This looks like a MAC address, not an IPEI. An IPEI looks like 03AABB1234567890CCDD.",removeDevice:"Remove",unsupportedVendor:"This device is not currently supported. Our support team has been notified and will follow up.",duplicateMac:"This MAC address is already registered.",deviceNotFound:"Device was created but could not be found. Please try again.",handset:"handset",handsets:"handsets",addDeviceButton:"+ Add Device",addHandsetButton:"+ Handset",save:"Save",saving:"Saving...",cancel:"Cancel",dectBase:"Cordless Base",removeBaseFailed:"Failed to remove cordless base.",tableHeaderName:"Full name",tableHeaderExtension:"Extension",tableHeaderDevice:"Assigned Device",availableDevices:"Available Devices",allAssigned:"All devices have been assigned",dragDropHint:"Drag and drop device here",clickToAssign:"Click to assign",submitOrder:"Submit Order",assignAndComplete:"Save & Continue",unassign:"Unassign",deskPhone:"Desk phone",cordless:"Cordless",submitting:"Submitting...",gate:{noDevices:"No devices are available for your account. Please contact support to add devices before completing this step."}},complete:{title:"Wahoo!",subtitle:"It's time to start using your embedded voice system",e911:{loading:"Configuring emergency services...",pollingStatus:"Verifying emergency services registration...",verified:"E911 emergency address is verified.",processing:"E911 registration is being processed. This may take a few minutes.",pendingAfterPolling:"E911 registration submitted. Your phone service is active — emergency address verification will complete shortly.",addressStandardized:"Your address was standardized for emergency services accuracy.",primaryAssigned:"assigned as primary number for",errorTitle:"E911 configuration failed",errorDescription:"There was an error configuring emergency services. You can retry or configure manually later.",retryButton:"Retry",deferred:"E911 emergency services have not been fully configured. Each location with a phone number needs a verified emergency address before your phone service can be activated."}},stepComplete:{title:"{stepName} Complete",subtitle:"This step has been completed successfully.",done:"Done"},nav:{next:"Next",skip:"Skip",back:"Back",exit:"Finish"},legal:{prefix:"By continuing, you agree to the",and:"and",termsOfService:"Terms of Service",recipientTerms:"Recipient Terms of Service",privacyPolicy:"Privacy Policy"},ssa:{title:"Review and accept your subscription agreement",intro:"Before you can use your phone service, please review the Service Subscription Agreement below — including its emergency calling (911/E911) terms — and confirm your acceptance.",pricingTitle:"Your plan pricing",perUser:"Per user",perNumber:"Per phone number",perAiLocation:"Managed VoiceAI, per location",perMonthSuffix:"/mo",agreementLabel:"Service Subscription Agreement",openInNewTab:"Open the full agreement in a new tab",accept:"Accept & Continue",submitting:"Recording your acceptance…",notPermitted:"Only the account owner can accept this agreement. Please ask them to sign in and accept it — phone service requires their signature.",errors:{stale:"The agreement was updated. Please review the latest version and accept again.",pricingMissing:"Your plan pricing has not been finalized yet. Please contact your provider to continue.",generic:"We could not record your acceptance. Please try again.",retry:"Try again"},loadError:{title:"Unable to load your agreement",description:"We could not load your subscription agreement, which is required before you can continue. Please try again.",retry:"Try again",retrying:"Loading…"}}},onboardingPortal:{onboardingFlows:"ONBOARDING FLOWS",saveAndExit:"Save & Exit to Overview",back:"Back",helpSupport:"Help & Support",onboardingComplete:"Onboarding complete",rates:{title:"Your monthly rates",subtitle:"What you're billed at today.",perUser:"Per user",perPhoneNumber:"Per phone number",perVoiceAiLocation:"Managed VoiceAI, per location",voiceAiPerLocationNote:"Charged for every location once Managed VoiceAI is active.",perMonth:"{rate}/month",rateNotSet:"Not set",pendingRate:"{rate}/month from {date}",pendingNote:"Rate changes take effect at the start of the next billing period.",taxesAndFees:"Taxes and fees are additional.",notBilled:"This account is not billed.",noRates:"No rates are set for this account yet.",unavailable:"Rates are unavailable right now."},overview:{label:"Overview",title:"Your Business Onboarding",subtitle:"Complete the steps below to set up your business phone system",progressTitle:"Onboarding Progress",flowsComplete:"{completed} of {total} flows complete",stepsTitle:"Onboarding Steps",complete:"Complete",progress:"Progress",completeSetup:"Complete Setup",continueSetup:"Continue Setup",review:"Review",needHelp:"Need help?",needHelpSubtitle:"Our team is here to help you get set up quickly",scheduleCall:"Schedule a Call",viewDocs:"View Documentation",accountDesc:"Set up your business profile, add team members, and configure your dial plan",numbersDesc:"Port existing numbers or request new business lines",hardwareDesc:"Assign phones to team members and track delivery",phoneStatusTitle:"Phone number status",phoneStatusSubtitle:"Track the status of your phone numbers",phoneStatusNumber:"Phone Number",phoneStatusType:"Type",phoneStatusStatus:"Status",phoneStatusTypeNew:"New",phoneStatusTypePort:"Port",phoneStatusProcessing:"Processing",phoneStatusComplete:"Complete",phoneStatusTemporary:"Temporary"},splash:{title:"Welcome\nto {platformName}",subtitle:"Let's get your business set up in 3 easy steps",start:"Start Onboarding",step1:"Account Details",step2:"Setup Phone Numbers",step3:"Assign Hardware"}},dialPlan:{title:"Dial Plan",loading:"Loading dial plan...",error:"Failed to load dial plan",empty:"No dial plan found",nodeTypes:{start:"Start",schedule:"Schedule",internalDial:"Internal Extension",voicemail:"Voicemail",externalDial:"External Number",voiceApp:"Voice App",menu:"IVR Menu",audioClip:"Audio Clip",hangUp:"Hang Up"},nodeDescriptions:{menu:"Play prompt and route by keypress",audioClip:"Play an audio clip",hangUp:"End the call"},exits:{open:"Open",closed:"Closed",holiday:"Holiday",next:"Next",timeout:"Timeout",invalid:"Invalid"},configLabels:{promptClip:"Prompt",audioClip:"Audio Clip",digit:"Digit",options:"Options",addOption:"Add Option",removeOption:"Remove",optionLabel:"Label",optionLabelPlaceholder:"e.g. Sales",routeHolidaySeparately:"Route holidays separately",routeHolidaySeparatelyHint:"When on, holidays route to a dedicated branch you wire below. Otherwise holidays follow the Closed exit."},resourceGroups:{audioClips:"Audio Clips"}}},f=v;
|
|
5858
|
+
"function"==typeof SuppressedError&&SuppressedError;const v={common:{loading:"Loading...",error:"Error",noResults:"No results",delete:"Delete",call:"Call",cancel:"Cancel",confirm:"Confirm",previous:"Previous",next:"Next",perPage:"Per page",showing:"Showing {start}-{end} of {total}",play:"Play",pause:"Pause"},softphone:{title:"Softphone",destinationPlaceholder:"Enter a number",call:"Call",backspace:"Delete",connecting:"Connecting…",reconnecting:"Reconnecting…",disconnected:"Disconnected",connectionError:"Connection error",callError:"Call failed",micPermissionError:"Microphone access is required — allow it and try again",dismiss:"Dismiss",unknownCaller:"Unknown",incomingCall:"Incoming call",answer:"Answer",decline:"Decline",hangUp:"Hang up",mute:"Mute",unmute:"Unmute",hold:"Hold",resume:"Resume",keypad:"Keypad",transfer:"Transfer",transferPlaceholder:"Transfer to…",transferSend:"Transfer",transferNow:"Transfer now",transferConsult:"Consult first",transferComplete:"Complete transfer",transferConsulting:"Consulting…",transferOriginalOnHold:"On hold",addCall:"Add call",addCallPlaceholder:"Number to dial",addCallSend:"Call",merge:"Merge calls",split:"Split",conferenceLabel:"Conference",cancel:"Cancel",stateTrying:"Calling…",stateRinging:"Ringing…",stateActive:"In call",stateHeld:"On hold",stateEnded:"Call ended",done:"Done",audioDevices:"Audio",audioMicrophone:"Microphone",audioSpeaker:"Speaker",audioSystemDefault:"System default",audioUnnamedDevice:"Unnamed device",audioLabelsHidden:"Allow microphone access to see device names",audioDevicesUnsupported:"This browser cannot list audio devices",audioSpeakerUnsupported:"Choose your speaker in your device settings",audioMicrophoneLost:"Your microphone was disconnected — choose another",switchToCall:"Switch to this call",heldCallsLabel:"On hold",callWaiting:"Call waiting",emergencyPrompt:"Set your emergency location",emergencyHint:"Confirm your location before placing calls — required by 911 regulations for internet calling.",emergencyConfirm:"Yes, I'm here",emergencyNewLocation:"Set a new location",emergencyUseLocation:"Use my current location",emergencyLocating:"Getting your location…",emergencyNumber:"Number",emergencyStreet:"Street",emergencyUnit:"Unit (optional)",emergencyCity:"City",emergencyState:"State",emergencyPostalCode:"Postal code",emergencySave:"Confirm location",emergencySaving:"Saving…",emergencyBack:"Back"},aiAgent:{loading:"Loading Managed VoiceAI agent…",loadFailed:"Failed to load Managed VoiceAI agent: {message}",fields:{name:"Name",namePlaceholder:"Front Desk Agent",nameHint:"Internal label shown in lists and call logs. Not heard by callers.",extensionNumber:"Extension",extensionNumberPlaceholder:"700",extensionNumberHint:"Dial this extension from any phone on the account to reach the agent.",extensionChecking:"Checking extension...",personaName:"Persona name",personaNamePlaceholder:"e.g. Receptionist",personaNameHint:"How the agent introduces itself on calls.",greetingName:"Greeting name",greetingNamePlaceholder:"Your business name",greetingNameHintWithName:'Used in the call greeting (e.g. "Thanks for calling {name}").',greetingNameHintGeneric:'Used in the call greeting (e.g. "Thanks for calling [your business]").',instructions:"Instructions",instructionsPlaceholder:"Provide additional instructions for how the Managed VoiceAI agent should behave during calls...",instructionsHint:"Plain-English guidance for the agent: tone, what to do, what to escalate.",faq:"FAQ",faqEmpty:"No FAQ entries yet. Add one to teach the agent a recurring question.",faqEntry:"Entry {index}",faqQuestion:"Question",faqAnswer:"Answer",faqQuestionLabel:"FAQ entry {index} question",faqAnswerLabel:"FAQ entry {index} answer",faqRemove:"Remove",faqRemoveLabel:"Remove FAQ entry {index}",faqAdd:"Add FAQ entry",scheduling:"Scheduling",schedulingHint:"Connect your Managed VoiceAI agent to an external scheduling system. Clear the URL to disable scheduling.",webhookUrl:"Webhook URL",webhookUrlHint:"Base URL for scheduling webhooks. DialStack appends tool-call paths automatically.",webhookUrlPlaceholder:"https://example.com/api/dialstack/webhooks",secret:"Webhook secret",secretHint:"Used to verify tool-call webhooks sent from this Managed VoiceAI agent to your integration.",copySecret:"Copy webhook secret",rotateSecret:"Rotate secret"},save:"Save",saving:"Saving…",saved:"Saved.",errors:{nameRequired:"Name is required.",nameMaxLength:"Name must be {max} characters or fewer.",personaNameMaxLength:"Persona name must be {max} characters or fewer.",greetingNameMaxLength:"Greeting name must be {max} characters or fewer.",instructionsMaxLength:"Instructions must be {max} characters or fewer.",faqMaxItems:"FAQ supports up to {max} entries.",faqIncompleteEntry:"Every FAQ entry needs both a question and an answer.",faqFieldMaxLength:"FAQ fields must be {max} characters or fewer.",extensionNumeric:"Extension must contain only digits.",extensionUnavailable:"Extension number is already in use.",schedulingUrlMaxLength:"Webhook URL must be {max} characters or fewer.",schedulingUrlHttpsRequired:"Webhook URL must start with https://.",hostCreateRequired:"This form is waiting for the host app to create the Managed VoiceAI agent.",hostSaveRequired:"This form is waiting for the host app to save the Managed VoiceAI agent."}},voicemails:{title:"Voicemails",loading:"Loading voicemails...",empty:"No voicemails",noUserId:"Please set a user ID to load voicemails",transcription:"Transcription",summary:"Summary",sentiment:"Sentiment",sentimentPositive:"Positive",sentimentNeutral:"Neutral",sentimentNegative:"Negative",sentimentMixed:"Mixed",transcript:"Full Transcript",transcriptLoading:"Loading transcript...",transcriptNotAvailable:"Transcript not available",deleteConfirm:"Delete this voicemail?",deleteTitle:"Delete Voicemail",progress:"Playback progress"},callLogs:{title:"Call Logs",loading:"Loading call logs...",empty:"No call logs found",columns:{date:"Date",direction:"Direction",from:"From",to:"To",duration:"Duration",status:"Status",quality:"MOS"},directions:{inbound:"Inbound",outbound:"Outbound",internal:"Internal"},routedTo:"Routed to:",calledBy:"Called by:",statuses:{completed:"Completed",noAnswer:"No Answer",busy:"Busy",failed:"Failed",voicemail:"Voicemail"},quality:{good:"Good",fair:"Fair",poor:"Poor",unavailable:"N/A",unavailableTooltip:"No quality data available"}},callHistory:{title:"Call History",loading:"Loading call history...",empty:"No call history",noPhoneNumber:"Please set a phone number to load call history",error:"Unable to load call history",clickToCall:"Click to call",summaryNotAvailable:"Summary not available",relativeTime:{justNow:"Just now",minuteAgo:"1 min ago",minutesAgo:"{count} min ago",hourAgo:"1 hour ago",hoursAgo:"{count} hours ago",yesterday:"Yesterday"}},phoneNumberOrdering:{title:"Order Phone Numbers",steps:{search:"Search",select:"Select",confirm:"Confirm",route:"Route",done:"Done",stepOf:"Step {current} of {total}"},search:{title:"Search Available Numbers",subtitle:"Find available phone numbers by entering an area code or ZIP code.",searchType:"Search by",areaCode:"Area Code",zip:"ZIP Code",areaCodeLabel:"Area Code",areaCodePlaceholder:"e.g. 212",zipLabel:"ZIP Code",zipPlaceholder:"e.g. 10001",numberOfResults:"Quantity to display",search:"Search"},results:{title:"Available Numbers",phoneNumber:"Phone Number",state:"State",selectAll:"Select all",selected:"{count} selected",noResults:"No numbers available for this search",continue:"Continue",backToSearch:"Back to Search"},confirm:{title:"Confirm Order",subtitleOne:"You are about to order 1 phone number",subtitleOther:"You are about to order {count} phone numbers",description:"Your order will be submitted to the carrier for fulfillment. This usually completes within seconds but may take longer.",placeOrder:"Place Order",continue:"Continue",back:"Back",billing:{label:"Billing impact",headline:"Adds {amount}/month to this account's bill",detail:"{count} phone numbers at {rate} each per month.",detail_one:"{count} phone number at {rate} per month.",detail_other:"{count} phone numbers at {rate} each per month.",timing:"Billing starts when each number activates.",taxesAndFees:"Taxes and fees are additional.",noPrice:"These numbers are billable on this account.",noPrice_one:"This number is billable on this account.",noPrice_other:"These numbers are billable on this account.",notBilled:"This account is not billed, so ordering these numbers costs nothing."}},route:{title:"Choose call routing",subtitle:"Pick where these numbers should send calls once they activate. You can change this any time, or set it up later.",later:"Set up routing later",laterHint:"Configure each number from its detail page after it activates.",noTargets:"No routing destinations exist yet. You can set up routing after the numbers are added.",unnamed:"Untitled",extension:"ext. {ext}",back:"Back",type:{user:"User",dial_plan:"Dial plan",voice_app:"Voice app",queue:"Queue",ring_group:"Ring group",shared_voicemail:"Shared voicemail"}},ordering:{title:"Placing Order..."},complete:{titlePendingOne:"Order Submitted",titlePendingOther:"Order Submitted",titleCompleteOne:"Number Ready",titleCompleteOther:"Numbers Ready",titlePartialOne:"Partially Fulfilled",titlePartialOther:"Partially Fulfilled",descriptionPendingOne:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",descriptionPendingOther:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",descriptionCompleteOne:"Your phone number is now in your inventory and ready to be configured.",descriptionCompleteOther:"Your phone numbers are now in your inventory and ready to be configured.",descriptionPartialOne:"Some numbers could not be fulfilled by the carrier.",descriptionPartialOther:"Some numbers could not be fulfilled by the carrier.",checking:"Checking order status...",assignmentHint:"Numbers added to your inventory still need to be assigned to an extension or dial plan before they can receive calls.",orderMore:"Order More Numbers"},error:{title:"Order Failed",description:"The carrier was unable to fulfill your order.",tryAgain:"Try Again"},statuses:{pending:"Pending",complete:"Complete",partial:"Partial",failed:"Failed"}},phoneNumbers:{title:"Phone Numbers",loading:"Loading phone numbers...",empty:"No phone numbers",filterLabel:"Filter by status",search:{placeholder:"Search phone numbers...",noResults:"No phone numbers match your search"},filters:{active:"Active",in_progress:"In Progress",cancelled:"Cancelled"},columns:{phoneNumber:"Phone Number",status:"Status",callerID:"Outbound Caller ID",callerIDPrefix:"Inbound Caller ID Prefix",outbound:"Usage",carrier:"Carrier",transferDate:"Transfer Date",routingTarget:"Call Routing",cancelledDate:"Date Cancelled"},statuses:{active:"Active",inactive:"Inactive",released:"Released",ordering:"Ordering",orderFailed:"Order Failed",portingDraft:"Port Draft",portingApproved:"Ready to Submit",portingSubmitted:"Port Submitted",portingException:"Port Issue",portingFoc:"Port Scheduled"},badges:{temporary:"Temporary"},outbound:{enabled:"Two-way",disabled:"Inbound only",fax:"Fax"},routingTarget:{notSet:"Not set",setAction:"Set routing",faxNotApplicable:"Not applicable"},routingTargetTypes:{user:"User",dialPlan:"Dial Plan",voiceApp:"Voice App",ringGroup:"Ring Group"}},accountOnboarding:{billing:{label:"Billing impact",headline:"Adds {amount}/month to this account's bill",detail:{userSeat:{one:"{count} user seat at {rate} per month.",other:"{count} user seats at {rate} each per month."},phoneNumber:{one:"{count} phone number at {rate} per month.",other:"{count} phone numbers at {rate} each per month."}},noPrice:{userSeat:{one:"Adds {count} billable user seat to this account.",other:"Adds {count} billable user seats to this account."},phoneNumber:{one:"Adds {count} billable phone number to this account.",other:"Adds {count} billable phone numbers to this account."}},rateHeadline:{userSeat:"{rate}/month per user seat",phoneNumber:"{rate}/month per phone number"},rateDetail:{userSeat:"Each team member you add is billed at this rate.",phoneNumber:"Each number you add is billed at this rate."},noPriceRate:{userSeat:"Each team member you add is billable on this account.",phoneNumber:"Each number you add is billable on this account."},startsOnActivation:"Billing starts when each number activates.",taxesAndFees:"Taxes and fees are additional.",notBilled:"This account is not billed, so this costs nothing."},title:"Account Onboarding",breadcrumbAriaLabel:"Onboarding progress",loading:"Loading...",error:{title:"Unable to Load",description:"Something went wrong loading the onboarding wizard.",retry:"Try Again"},steps:{account:"Account Setup",numbers:"Phone Numbers",hardware:"Hardware Setup",complete:"Complete"},sidebar:{businessDetails:"Business Details",businessDetailsDesc:"Enter your company information",teamMembers:"Team Members",teamMembersDesc:"Add users and assign extensions",numberOptions:"Number Options",numberOptionsDesc:"Choose to port existing or get new numbers",callerId:"Caller ID",callerIdDesc:"Set caller ID for your numbers",directoryListing:"Directory Listing",directoryListingDesc:"Configure 411 directory listing",numberSetup:"Number Setup",numberSetupDesc:"Configure your phone numbers",verification:"Verification",verificationDesc:"Verify number status",deviceAssignment:"Device Assignment",deviceAssignmentDesc:"Assign devices to users"},account:{title:"Business Details",subtitle:"Enter your company information",details:{heading:"Account Details",companyNameLabel:"Company Name",companyNamePlaceholder:"Acme Corp",companyNameRequired:"Company name is required",emailLabel:"Primary Contact Email",emailPlaceholder:"admin@company.com",emailRequired:"Primary contact email is required",emailInvalid:"Enter a valid email address",phoneLabel:"Primary Contact Phone Number",phonePlaceholder:"(555) 123-4567",phoneRequired:"Primary contact phone number is required",phoneInvalid:"Enter a valid US phone number",primaryContactLabel:"Primary Contact",primaryContactPlaceholder:"Jane Doe",primaryContactRequired:"Primary contact is required",regionLabel:"Region",regionPlaceholder:"Select a region",timezoneLabel:"Timezone",timezonePlaceholder:"Select a timezone",timezoneRequired:"Timezone is required"},users:{heading:"Team Members",description:"Add users who will have phone extensions. Administrators without phone service are listed too.",nameLabel:"Full name",namePlaceholder:"John Doe",nameRequired:"Name is required",emailLabel:"Email",emailPlaceholder:"john@company.com",extensionLabel:"Extension",extensionPlaceholder:"ex. 103",addUser:"Add User",removeUser:"Remove",removePhoneAccess:"Remove phone access",adminBadge:"Admin",noUsers:"No team members added yet.",atLeastOne:"Add at least one team member to continue.",duplicateEmail:"A user with this email already exists.",extensionRequired:"Extension is required",extensionTaken:"This extension is already in use. Choose another.",noPhoneService:"No phone service",givePhoneAccess:"Give phone access",givingPhoneAccess:"Adding…"},location:{heading:"Business Location",description:"Add your business address for E911 and caller ID.",nameLabel:"Location Name",namePlaceholder:"Main Office",nameRequired:"Location name is required",addressLabel:"Address",searchPlaceholder:"Start typing an address...",searching:"Searching...",noResults:"No addresses found",enterManually:"Enter manually",searchInstead:"Search instead",edit:"Edit",addressRequired:"Address is required",houseNumberLabel:"#",houseNumberPlaceholder:"123",streetLabel:"Street",streetPlaceholder:"Main St",cityLabel:"City",cityPlaceholder:"New York",stateLabel:"State",statePlaceholder:"Select",postalCodeLabel:"ZIP",postalCodePlaceholder:"10001"},saving:"Saving...",saveError:"Failed to save. Please try again."},numbers:{title:"Phone Numbers",subtitle:"Choose how you'd like to set up your business numbers",defaultDialPlanName:"Onboarding Dial Plan",callerId:{title:"Caller ID Setup",subtitle:"Configure the name displayed when making outbound calls",inputLabel:"Caller ID Name",inputPlaceholder:"e.g. ACME Corp",inputHelp:"Max 15 characters. Letters, numbers, spaces, and hyphens only.",charCount:"{count}/15",submit:"Set Caller ID",submitting:"Submitting...",submittingAll:"Submitting caller IDs...",submitted:"Submitted",alreadySet:"Already configured",submitAll:"Set All Caller IDs",skipCallerId:"Skip",partialError:"Some caller IDs could not be set. Fix errors and retry, or skip.",validation:{required:"Caller ID name is required",tooLong:"Must be 15 characters or fewer",invalidChars:"Only letters, numbers, spaces, and hyphens allowed"},error:{submitFailed:"Failed to set caller ID. Please try again.",conflict:"A caller ID update is already in progress for this number."},directoryListing:{title:"Directory Listing (DA/DL)",info:"To update your directory listing, contact {platformName} support."},noDIDs:"No active phone numbers to configure."},directoryListing:{title:"Directory Listing",subtitle:"A directory listing feeds your business information into online directories and data aggregators, helping customers find you. It also reduces the chance of your outbound calls being flagged as spam by call-screening apps.",selectPrompt:"Select which number should be listed:",noneOption:"None — skip directory listing",noDIDs:"No eligible phone numbers to configure.",businessName:"Business Name",businessNamePlaceholder:"Enter business name for listing",businessNameHelp:"The name shown in directory listings and used for caller verification. Max 200 characters.",validation:{nameRequired:"Business name is required for the directory listing."}},overview:{heading:"Your Numbers",empty:"No telephone numbers yet. Request new numbers or port your existing ones.",requestNew:"Request New Numbers",requestNewDesc:"Get new business phone numbers instantly. Choose from available numbers in your area.",portExisting:"Port Existing Number",portExistingDesc:"Transfer your current business number to {platformName}. This typically takes 5–10 business days.",phoneNumber:"Phone Number",type:"Type",status:"Status",source:"Source",temporaryBanner:"A temporary number has been assigned to your account while you set up your permanent numbers.",loadError:"Failed to load telephone numbers. Please try again.",retry:"Retry"},status:{active:"Active",inactive:"Inactive",released:"Released",ordering:"Ordering",order_failed:"Order Failed",porting_draft:"Port Draft",porting_submitted:"Port Submitted",porting_exception:"Port Exception",porting_foc:"Port Scheduled",porting_approved:"Ready to Submit"},source:{did:"Account",didTemporary:"Temporary",number_order:"New Order",port_order:"Port"},order:{searchTitle:"Search Available Numbers",searchSubtitle:"Find available numbers by entering an area code or ZIP code",searchByAreaCode:"Area Code",searchByZip:"ZIP Code",areaCodeLabel:"Area Code",areaCodePlaceholder:"212",zipLabel:"ZIP Code",zipPlaceholder:"10001",quantityLabel:"Quantity",search:"Search",searching:"Searching...",resultsTitle:"Available Numbers",resultsSubtitle:"Select the numbers you would like to order.",noResults:"No numbers found. Try a different search.",selectAll:"Select All",deselectAll:"Deselect All",selected:"selected",state:"State",confirmTitle:"Confirm Your Order",confirmSubtitle:"You are about to order {count} phone numbers",confirmSubtitle_one:"You are about to order {count} phone number",confirmSubtitle_other:"You are about to order {count} phone numbers",carrierNote:"Your order will be submitted to the carrier for fulfillment. This usually completes within seconds but may take longer.",placeOrder:"Place Order",placing:"Placing Order...",ordering:"Ordering...",statusTitle:"Order Submitted",statusPending:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",statusStalled:"Your order has been submitted to the carrier. Fulfillment usually completes within seconds but may take longer.",statusComplete:"Your numbers have been activated.",statusFailed:"The order could not be completed.",statusPartial:"Some numbers were activated, but others failed.",done:"Done",orderMore:"Order More Numbers",continue:"Continue",error:"An error occurred while placing the order."},port:{numbersTitle:"Numbers to Port",numbersSubtitle:"Enter the numbers you want to transfer to {platformName}, or paste a whole list into any row.",phoneLabel:"Phone Number",phonePlaceholder:"(555) 123-4567",addAnother:"Add another number",numberLabel:"Phone number {row}",removeNumber:"Remove phone number {row}",duplicateOfRow:"Duplicate of row {row}",pasteHint:"Press Enter for another row. Pasting a list — one per line, commas, or a spreadsheet column — fills a row for each number.",readyCountZero:"No numbers yet",readyCountOne:"{count} number ready",readyCountOther:"{count} numbers ready",needsAttentionOne:"{count} row needs attention before you can continue",needsAttentionOther:"{count} rows need attention before you can continue",reasonInvalid:"Not a valid US phone number",reasonNotUs:"Only US numbers can be ported",reasonTollFree:"Toll-free numbers cannot be ported",reasonAmbiguous:"Too many digits for one number — if this is several, put one per row",reasonHasExtension:"Remove the extension",maxPerOrder:"{count} numbers — the maximum is {max} per order. Move {excess} into a second port order.",notPortableWithDetail:"{label} ({detail})",accountLimit:"You've reached the number of phone numbers this account can hold. Contact support to raise the limit, then try again.",numbersUnavailable:"Some of these numbers are already in use and can't be ported. The ones affected are marked above.",conflictAlreadyOnAccount:"You already have this number",conflictInServiceElsewhere:"Already in service — contact support to transfer it",checkEligibility:"Check Eligibility",checking:"Checking...",eligibilityTitle:"Port Eligibility",eligibilitySubtitle:"Review which numbers can be ported.",portable:"Portable",notPortable:"Not Portable",carrier:"Current Carrier",wireless:"Wireless",wirelessYes:"Yes",wirelessNo:"No",accountRequired:"Account # Required",continueWithPortable:"Continue with Portable Numbers",noPortable:"None of the entered numbers are eligible for porting.",subscriberTitle:"Subscriber Information",subscriberSubtitle:"Enter the details exactly as they appear on your current phone bill.",btnLabel:"Billing Telephone Number (BTN)",btnPlaceholder:"(555) 123-4567",businessNameLabel:"Business Name",businessNamePlaceholder:"Acme Corp",approverNameLabel:"Authorized Contact",approverNamePlaceholder:"John Doe",accountNumberLabel:"Account Number",accountNumberPlaceholder:"From your current carrier",pinLabel:"Account PIN",pinPlaceholder:"1234",addressHeading:"Service Address",houseNumberLabel:"Street Number",houseNumberPlaceholder:"123",streetNameLabel:"Street Name",streetNamePlaceholder:"Main St",line2Label:"Suite / Unit",line2Placeholder:"Suite 100",cityLabel:"City",cityPlaceholder:"New York",stateLabel:"State",statePlaceholder:"Select state",zipLabel:"ZIP Code",zipPlaceholder:"10001",focTitle:"Requested Port Date",focSubtitle:"Choose when you want the numbers transferred. Must be at least 5 business days out.",focDateLabel:"Port Date",focTimeLabel:"Port Time ({zone})",focTimePlaceholder:"Select time",documentsTitle:"Supporting Documents",documentsSubtitle:"Upload your latest phone bill and optionally a Customer Service Record (CSR).",billCopyLabel:"Phone Bill Copy",billCopyDesc:"A recent bill from your current carrier showing the numbers to be ported.",billCopyRequired:"Required",csrLabel:"Customer Service Record (CSR)",csrDesc:"Optional but recommended — speeds up the porting process.",csrOptional:"Optional",uploadFile:"Choose File",fileSelected:"Selected:",noFileSelected:"No file selected",uploading:"Uploading...",reviewTitle:"Review & Approve",reviewSubtitle:"Verify all details before submitting your port request.",numbersSection:"Numbers",subscriberSection:"Subscriber",focSection:"Port Date",documentsSection:"Documents",signatureLabel:"Electronic Signature",signaturePlaceholder:"Type your full legal name",signatureHelp:"By signing, you authorize the transfer of the listed numbers to {platformName}.",approve:"Approve & Submit",submitting:"Submitting...",submittedTitle:"Port Request Submitted",submittedSubtitle:"Your port request has been submitted and is being processed.",submittedStatus:"Status",backToOverview:"Back to Numbers",carrierGroupsTitle:"Carrier Groups",carrierGroupsSubtitle:"Your numbers are with different carriers. Each carrier requires a separate port request.",carrierStart:"Start",carrierContinue:"Continue",carrierSubmitted:"Submitted",numberSingular:"number",numberPlural:"numbers"},validation:{areaCodeRequired:"Area code is required.",areaCodeFormat:"Enter a 3-digit area code.",cityRequired:"City is required.",stateRequired:"State is required.",zipRequired:"ZIP code is required.",zipFormat:"Enter a 5-digit ZIP code.",selectAtLeastOne:"Select at least one number.",phoneRequired:"At least one phone number is required.",phoneInvalid:"Enter a valid US phone number.",phoneDuplicate:"This number has already been entered.",btnRequired:"BTN is required.",btnInvalid:"Enter a valid US phone number.",businessNameRequired:"Business name is required.",approverNameRequired:"Authorized contact name is required.",houseNumberRequired:"Street number is required.",streetNameRequired:"Street name is required.",focDateRequired:"Port date is required.",focDateTooSoon:"Port date must be at least 5 business days from today.",focDateTooFar:"Port date must be within 30 days.",focTimeRequired:"Port time is required.",focTimeOutOfWindow:"Choose a time between {start} and {end} {zone}.",billCopyRequired:"A phone bill copy is required.",signatureRequired:"Signature is required.",eligibilityError:"Failed to check eligibility. Please try again.",submitError:"Failed to submit port request. Please try again."},nav:{back:"Back",next:"Next",cancel:"Cancel",backToSearch:"Back to Search",confirm:"Confirm"},gate:{noDIDsAvailable:"You need at least one phone number before selecting a primary number. Order or port a number first.",primaryRequired:"Please select a primary number to continue."}},hardware:{title:"Assign Devices",shippingAddress:"Shipping Address",subtitle:"Drag and drop devices to assign them to team members",noUsers:"No team members found. Add team members in the Account step first.",noDevices:"No devices are available for your account at the moment.",isDectBase:"This is a cordless handset base station",userLabel:"Team Member",selectUser:"Select a team member",selectUserRequired:"Please select a team member.",macLabel:"MAC Address",macPlaceholder:"00:04:13:AA:BB:CC",invalidMac:"Enter a valid 12-digit MAC address.",ipeiLabel:"Handset IPEI",ipeiPlaceholder:"03AABB1234567890CCDD",invalidIpei:"Enter a valid IPEI (hex digits only).",ipeiNotMac:"This looks like a MAC address, not an IPEI. An IPEI looks like 03AABB1234567890CCDD.",removeDevice:"Remove",unsupportedVendor:"This device is not currently supported. Our support team has been notified and will follow up.",duplicateMac:"This MAC address is already registered.",deviceNotFound:"Device was created but could not be found. Please try again.",handset:"handset",handsets:"handsets",addDeviceButton:"+ Add Device",addHandsetButton:"+ Handset",save:"Save",saving:"Saving...",cancel:"Cancel",dectBase:"Cordless Base",removeBaseFailed:"Failed to remove cordless base.",tableHeaderName:"Full name",tableHeaderExtension:"Extension",tableHeaderDevice:"Assigned Device",availableDevices:"Available Devices",allAssigned:"All devices have been assigned",dragDropHint:"Drag and drop device here",clickToAssign:"Click to assign",submitOrder:"Submit Order",assignAndComplete:"Save & Continue",unassign:"Unassign",deskPhone:"Desk phone",cordless:"Cordless",submitting:"Submitting...",gate:{noDevices:"No devices are available for your account. Please contact support to add devices before completing this step."}},complete:{title:"Wahoo!",subtitle:"It's time to start using your embedded voice system",e911:{loading:"Configuring emergency services...",pollingStatus:"Verifying emergency services registration...",verified:"E911 emergency address is verified.",processing:"E911 registration is being processed. This may take a few minutes.",pendingAfterPolling:"E911 registration submitted. Your phone service is active — emergency address verification will complete shortly.",addressStandardized:"Your address was standardized for emergency services accuracy.",primaryAssigned:"assigned as primary number for",errorTitle:"E911 configuration failed",errorDescription:"There was an error configuring emergency services. You can retry or configure manually later.",retryButton:"Retry",deferred:"E911 emergency services have not been fully configured. Each location with a phone number needs a verified emergency address before your phone service can be activated."}},stepComplete:{title:"{stepName} Complete",subtitle:"This step has been completed successfully.",done:"Done"},nav:{next:"Next",skip:"Skip",back:"Back",exit:"Finish"},legal:{prefix:"By continuing, you agree to the",and:"and",termsOfService:"Terms of Service",recipientTerms:"Recipient Terms of Service",privacyPolicy:"Privacy Policy"},ssa:{title:"Review and accept your subscription agreement",intro:"Before you can use your phone service, please review the Service Subscription Agreement below — including its emergency calling (911/E911) terms — and confirm your acceptance.",pricingTitle:"Your plan pricing",perUser:"Per user",perNumber:"Per phone number",perAiLocation:"Managed VoiceAI, per location",perMonthSuffix:"/mo",agreementLabel:"Service Subscription Agreement",openInNewTab:"Open the full agreement in a new tab",accept:"Accept & Continue",submitting:"Recording your acceptance…",notPermitted:"Only the account owner can accept this agreement. Please ask them to sign in and accept it — phone service requires their signature.",errors:{stale:"The agreement was updated. Please review the latest version and accept again.",pricingMissing:"Your plan pricing has not been finalized yet. Please contact your provider to continue.",generic:"We could not record your acceptance. Please try again.",retry:"Try again"},loadError:{title:"Unable to load your agreement",description:"We could not load your subscription agreement, which is required before you can continue. Please try again.",retry:"Try again",retrying:"Loading…"}}},onboardingPortal:{onboardingFlows:"ONBOARDING FLOWS",saveAndExit:"Save & Exit to Overview",back:"Back",helpSupport:"Help & Support",onboardingComplete:"Onboarding complete",rates:{title:"Your monthly rates",subtitle:"What you're billed at today.",perUser:"Per user",perPhoneNumber:"Per phone number",perVoiceAiLocation:"Managed VoiceAI, per location",voiceAiPerLocationNote:"Charged for every location once Managed VoiceAI is active.",perMonth:"{rate}/month",rateNotSet:"Not set",pendingRate:"{rate}/month from {date}",pendingNote:"Rate changes take effect at the start of the next billing period.",taxesAndFees:"Taxes and fees are additional.",notBilled:"This account is not billed.",noRates:"No rates are set for this account yet.",unavailable:"Rates are unavailable right now."},overview:{label:"Overview",title:"Your Business Onboarding",subtitle:"Complete the steps below to set up your business phone system",progressTitle:"Onboarding Progress",flowsComplete:"{completed} of {total} flows complete",stepsTitle:"Onboarding Steps",complete:"Complete",progress:"Progress",completeSetup:"Complete Setup",continueSetup:"Continue Setup",review:"Review",needHelp:"Need help?",needHelpSubtitle:"Our team is here to help you get set up quickly",scheduleCall:"Schedule a Call",viewDocs:"View Documentation",accountDesc:"Set up your business profile, add team members, and configure your dial plan",numbersDesc:"Port existing numbers or request new business lines",hardwareDesc:"Assign phones to team members and track delivery",phoneStatusTitle:"Phone number status",phoneStatusSubtitle:"Track the status of your phone numbers",phoneStatusNumber:"Phone Number",phoneStatusType:"Type",phoneStatusStatus:"Status",phoneStatusTypeNew:"New",phoneStatusTypePort:"Port",phoneStatusProcessing:"Processing",phoneStatusComplete:"Complete",phoneStatusTemporary:"Temporary"},splash:{title:"Welcome\nto {platformName}",subtitle:"Let's get your business set up in 3 easy steps",start:"Start Onboarding",step1:"Account Details",step2:"Setup Phone Numbers",step3:"Assign Hardware"}},dialPlan:{title:"Dial Plan",loading:"Loading dial plan...",error:"Failed to load dial plan",empty:"No dial plan found",nodeTypes:{start:"Start",schedule:"Schedule",internalDial:"Internal Extension",voicemail:"Voicemail",externalDial:"External Number",voiceApp:"Voice App",menu:"IVR Menu",audioClip:"Audio Clip",hangUp:"Hang Up"},nodeDescriptions:{menu:"Play prompt and route by keypress",audioClip:"Play an audio clip",hangUp:"End the call"},exits:{open:"Open",closed:"Closed",holiday:"Holiday",next:"Next",timeout:"Timeout",invalid:"Invalid"},configLabels:{promptClip:"Prompt",audioClip:"Audio Clip",digit:"Digit",options:"Options",addOption:"Add Option",removeOption:"Remove",optionLabel:"Label",optionLabelPlaceholder:"e.g. Sales",routeHolidaySeparately:"Route holidays separately",routeHolidaySeparatelyHint:"When on, holidays route to a dedicated branch you wire below. Otherwise holidays follow the Closed exit."},resourceGroups:{audioClips:"Audio Clips"}}},f=v;
|
|
5783
5859
|
|
|
5784
5860
|
const SoftphoneContext = createContext(null);
|
|
5785
5861
|
// Stands in for the phone while `usePhone` has none — before the first construct
|