@forgeroute/ui 0.4.78 → 0.4.79

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.
@@ -1,7 +1,7 @@
1
1
  import * as i0 from "@angular/core";
2
2
  import { ChangeDetectionStrategy, Component, DestroyRef, ElementRef, Injectable, InjectionToken, Injector, PLATFORM_ID, ViewEncapsulation, afterNextRender, computed, effect, forwardRef, inject, input, model, output, signal, untracked, viewChild } from "@angular/core";
3
+ import { AlertComponent, BadgeComponent, ButtonComponent, DetailCardComponent, FormRowComponent, FormSectionComponent, HintComponent, KpiCardComponent, ModalComponent, PAYMENT_METHOD_PLUGIN, PaymentMethodPlugin, SkeletonComponent, StackComponent, TextComponent, TextInputComponent, UiLabelsService, callHost, formatCurrency, safeLocale, uiLocale, uiText } from "@forgeroute/ui";
3
4
  import { DOCUMENT, NgTemplateOutlet, isPlatformBrowser } from "@angular/common";
4
- import { AlertComponent, BadgeComponent, ButtonComponent, DetailCardComponent, FormRowComponent, FormSectionComponent, HintComponent, KpiCardComponent, ModalComponent, PAYMENT_METHOD_PLUGIN, PaymentMethodPlugin, SkeletonComponent, StackComponent, TextComponent, TextInputComponent, callHost, formatCurrency } from "@forgeroute/ui";
5
5
  import * as i1 from "@angular/forms";
6
6
  import { FormsModule } from "@angular/forms";
7
7
  import { takeUntilDestroyed } from "@angular/core/rxjs-interop";
@@ -98,23 +98,25 @@ const STRIPE_TECHNICAL_ERROR_MESSAGES = {
98
98
  invalid_request_error: "Something went wrong while processing the payment. Please try again."
99
99
  };
100
100
  const STRIPE_DEFAULT_ERROR_MESSAGE = "Payment failed. Please try again.";
101
- const STRIPE_SESSION_EXPIRED_MESSAGE = "Your payment session has expired. Please refresh the page and try again.";
101
+ function localizedTable(english, prefix) {
102
+ return Object.fromEntries(Object.keys(english).map((code) => [code, uiText(`${prefix}${code}`)]));
103
+ }
102
104
  function getStripeErrorMessage(error, options = {}) {
103
- const fallback = options.fallback ?? "Payment failed. Please try again.";
105
+ const fallback = options.fallback ?? uiText("stripeErrors.defaultMessage");
104
106
  if (!error) return fallback;
105
107
  if (options.display === "stripe") return error.message || fallback;
106
108
  const table = {
107
- ...STRIPE_ERROR_MESSAGES,
109
+ ...localizedTable(STRIPE_ERROR_MESSAGES, "stripeErrors."),
108
110
  ...options.overrides ?? {}
109
111
  };
110
112
  if (error.decline_code && table[error.decline_code]) return table[error.decline_code];
111
113
  if (error.code && table[error.code]) return table[error.code];
112
114
  const message = error.message;
113
115
  if (message) {
114
- if (message.includes("already succeeded") || message.includes("previously confirmed")) return options.overrides?.["payment_intent_unexpected_state"] ?? "This payment has already been processed. Please refresh the page and try again.";
115
- if (message.includes("expired")) return STRIPE_SESSION_EXPIRED_MESSAGE;
116
+ if (message.includes("already succeeded") || message.includes("previously confirmed")) return options.overrides?.["payment_intent_unexpected_state"] ?? uiText("stripeErrors.alreadyProcessed");
117
+ if (message.includes("expired")) return uiText("stripeErrors.sessionExpired");
116
118
  }
117
- const technical = options.display === "table" || !error.type ? void 0 : STRIPE_TECHNICAL_ERROR_MESSAGES[error.type];
119
+ const technical = options.display === "table" || !error.type || !(error.type in STRIPE_TECHNICAL_ERROR_MESSAGES) ? void 0 : uiText(`stripeErrors.technical.${error.type}`);
118
120
  if (technical) return technical;
119
121
  return message || fallback;
120
122
  }
@@ -182,10 +184,34 @@ function failureFromError(error, stage, options = {}) {
182
184
  ...error ? { error } : {}
183
185
  };
184
186
  }
187
+ const KNOWN_MESSAGE_KEYS = {
188
+ "Payment system not initialized": "stripePayment.msg.notInitialized",
189
+ "Failed to create payment intent": "stripePayment.msg.intentFailed",
190
+ "Payment was not completed": "stripePayment.msg.notCompleted",
191
+ "Payment failed. Please try a different payment method.": "stripePayment.msg.requiresPaymentMethod",
192
+ "No payment method returned from Stripe": "stripePayment.msg.noPaymentMethod",
193
+ "Payment authentication failed": "stripePayment.msg.authFailed",
194
+ "Payment authentication was not completed": "stripePayment.msg.authNotCompleted",
195
+ "A Stripe publishable key is required": "stripePayment.msg.keyMissing",
196
+ "Failed to load Stripe": "stripePayment.msg.loadFailed",
197
+ "Verification failed": "stripePayment.msg.verifyFailed",
198
+ "Verification failed. Please check the code and try again.": "stripePayment.msg.verifyThrown",
199
+ "We could not check the status of this payment. Please contact support before trying again.": "stripePayment.msg.returnFailed",
200
+ "Payment method setup was incomplete. Please try again.": "stripePayment.msg.setupIncomplete",
201
+ "Payment authentication failed. Please try a different payment method.": "stripePayment.msg.authFailedTryOther",
202
+ "Card payments are not available right now.": "stripePayment.msg.cardsUnavailable",
203
+ "Failed to initialize payment. Please try again.": "stripePayment.msg.initFailed",
204
+ "Could not calculate the fees. Please try again.": "stripePayment.msg.feesFailed",
205
+ "Payment failed. Please try again.": "stripeErrors.defaultMessage"
206
+ };
207
+ function localizeStripeMessage(message) {
208
+ const key = KNOWN_MESSAGE_KEYS[message];
209
+ return key ? uiText(key) : message;
210
+ }
185
211
  function failure(code, message, stage, stripeMessage = "") {
186
212
  return {
187
213
  code,
188
- message,
214
+ message: localizeStripeMessage(message),
189
215
  stripeMessage,
190
216
  stage
191
217
  };
@@ -397,21 +423,40 @@ function readStripeAppearance(doc, element = doc.documentElement) {
397
423
  };
398
424
  }
399
425
  const STRIPE_A11Y_MESSAGES = {
400
- loading: "Loading payment form",
401
- savingMethod: "Saving payment method",
402
- processingPayment: "Processing payment",
403
- methodSaved: "Payment method saved",
404
- paymentReceived: "Payment received",
405
- paymentProcessing: "Payment is processing",
406
- paymentAuthorized: "Payment authorized",
407
- verificationNeeded: "Bank account added. It needs to be verified with small deposits.",
408
- actionRequired: "Further action is required to complete the payment"
426
+ get loading() {
427
+ return uiText("stripePayment.a11y.loading");
428
+ },
429
+ get savingMethod() {
430
+ return uiText("stripePayment.a11y.savingMethod");
431
+ },
432
+ get processingPayment() {
433
+ return uiText("stripePayment.a11y.processingPayment");
434
+ },
435
+ get methodSaved() {
436
+ return uiText("stripePayment.a11y.methodSaved");
437
+ },
438
+ get paymentReceived() {
439
+ return uiText("stripePayment.a11y.paymentReceived");
440
+ },
441
+ get paymentProcessing() {
442
+ return uiText("stripePayment.a11y.paymentProcessing");
443
+ },
444
+ get paymentAuthorized() {
445
+ return uiText("stripePayment.a11y.paymentAuthorized");
446
+ },
447
+ get verificationNeeded() {
448
+ return uiText("stripePayment.a11y.verificationNeeded");
449
+ },
450
+ get actionRequired() {
451
+ return uiText("stripePayment.a11y.actionRequired");
452
+ }
409
453
  };
410
454
  const STRIPE_ACH_NOTICE = "Signing in to your bank account lets you pay right away. Entering your routing and account numbers instead requires verification with two small deposits, which typically take a couple of days to arrive in your account.";
411
455
  let nextId = 0;
412
456
  const jsonEqual = (a, b) => JSON.stringify(a) === JSON.stringify(b);
413
457
  var StripePaymentComponent = class StripePaymentComponent {
414
458
  constructor() {
459
+ this.labels = inject(UiLabelsService);
415
460
  this.loader = inject(STRIPE_LOADER);
416
461
  this.defaults = inject(STRIPE_PAYMENT_DEFAULTS);
417
462
  this.doc = inject(DOCUMENT);
@@ -448,12 +493,20 @@ var StripePaymentComponent = class StripePaymentComponent {
448
493
  this.showSubmit = input(true, ...ngDevMode ? [{ debugName: "showSubmit" }] : /* istanbul ignore next */ []);
449
494
  this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
450
495
  this.pending = input(false, ...ngDevMode ? [{ debugName: "pending" }] : /* istanbul ignore next */ []);
451
- this.label = input("Payment details", ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
496
+ this.labelInput = input(null, {
497
+ ...ngDevMode ? { debugName: "labelInput" } : /* istanbul ignore next */ {},
498
+ alias: "label"
499
+ });
500
+ this.label = computed(() => this.labelInput() ?? this.labels.t("stripeStripePayment.label"), ...ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []);
452
501
  this.required = input(false, ...ngDevMode ? [{ debugName: "required" }] : /* istanbul ignore next */ []);
453
502
  this.mountId = input("", ...ngDevMode ? [{ debugName: "mountId" }] : /* istanbul ignore next */ []);
454
503
  this.mountClass = input("", ...ngDevMode ? [{ debugName: "mountClass" }] : /* istanbul ignore next */ []);
455
504
  this.showAchNotice = input(true, ...ngDevMode ? [{ debugName: "showAchNotice" }] : /* istanbul ignore next */ []);
456
- this.achNotice = input(STRIPE_ACH_NOTICE, ...ngDevMode ? [{ debugName: "achNotice" }] : /* istanbul ignore next */ []);
505
+ this.achNoticeInput = input(null, {
506
+ ...ngDevMode ? { debugName: "achNoticeInput" } : /* istanbul ignore next */ {},
507
+ alias: "achNotice"
508
+ });
509
+ this.achNotice = computed(() => this.achNoticeInput() ?? this.labels.t("stripePayment.achNotice"), ...ngDevMode ? [{ debugName: "achNotice" }] : /* istanbul ignore next */ []);
457
510
  this.achNoticeTestId = input("stripe-ach-notice", ...ngDevMode ? [{ debugName: "achNoticeTestId" }] : /* istanbul ignore next */ []);
458
511
  this.initialPaymentMethodType = input("card", ...ngDevMode ? [{ debugName: "initialPaymentMethodType" }] : /* istanbul ignore next */ []);
459
512
  this.showErrors = input(true, ...ngDevMode ? [{ debugName: "showErrors" }] : /* istanbul ignore next */ []);
@@ -462,7 +515,11 @@ var StripePaymentComponent = class StripePaymentComponent {
462
515
  this.errorFallback = input("", ...ngDevMode ? [{ debugName: "errorFallback" }] : /* istanbul ignore next */ []);
463
516
  this.errorFallbackByStage = input(null, ...ngDevMode ? [{ debugName: "errorFallbackByStage" }] : /* istanbul ignore next */ []);
464
517
  this.errorMessages = input(null, ...ngDevMode ? [{ debugName: "errorMessages" }] : /* istanbul ignore next */ []);
465
- this.loadErrorMessage = input("Failed to load the payment form. Please try again.", ...ngDevMode ? [{ debugName: "loadErrorMessage" }] : /* istanbul ignore next */ []);
518
+ this.loadErrorMessageInput = input(null, {
519
+ ...ngDevMode ? { debugName: "loadErrorMessageInput" } : /* istanbul ignore next */ {},
520
+ alias: "loadErrorMessage"
521
+ });
522
+ this.loadErrorMessage = computed(() => this.loadErrorMessageInput() ?? this.labels.t("stripeStripePayment.loadErrorMessage"), ...ngDevMode ? [{ debugName: "loadErrorMessage" }] : /* istanbul ignore next */ []);
466
523
  this.a11yMessages = input(null, ...ngDevMode ? [{ debugName: "a11yMessages" }] : /* istanbul ignore next */ []);
467
524
  this.stripeReady = output();
468
525
  this.ready = output();
@@ -483,7 +540,7 @@ var StripePaymentComponent = class StripePaymentComponent {
483
540
  this.mountRef = viewChild("mount", ...ngDevMode ? [{ debugName: "mountRef" }] : /* istanbul ignore next */ []);
484
541
  this.mountHidden = computed(() => !this.mountOnly() && (this.loading() || this.pending() || !!this.loadErrorText()), ...ngDevMode ? [{ debugName: "mountHidden" }] : /* istanbul ignore next */ []);
485
542
  this.achNoticeVisible = computed(() => this.showAchNotice() && this.selectedType() === "us_bank_account", ...ngDevMode ? [{ debugName: "achNoticeVisible" }] : /* istanbul ignore next */ []);
486
- this.effectiveSubmitLabel = computed(() => this.submitLabel() || (this.mode() === "setup" ? "Save payment method" : "Pay"), ...ngDevMode ? [{ debugName: "effectiveSubmitLabel" }] : /* istanbul ignore next */ []);
543
+ this.effectiveSubmitLabel = computed(() => this.submitLabel() || (this.mode() === "setup" ? this.labels.t("stripePayment.saveMethod") : this.labels.t("stripePayment.pay")), ...ngDevMode ? [{ debugName: "effectiveSubmitLabel" }] : /* istanbul ignore next */ []);
487
544
  this.submitDisabled = computed(() => this.disabled() || this.loading() || this.pending() || !this.isReady() || !!this.loadErrorText(), ...ngDevMode ? [{ debugName: "submitDisabled" }] : /* istanbul ignore next */ []);
488
545
  this.messages = computed(() => {
489
546
  const given = Object.fromEntries(Object.entries(this.a11yMessages() ?? {}).filter(([, text]) => typeof text === "string"));
@@ -917,7 +974,7 @@ var StripePaymentComponent = class StripePaymentComponent {
917
974
  return;
918
975
  }
919
976
  if (!connection.key) {
920
- this.loadFailed(MSG_KEY_MISSING, "");
977
+ this.loadFailed(localizeStripeMessage(MSG_KEY_MISSING), "");
921
978
  return;
922
979
  }
923
980
  this.loading.set(true);
@@ -928,7 +985,7 @@ var StripePaymentComponent = class StripePaymentComponent {
928
985
  const stripe = await this.loader(connection.key, connection.options);
929
986
  if (generation !== this.generation) return;
930
987
  if (!stripe) {
931
- this.loadFailed(MSG_LOAD_FAILED, "");
988
+ this.loadFailed(localizeStripeMessage(MSG_LOAD_FAILED), "");
932
989
  return;
933
990
  }
934
991
  this.stripe = stripe;
@@ -964,7 +1021,7 @@ var StripePaymentComponent = class StripePaymentComponent {
964
1021
  });
965
1022
  element.on("loaderror", (event) => {
966
1023
  if (generation !== this.generation) return;
967
- const message = event?.error?.message || "Failed to load Stripe";
1024
+ const message = event?.error?.message || localizeStripeMessage("Failed to load Stripe");
968
1025
  this.loadFailed(message, event?.error?.message ?? "");
969
1026
  });
970
1027
  element.mount(container);
@@ -975,7 +1032,7 @@ var StripePaymentComponent = class StripePaymentComponent {
975
1032
  });
976
1033
  } catch (err) {
977
1034
  if (generation !== this.generation) return;
978
- this.loadFailed(messageOfThrown(err, MSG_LOAD_FAILED), messageOfThrown(err, ""));
1035
+ this.loadFailed(localizeStripeMessage(messageOfThrown(err, MSG_LOAD_FAILED)), messageOfThrown(err, ""));
979
1036
  }
980
1037
  }
981
1038
  applyDefaultValues(defaultValues) {
@@ -1238,8 +1295,8 @@ var StripePaymentComponent = class StripePaymentComponent {
1238
1295
  isRequired: false,
1239
1296
  transformFunction: null
1240
1297
  },
1241
- label: {
1242
- classPropertyName: "label",
1298
+ labelInput: {
1299
+ classPropertyName: "labelInput",
1243
1300
  publicName: "label",
1244
1301
  isSignal: true,
1245
1302
  isRequired: false,
@@ -1273,8 +1330,8 @@ var StripePaymentComponent = class StripePaymentComponent {
1273
1330
  isRequired: false,
1274
1331
  transformFunction: null
1275
1332
  },
1276
- achNotice: {
1277
- classPropertyName: "achNotice",
1333
+ achNoticeInput: {
1334
+ classPropertyName: "achNoticeInput",
1278
1335
  publicName: "achNotice",
1279
1336
  isSignal: true,
1280
1337
  isRequired: false,
@@ -1336,8 +1393,8 @@ var StripePaymentComponent = class StripePaymentComponent {
1336
1393
  isRequired: false,
1337
1394
  transformFunction: null
1338
1395
  },
1339
- loadErrorMessage: {
1340
- classPropertyName: "loadErrorMessage",
1396
+ loadErrorMessageInput: {
1397
+ classPropertyName: "loadErrorMessageInput",
1341
1398
  publicName: "loadErrorMessage",
1342
1399
  isSignal: true,
1343
1400
  isRequired: false,
@@ -1775,7 +1832,7 @@ i0.ɵɵngDeclareClassMetadata({
1775
1832
  required: false
1776
1833
  }]
1777
1834
  }],
1778
- label: [{
1835
+ labelInput: [{
1779
1836
  type: i0.Input,
1780
1837
  args: [{
1781
1838
  isSignal: true,
@@ -1815,7 +1872,7 @@ i0.ɵɵngDeclareClassMetadata({
1815
1872
  required: false
1816
1873
  }]
1817
1874
  }],
1818
- achNotice: [{
1875
+ achNoticeInput: [{
1819
1876
  type: i0.Input,
1820
1877
  args: [{
1821
1878
  isSignal: true,
@@ -1887,7 +1944,7 @@ i0.ɵɵngDeclareClassMetadata({
1887
1944
  required: false
1888
1945
  }]
1889
1946
  }],
1890
- loadErrorMessage: [{
1947
+ loadErrorMessageInput: [{
1891
1948
  type: i0.Input,
1892
1949
  args: [{
1893
1950
  isSignal: true,
@@ -1938,24 +1995,50 @@ i0.ɵɵngDeclareClassMetadata({
1938
1995
  }
1939
1996
  });
1940
1997
  const MICRODEPOSIT_COPY = {
1941
- title: "Bank account waiting for verification",
1942
- processingTitle: "Bank account being confirmed",
1943
- processing: "Your bank is confirming this account; this usually takes up to a few business days. We will email you when it is ready.",
1944
- cannotPay: "Until then this account can't be used to pay invoices.",
1945
- readOnly: "An administrator of your organization can finish the verification.",
1946
- keepsActive: "Your current payment method stays active until the new bank account is verified.",
1947
- cancelTitle: "Cancel verification",
1948
- verifyLabel: "Verify bank account",
1949
- cancelBase: "Cancel the verification of this bank account? It will not be saved as a payment method and you can add it again later.",
1950
- cancelKeepsActive: " Your current payment method stays active.",
1951
- cancelNoOther: " You have no other payment method saved.",
1952
- tooManyAttempts: "Too many failed attempts. Please try again later or contact support.",
1953
- codeRequired: "Enter the 6-character code."
1998
+ get title() {
1999
+ return uiText("stripeMicrodepositVerify.title");
2000
+ },
2001
+ get processingTitle() {
2002
+ return uiText("stripeMicrodepositVerify.processingTitle");
2003
+ },
2004
+ get processing() {
2005
+ return uiText("stripeMicrodepositVerify.processing");
2006
+ },
2007
+ get cannotPay() {
2008
+ return uiText("stripeMicrodepositVerify.cannotPay");
2009
+ },
2010
+ get readOnly() {
2011
+ return uiText("stripeMicrodepositVerify.readOnly");
2012
+ },
2013
+ get keepsActive() {
2014
+ return uiText("stripeMicrodepositVerify.keepsActive");
2015
+ },
2016
+ get cancelTitle() {
2017
+ return uiText("stripeMicrodepositVerify.cancelTitle");
2018
+ },
2019
+ get verifyLabel() {
2020
+ return uiText("stripeMicrodepositVerify.verifyLabel");
2021
+ },
2022
+ get cancelBase() {
2023
+ return uiText("stripeMicrodepositVerify.cancelBase");
2024
+ },
2025
+ get cancelKeepsActive() {
2026
+ return uiText("stripeMicrodepositVerify.cancelKeepsActive");
2027
+ },
2028
+ get cancelNoOther() {
2029
+ return uiText("stripeMicrodepositVerify.cancelNoOther");
2030
+ },
2031
+ get tooManyAttempts() {
2032
+ return uiText("stripeMicrodepositVerify.tooManyAttempts");
2033
+ },
2034
+ get codeRequired() {
2035
+ return uiText("stripeMicrodepositVerify.codeRequired");
2036
+ }
1954
2037
  };
1955
2038
  function microdepositArrivalText(iso) {
1956
2039
  if (!iso) return "";
1957
2040
  const date = new Date(iso);
1958
- return Number.isNaN(date.getTime()) ? "" : date.toLocaleDateString("en-US", {
2041
+ return Number.isNaN(date.getTime()) ? "" : date.toLocaleDateString(safeLocale(uiLocale()), {
1959
2042
  month: "long",
1960
2043
  day: "numeric",
1961
2044
  year: "numeric",
@@ -1965,16 +2048,16 @@ function microdepositArrivalText(iso) {
1965
2048
  function depositAmountError(value) {
1966
2049
  if (value === "" || value === null || value === void 0) return "";
1967
2050
  const n = Number(value);
1968
- if (!Number.isInteger(n)) return "Enter whole cents, for example 32.";
1969
- if (n < 1 || n > 99) return "Enter a number of cents from 1 to 99.";
2051
+ if (!Number.isInteger(n)) return uiText("stripeMicrodepositVerify.wholeCents");
2052
+ if (n < 1 || n > 99) return uiText("stripeMicrodepositVerify.centsRange");
1970
2053
  return "";
1971
2054
  }
1972
2055
  const normalizeDescriptorCode = (value) => (value ?? "").trim().toUpperCase();
1973
2056
  function descriptorCodeError(value, requireSmPrefix = false) {
1974
2057
  const code = normalizeDescriptorCode(value);
1975
2058
  if (!code) return "";
1976
- if (!/^[A-Z0-9]{6}$/.test(code)) return "The code has 6 letters or numbers.";
1977
- if (requireSmPrefix && !/^SM[A-Z0-9]{4}$/.test(code)) return "Descriptor code must start with \"SM\" followed by 4 characters (e.g., SMXXXX)";
2059
+ if (!/^[A-Z0-9]{6}$/.test(code)) return uiText("stripeMicrodepositVerify.code6");
2060
+ if (requireSmPrefix && !/^SM[A-Z0-9]{4}$/.test(code)) return uiText("stripeMicrodepositVerify.codeSm");
1978
2061
  return "";
1979
2062
  }
1980
2063
  function safeHostedUrl(url) {
@@ -1982,29 +2065,37 @@ function safeHostedUrl(url) {
1982
2065
  }
1983
2066
  const arrivalClause = (iso) => {
1984
2067
  const text = microdepositArrivalText(iso);
1985
- return text ? ` (by ${text})` : "";
2068
+ return text ? uiText("stripeMicrodepositVerify.byDate", { date: text }) : "";
1986
2069
  };
1987
2070
  function microdepositStepsText(ctx) {
2071
+ const t = (key, params) => uiText(`stripeMicrodepositVerify.${key}`, params);
1988
2072
  const partner = ctx.partnerName ?? "";
1989
- const holder = partner ? `${partner}'s account` : "your account";
2073
+ const holder = partner ? t("holderPartner", { partner }) : t("holderYours");
1990
2074
  const clause = arrivalClause(ctx.arrivalDate);
1991
- const deposits = ctx.type === "descriptor_code" ? `Stripe sent one small deposit to ${holder}${clause}, with a description that starts with SM followed by a 6-character code. ` : `Stripe sent two small deposits to ${holder}; they appear in 1-2 business days${clause}, with the description SMXXXX. `;
1992
- if (ctx.readOnly) return `${deposits}${ctx.readOnlyText ?? (ctx.startedBy === "partner" ? `This bank account was started by ${partner}; it can be finished by them.` : ctx.startedBy === "other" ? "This bank account was started by another crematory; it can be finished by them." : partner ? `${partner} or the crematory that set it up can finish the verification.` : MICRODEPOSIT_COPY.readOnly)} ${MICRODEPOSIT_COPY.cannotPay}`;
1993
- return `${deposits}${ctx.type === "descriptor_code" ? partner ? `Ask ${partner} for the code and enter it below to finish. ` : "When it arrives, enter that code below to finish. " : partner ? `Ask ${partner} for the two deposit amounts and enter them below to finish. ` : "When they arrive, enter the two amounts below to finish. "}${MICRODEPOSIT_COPY.cannotPay}`;
2075
+ const deposits = ctx.type === "descriptor_code" ? t("depositsDescriptor", {
2076
+ holder,
2077
+ clause
2078
+ }) : t("depositsAmounts", {
2079
+ holder,
2080
+ clause
2081
+ });
2082
+ if (ctx.readOnly) return `${deposits}${ctx.readOnlyText ?? (ctx.startedBy === "partner" ? t("startedByPartner", { partner }) : ctx.startedBy === "other" ? t("startedByOther") : partner ? t("partnerOrSetup", { partner }) : MICRODEPOSIT_COPY.readOnly)} ${MICRODEPOSIT_COPY.cannotPay}`;
2083
+ return `${deposits}${ctx.type === "descriptor_code" ? partner ? t("enterCodePartner", { partner }) : t("enterCodeOwn") : partner ? t("enterAmountsPartner", { partner }) : t("enterAmountsOwn")}${MICRODEPOSIT_COPY.cannotPay}`;
1994
2084
  }
1995
2085
  function microdepositProcessingText(partnerName = "") {
1996
- return partnerName ? `${partnerName}'s bank is confirming this account; this usually takes up to a few business days. We will email you when it is ready.` : MICRODEPOSIT_COPY.processing;
2086
+ return partnerName ? uiText("stripeMicrodepositVerify.processingPartner", { partner: partnerName }) : MICRODEPOSIT_COPY.processing;
1997
2087
  }
1998
2088
  function microdepositKeepsActiveText(partnerName = "") {
1999
- return partnerName ? `${partnerName}'s current payment method stays active until the new bank account is verified.` : MICRODEPOSIT_COPY.keepsActive;
2089
+ return partnerName ? uiText("stripeMicrodepositVerify.keepsActivePartner", { partner: partnerName }) : MICRODEPOSIT_COPY.keepsActive;
2000
2090
  }
2001
2091
  function microdepositCancelMessage(options = {}) {
2002
2092
  const partner = options.partnerName ?? "";
2003
- if (partner) return `${MICRODEPOSIT_COPY.cancelBase} ${options.hasSavedMethod ? `${partner}'s current payment method stays active.` : `${partner} has no other payment method saved.`}`;
2093
+ if (partner) return `${MICRODEPOSIT_COPY.cancelBase} ${options.hasSavedMethod ? uiText("stripeMicrodepositVerify.cancelKeepsActivePartner", { partner }) : uiText("stripeMicrodepositVerify.cancelNoOtherPartner", { partner })}`;
2004
2094
  return MICRODEPOSIT_COPY.cancelBase + (options.hasSavedMethod ? MICRODEPOSIT_COPY.cancelKeepsActive : MICRODEPOSIT_COPY.cancelNoOther);
2005
2095
  }
2006
2096
  var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2007
2097
  constructor() {
2098
+ this.labels = inject(UiLabelsService);
2008
2099
  this.service = inject(StripePaymentService);
2009
2100
  this.type = input("amounts", ...ngDevMode ? [{ debugName: "type" }] : /* istanbul ignore next */ []);
2010
2101
  this.bankName = input("", ...ngDevMode ? [{ debugName: "bankName" }] : /* istanbul ignore next */ []);
@@ -2051,7 +2142,7 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2051
2142
  const bank = this.bankName().trim();
2052
2143
  const last4 = this.last4().trim();
2053
2144
  if (!bank && !last4) return "";
2054
- return `${bank || "Bank account"}${last4 ? ` ····${last4}` : ""}`;
2145
+ return `${bank || this.labels.t("stripeMicrodepositVerify.bankFallback")}${last4 ? ` ····${last4}` : ""}`;
2055
2146
  }, ...ngDevMode ? [{ debugName: "bankLine" }] : /* istanbul ignore next */ []);
2056
2147
  this.busy = computed(() => this.verifying() || this.stripeBusy(), ...ngDevMode ? [{ debugName: "busy" }] : /* istanbul ignore next */ []);
2057
2148
  this.shownError = computed(() => this.stripeError() || this.errorText(), ...ngDevMode ? [{ debugName: "shownError" }] : /* istanbul ignore next */ []);
@@ -2096,9 +2187,12 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2096
2187
  return;
2097
2188
  }
2098
2189
  this.failedAttempts++;
2099
- const message = result.failure?.message ?? "Verification failed";
2190
+ const message = result.failure?.message ?? localizeStripeMessage("Verification failed");
2100
2191
  const remaining = max - this.failedAttempts;
2101
- this.stripeError.set(max > 0 && remaining > 0 ? `${message} (${remaining} attempt${remaining === 1 ? "" : "s"} remaining)` : message);
2192
+ this.stripeError.set(max > 0 && remaining > 0 ? this.labels.t(remaining === 1 ? "stripeMicrodepositVerify.attemptsRemaining_one" : "stripeMicrodepositVerify.attemptsRemaining_other", {
2193
+ message,
2194
+ count: remaining
2195
+ }) : message);
2102
2196
  this.verifyFailed.emit(result);
2103
2197
  }
2104
2198
  confirmCancel() {
@@ -2320,7 +2414,7 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2320
2414
  <ui-alert variant="info" data-testid="bank-pending-alert">
2321
2415
  <div data-testid="bank-pending-summary">
2322
2416
  @if (bankLine(); as line) { <strong data-testid="bank-pending-bank">{{ line }}</strong> }
2323
- <ui-badge label="Pending" variant="yellow" data-testid="bank-pending-badge" />
2417
+ <ui-badge [label]="labels.t('stripeMicrodepositVerify.pending')" variant="yellow" data-testid="bank-pending-badge" />
2324
2418
  </div>
2325
2419
  @if (stepsText().trim()) {
2326
2420
  <ui-text size="sm" [text]="stepsText()" data-testid="bank-pending-steps" />
@@ -2334,19 +2428,19 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2334
2428
  }
2335
2429
  <!-- Finishing the verification on Stripe's page saves the payment method (a write): never offered to a read-only user -->
2336
2430
  @if (!formHidden() && !hideHostedLink() && safeUrl(); as url) {
2337
- <div><ui-button variant="link" size="sm" [href]="url" target="_blank" data-testid="bank-hosted-link">Open Stripe's verification page</ui-button></div>
2431
+ <div><ui-button variant="link" size="sm" [href]="url" target="_blank" data-testid="bank-hosted-link">{{ labels.t('stripeMicrodepositVerify.openStripeSVerificationPage') }}</ui-button></div>
2338
2432
  }
2339
2433
  </ui-alert>
2340
2434
 
2341
2435
  @if (!formHidden() && !isProcessing()) {
2342
2436
  @if (type() === 'descriptor_code') {
2343
- <ui-text-input label="Verification code" hint="6 letters or numbers from the deposit description" [maxlength]="6" [required]="true" [showErrors]="touched()"
2437
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.verificationCode')" [hint]="labels.t('stripeMicrodepositVerify.6LettersOrNumbersFrom')" [maxlength]="6" [required]="true" [showErrors]="touched()"
2344
2438
  [error]="touched() ? codeError() : ''" data-testid="bank-code-input" [ngModel]="code()" (ngModelChange)="code.set($event)" />
2345
2439
  } @else {
2346
2440
  <ui-form-row data-testid="bank-amounts-row">
2347
- <ui-text-input label="First deposit (cents)" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2441
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.firstDepositCents')" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2348
2442
  [error]="touched() ? amountError(first()) : ''" data-testid="bank-amount-first" [ngModel]="first()" (ngModelChange)="first.set($event)" />
2349
- <ui-text-input label="Second deposit (cents)" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2443
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.secondDepositCents')" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2350
2444
  [error]="touched() ? amountError(second()) : ''" data-testid="bank-amount-second" [ngModel]="second()" (ngModelChange)="second.set($event)" />
2351
2445
  </ui-form-row>
2352
2446
  }
@@ -2363,7 +2457,7 @@ var MicrodepositVerifyComponent = class MicrodepositVerifyComponent {
2363
2457
 
2364
2458
  <ui-modal [open]="showCancelConfirm()" [title]="cancelLabel() || copy.cancelTitle" maxWidth="460px" (close)="showCancelConfirm.set(false)">
2365
2459
  <ui-text size="sm" data-testid="bank-cancel-message" [text]="cancelMessage()" />
2366
- <ui-button modal-footer-left variant="secondary" size="sm" data-testid="bank-cancel-keep" (click)="showCancelConfirm.set(false)">Keep waiting</ui-button>
2460
+ <ui-button modal-footer-left variant="secondary" size="sm" data-testid="bank-cancel-keep" (click)="showCancelConfirm.set(false)">{{ labels.t('stripeMicrodepositVerify.keepWaiting') }}</ui-button>
2367
2461
  <ui-button modal-footer-right variant="danger" size="sm" data-testid="bank-cancel-confirm" [loading]="cancelling()" (click)="confirmCancel()">{{ cancelLabel() || copy.cancelTitle }}</ui-button>
2368
2462
  </ui-modal>
2369
2463
  </div>
@@ -2582,7 +2676,7 @@ i0.ɵɵngDeclareClassMetadata({
2582
2676
  <ui-alert variant="info" data-testid="bank-pending-alert">
2583
2677
  <div data-testid="bank-pending-summary">
2584
2678
  @if (bankLine(); as line) { <strong data-testid="bank-pending-bank">{{ line }}</strong> }
2585
- <ui-badge label="Pending" variant="yellow" data-testid="bank-pending-badge" />
2679
+ <ui-badge [label]="labels.t('stripeMicrodepositVerify.pending')" variant="yellow" data-testid="bank-pending-badge" />
2586
2680
  </div>
2587
2681
  @if (stepsText().trim()) {
2588
2682
  <ui-text size="sm" [text]="stepsText()" data-testid="bank-pending-steps" />
@@ -2596,19 +2690,19 @@ i0.ɵɵngDeclareClassMetadata({
2596
2690
  }
2597
2691
  <!-- Finishing the verification on Stripe's page saves the payment method (a write): never offered to a read-only user -->
2598
2692
  @if (!formHidden() && !hideHostedLink() && safeUrl(); as url) {
2599
- <div><ui-button variant="link" size="sm" [href]="url" target="_blank" data-testid="bank-hosted-link">Open Stripe's verification page</ui-button></div>
2693
+ <div><ui-button variant="link" size="sm" [href]="url" target="_blank" data-testid="bank-hosted-link">{{ labels.t('stripeMicrodepositVerify.openStripeSVerificationPage') }}</ui-button></div>
2600
2694
  }
2601
2695
  </ui-alert>
2602
2696
 
2603
2697
  @if (!formHidden() && !isProcessing()) {
2604
2698
  @if (type() === 'descriptor_code') {
2605
- <ui-text-input label="Verification code" hint="6 letters or numbers from the deposit description" [maxlength]="6" [required]="true" [showErrors]="touched()"
2699
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.verificationCode')" [hint]="labels.t('stripeMicrodepositVerify.6LettersOrNumbersFrom')" [maxlength]="6" [required]="true" [showErrors]="touched()"
2606
2700
  [error]="touched() ? codeError() : ''" data-testid="bank-code-input" [ngModel]="code()" (ngModelChange)="code.set($event)" />
2607
2701
  } @else {
2608
2702
  <ui-form-row data-testid="bank-amounts-row">
2609
- <ui-text-input label="First deposit (cents)" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2703
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.firstDepositCents')" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2610
2704
  [error]="touched() ? amountError(first()) : ''" data-testid="bank-amount-first" [ngModel]="first()" (ngModelChange)="first.set($event)" />
2611
- <ui-text-input label="Second deposit (cents)" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2705
+ <ui-text-input [label]="labels.t('stripeMicrodepositVerify.secondDepositCents')" type="number" [min]="1" [max]="99" [maxDecimals]="0" [required]="true" [showErrors]="touched()"
2612
2706
  [error]="touched() ? amountError(second()) : ''" data-testid="bank-amount-second" [ngModel]="second()" (ngModelChange)="second.set($event)" />
2613
2707
  </ui-form-row>
2614
2708
  }
@@ -2625,7 +2719,7 @@ i0.ɵɵngDeclareClassMetadata({
2625
2719
 
2626
2720
  <ui-modal [open]="showCancelConfirm()" [title]="cancelLabel() || copy.cancelTitle" maxWidth="460px" (close)="showCancelConfirm.set(false)">
2627
2721
  <ui-text size="sm" data-testid="bank-cancel-message" [text]="cancelMessage()" />
2628
- <ui-button modal-footer-left variant="secondary" size="sm" data-testid="bank-cancel-keep" (click)="showCancelConfirm.set(false)">Keep waiting</ui-button>
2722
+ <ui-button modal-footer-left variant="secondary" size="sm" data-testid="bank-cancel-keep" (click)="showCancelConfirm.set(false)">{{ labels.t('stripeMicrodepositVerify.keepWaiting') }}</ui-button>
2629
2723
  <ui-button modal-footer-right variant="danger" size="sm" data-testid="bank-cancel-confirm" [loading]="cancelling()" (click)="confirmCancel()">{{ cancelLabel() || copy.cancelTitle }}</ui-button>
2630
2724
  </ui-modal>
2631
2725
  </div>
@@ -3012,28 +3106,29 @@ function stripeConnectNotice(outcome) {
3012
3106
  switch (outcome.kind) {
3013
3107
  case "complete": return {
3014
3108
  variant: "success",
3015
- message: outcome.source === "resume" ? "Payment account setup is already complete!" : "Payment account setup complete!"
3109
+ message: uiText(outcome.source === "resume" ? "stripeStripeConnect.noticeCompleteResume" : "stripeStripeConnect.noticeComplete")
3016
3110
  };
3017
3111
  case "verifying": return {
3018
3112
  variant: "success",
3019
- message: "Setup submitted! Stripe is verifying your account. This usually takes a few minutes. Click \"Check Status\" to refresh."
3113
+ message: uiText("stripeStripeConnect.noticeVerifying")
3020
3114
  };
3021
3115
  case "incomplete": return {
3022
3116
  variant: "error",
3023
- message: "Payment account setup is not yet complete. Please continue setup."
3117
+ message: uiText("stripeStripeConnect.noticeIncomplete")
3024
3118
  };
3025
3119
  case "link-unavailable": return {
3026
3120
  variant: "error",
3027
- message: "Unable to retrieve onboarding link. Please try again."
3121
+ message: uiText("stripeStripeConnect.noticeLinkUnavailable")
3028
3122
  };
3029
3123
  case "failed": return {
3030
3124
  variant: "error",
3031
- message: outcome.action === "start" ? "Failed to start payment account setup" : outcome.action === "check" ? "Failed to check payment account status" : "Failed to retrieve onboarding link"
3125
+ message: uiText(outcome.action === "start" ? "stripeStripeConnect.failedStart" : outcome.action === "check" ? "stripeStripeConnect.failedCheck" : "stripeStripeConnect.failedLink")
3032
3126
  };
3033
3127
  }
3034
3128
  }
3035
3129
  var StripeConnectComponent = class StripeConnectComponent {
3036
3130
  constructor() {
3131
+ this.labels = inject(UiLabelsService);
3037
3132
  this.destroyRef = inject(DestroyRef);
3038
3133
  this.injector = inject(Injector);
3039
3134
  this.host = inject(ElementRef);
@@ -3042,12 +3137,28 @@ var StripeConnectComponent = class StripeConnectComponent {
3042
3137
  this.accountId = model(null, ...ngDevMode ? [{ debugName: "accountId" }] : /* istanbul ignore next */ []);
3043
3138
  this.complete = model(false, ...ngDevMode ? [{ debugName: "complete" }] : /* istanbul ignore next */ []);
3044
3139
  this.detailsSubmitted = model(false, ...ngDevMode ? [{ debugName: "detailsSubmitted" }] : /* istanbul ignore next */ []);
3045
- this.title = input("Stripe Connect Account", ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
3140
+ this.titleInput = input(null, {
3141
+ ...ngDevMode ? { debugName: "titleInput" } : /* istanbul ignore next */ {},
3142
+ alias: "title"
3143
+ });
3144
+ this.title = computed(() => this.titleInput() ?? this.labels.t("stripeStripeConnect.title"), ...ngDevMode ? [{ debugName: "title" }] : /* istanbul ignore next */ []);
3046
3145
  this.bare = input(false, ...ngDevMode ? [{ debugName: "bare" }] : /* istanbul ignore next */ []);
3047
3146
  this.showWhenNoAccount = input(false, ...ngDevMode ? [{ debugName: "showWhenNoAccount" }] : /* istanbul ignore next */ []);
3048
- this.startTitle = input("Connect your Stripe account", ...ngDevMode ? [{ debugName: "startTitle" }] : /* istanbul ignore next */ []);
3049
- this.startText = input("Collect your customers' payments online. You finish setting up your account on Stripe, then come back here.", ...ngDevMode ? [{ debugName: "startText" }] : /* istanbul ignore next */ []);
3050
- this.startLabel = input("Set Up Payment Account", ...ngDevMode ? [{ debugName: "startLabel" }] : /* istanbul ignore next */ []);
3147
+ this.startTitleInput = input(null, {
3148
+ ...ngDevMode ? { debugName: "startTitleInput" } : /* istanbul ignore next */ {},
3149
+ alias: "startTitle"
3150
+ });
3151
+ this.startTitle = computed(() => this.startTitleInput() ?? this.labels.t("stripeStripeConnect.startTitle"), ...ngDevMode ? [{ debugName: "startTitle" }] : /* istanbul ignore next */ []);
3152
+ this.startTextInput = input(null, {
3153
+ ...ngDevMode ? { debugName: "startTextInput" } : /* istanbul ignore next */ {},
3154
+ alias: "startText"
3155
+ });
3156
+ this.startText = computed(() => this.startTextInput() ?? this.labels.t("stripeStripeConnect.startText"), ...ngDevMode ? [{ debugName: "startText" }] : /* istanbul ignore next */ []);
3157
+ this.startLabelInput = input(null, {
3158
+ ...ngDevMode ? { debugName: "startLabelInput" } : /* istanbul ignore next */ {},
3159
+ alias: "startLabel"
3160
+ });
3161
+ this.startLabel = computed(() => this.startLabelInput() ?? this.labels.t("stripeStripeConnect.startLabel"), ...ngDevMode ? [{ debugName: "startLabel" }] : /* istanbul ignore next */ []);
3051
3162
  this.disabled = input(false, ...ngDevMode ? [{ debugName: "disabled" }] : /* istanbul ignore next */ []);
3052
3163
  this.refreshOnReturn = input(false, ...ngDevMode ? [{ debugName: "refreshOnReturn" }] : /* istanbul ignore next */ []);
3053
3164
  this.dashboardUrl = input("https://dashboard.stripe.com", ...ngDevMode ? [{ debugName: "dashboardUrl" }] : /* istanbul ignore next */ []);
@@ -3058,13 +3169,13 @@ var StripeConnectComponent = class StripeConnectComponent {
3058
3169
  this.state = computed(() => !this.accountId() ? "none" : this.complete() ? "complete" : this.detailsSubmitted() ? "verifying" : "incomplete", ...ngDevMode ? [{ debugName: "state" }] : /* istanbul ignore next */ []);
3059
3170
  this.liveText = computed(() => {
3060
3171
  if (!this.visible()) return "";
3061
- const text = {
3062
- none: "Stripe account not connected.",
3063
- incomplete: "Account setup incomplete.",
3064
- verifying: "Stripe is verifying your account.",
3065
- complete: "Account setup complete."
3066
- }[this.state()];
3067
- return this.loading() ? `${text} Loading.` : text;
3172
+ const text = this.labels.t({
3173
+ none: "stripeStripeConnect.liveNone",
3174
+ incomplete: "stripeStripeConnect.liveIncomplete",
3175
+ verifying: "stripeStripeConnect.liveVerifying",
3176
+ complete: "stripeStripeConnect.liveComplete"
3177
+ }[this.state()]);
3178
+ return this.loading() ? this.labels.t("stripeStripeConnect.liveLoading", { text }) : text;
3068
3179
  }, ...ngDevMode ? [{ debugName: "liveText" }] : /* istanbul ignore next */ []);
3069
3180
  this.acted = false;
3070
3181
  this.lastState = this.state();
@@ -3180,8 +3291,8 @@ var StripeConnectComponent = class StripeConnectComponent {
3180
3291
  isRequired: false,
3181
3292
  transformFunction: null
3182
3293
  },
3183
- title: {
3184
- classPropertyName: "title",
3294
+ titleInput: {
3295
+ classPropertyName: "titleInput",
3185
3296
  publicName: "title",
3186
3297
  isSignal: true,
3187
3298
  isRequired: false,
@@ -3201,22 +3312,22 @@ var StripeConnectComponent = class StripeConnectComponent {
3201
3312
  isRequired: false,
3202
3313
  transformFunction: null
3203
3314
  },
3204
- startTitle: {
3205
- classPropertyName: "startTitle",
3315
+ startTitleInput: {
3316
+ classPropertyName: "startTitleInput",
3206
3317
  publicName: "startTitle",
3207
3318
  isSignal: true,
3208
3319
  isRequired: false,
3209
3320
  transformFunction: null
3210
3321
  },
3211
- startText: {
3212
- classPropertyName: "startText",
3322
+ startTextInput: {
3323
+ classPropertyName: "startTextInput",
3213
3324
  publicName: "startText",
3214
3325
  isSignal: true,
3215
3326
  isRequired: false,
3216
3327
  transformFunction: null
3217
3328
  },
3218
- startLabel: {
3219
- classPropertyName: "startLabel",
3329
+ startLabelInput: {
3330
+ classPropertyName: "startLabelInput",
3220
3331
  publicName: "startLabel",
3221
3332
  isSignal: true,
3222
3333
  isRequired: false,
@@ -3285,31 +3396,31 @@ var StripeConnectComponent = class StripeConnectComponent {
3285
3396
  <strong class="sc-title">{{ startTitle() }}</strong>
3286
3397
  <ui-text size="sm" [text]="startText()" />
3287
3398
  <ui-stack direction="horizontal">
3288
- <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="disabled()" (click)="start()">@if (loading()) {<span aria-hidden="true">Loading...</span><span class="sc-sr">{{ startLabel() }}, opens in a new tab, busy</span>} @else { {{ startLabel() }}<span class="sc-sr">, opens in a new tab</span>}</ui-button>
3399
+ <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="disabled()" (click)="start()">@if (loading()) {<span aria-hidden="true">{{ labels.t('common.loadingellipsis') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabBusy', { label: startLabel() }) }}</span>} @else { {{ startLabel() }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span>}</ui-button>
3289
3400
  </ui-stack>
3290
3401
  </ui-stack>
3291
3402
  } @else if (complete()) {
3292
3403
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-complete">
3293
- <strong class="sc-title">Account setup complete</strong>
3294
- <ui-text size="sm" tone="muted" [text]="'Account ID: ' + accountId()" />
3404
+ <strong class="sc-title">{{ labels.t('stripeStripeConnect.accountSetupComplete') }}</strong>
3405
+ <ui-text size="sm" tone="muted" [text]="labels.t('stripeConnect.accountId', { id: accountId() ?? '' })" />
3295
3406
  <ui-stack direction="horizontal">
3296
- <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">View Stripe Dashboard<span class="sc-sr">, opens in a new tab</span></ui-button>
3407
+ <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">{{ labels.t('stripeStripeConnect.viewStripeDashboard') }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span></ui-button>
3297
3408
  </ui-stack>
3298
3409
  </ui-stack>
3299
3410
  } @else if (detailsSubmitted()) {
3300
3411
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-verifying" [attr.aria-busy]="loading() ? 'true' : null">
3301
- <strong class="sc-title">Stripe is verifying your account</strong>
3302
- <ui-text size="sm" text="Your setup has been submitted. Stripe is reviewing your information — this usually takes a few minutes. Payment collection will be enabled automatically once approved." />
3412
+ <strong class="sc-title">{{ labels.t('stripeStripeConnect.stripeIsVerifyingYourAccount') }}</strong>
3413
+ <ui-text size="sm" [text]="labels.t('stripeStripeConnect.yourSetupHasBeenSubmitted')" />
3303
3414
  <ui-stack direction="horizontal">
3304
- <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="disabled()" (click)="check()">@if (loading()) {<span aria-hidden="true">Checking...</span><span class="sc-sr">Check Status, busy</span>} @else {Check Status}</ui-button>
3415
+ <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="disabled()" (click)="check()">@if (loading()) {<span aria-hidden="true">{{ labels.t('stripeStripeConnect.checking') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.checkStatusBusy') }}</span>} @else { {{ labels.t('stripeStripeConnect.checkStatus') }} }</ui-button>
3305
3416
  </ui-stack>
3306
3417
  </ui-stack>
3307
3418
  } @else {
3308
3419
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-incomplete" [attr.aria-busy]="loading() ? 'true' : null">
3309
- <span class="sc-badge"><ui-badge label="Account setup incomplete" variant="red" data-testid="connect-incomplete-badge" /></span>
3310
- <ui-text size="sm" text="Complete your Stripe account setup to start collecting payments from customers." />
3420
+ <span class="sc-badge"><ui-badge [label]="labels.t('stripeStripeConnect.accountSetupIncomplete')" variant="red" data-testid="connect-incomplete-badge" /></span>
3421
+ <ui-text size="sm" [text]="labels.t('stripeStripeConnect.completeYourStripeAccountSetup')" />
3311
3422
  <ui-stack direction="horizontal">
3312
- <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="disabled()" (click)="resume()">@if (loading()) {<span aria-hidden="true">Loading...</span><span class="sc-sr">Complete Setup, opens in a new tab, busy</span>} @else {Complete Setup<span class="sc-sr">, opens in a new tab</span>}</ui-button>
3423
+ <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="disabled()" (click)="resume()">@if (loading()) {<span aria-hidden="true">{{ labels.t('common.loadingellipsis') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.completeSetupOpensInA') }}</span>} @else { {{ labels.t('stripeStripeConnect.completeSetup') }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span>}</ui-button>
3313
3424
  </ui-stack>
3314
3425
  </ui-stack>
3315
3426
  }
@@ -3393,6 +3504,7 @@ var StripeConnectComponent = class StripeConnectComponent {
3393
3504
  "editIcon",
3394
3505
  "editAriaLabel",
3395
3506
  "fill",
3507
+ "noPadding",
3396
3508
  "maxBodyHeight",
3397
3509
  "selectable",
3398
3510
  "selected",
@@ -3479,31 +3591,31 @@ i0.ɵɵngDeclareClassMetadata({
3479
3591
  <strong class="sc-title">{{ startTitle() }}</strong>
3480
3592
  <ui-text size="sm" [text]="startText()" />
3481
3593
  <ui-stack direction="horizontal">
3482
- <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="disabled()" (click)="start()">@if (loading()) {<span aria-hidden="true">Loading...</span><span class="sc-sr">{{ startLabel() }}, opens in a new tab, busy</span>} @else { {{ startLabel() }}<span class="sc-sr">, opens in a new tab</span>}</ui-button>
3594
+ <ui-button variant="primary" size="sm" data-testid="connect-start-button" [disabled]="disabled()" (click)="start()">@if (loading()) {<span aria-hidden="true">{{ labels.t('common.loadingellipsis') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabBusy', { label: startLabel() }) }}</span>} @else { {{ startLabel() }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span>}</ui-button>
3483
3595
  </ui-stack>
3484
3596
  </ui-stack>
3485
3597
  } @else if (complete()) {
3486
3598
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-complete">
3487
- <strong class="sc-title">Account setup complete</strong>
3488
- <ui-text size="sm" tone="muted" [text]="'Account ID: ' + accountId()" />
3599
+ <strong class="sc-title">{{ labels.t('stripeStripeConnect.accountSetupComplete') }}</strong>
3600
+ <ui-text size="sm" tone="muted" [text]="labels.t('stripeConnect.accountId', { id: accountId() ?? '' })" />
3489
3601
  <ui-stack direction="horizontal">
3490
- <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">View Stripe Dashboard<span class="sc-sr">, opens in a new tab</span></ui-button>
3602
+ <ui-button variant="secondary" size="sm" data-testid="connect-dashboard-button" (click)="openDashboard()">{{ labels.t('stripeStripeConnect.viewStripeDashboard') }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span></ui-button>
3491
3603
  </ui-stack>
3492
3604
  </ui-stack>
3493
3605
  } @else if (detailsSubmitted()) {
3494
3606
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-verifying" [attr.aria-busy]="loading() ? 'true' : null">
3495
- <strong class="sc-title">Stripe is verifying your account</strong>
3496
- <ui-text size="sm" text="Your setup has been submitted. Stripe is reviewing your information — this usually takes a few minutes. Payment collection will be enabled automatically once approved." />
3607
+ <strong class="sc-title">{{ labels.t('stripeStripeConnect.stripeIsVerifyingYourAccount') }}</strong>
3608
+ <ui-text size="sm" [text]="labels.t('stripeStripeConnect.yourSetupHasBeenSubmitted')" />
3497
3609
  <ui-stack direction="horizontal">
3498
- <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="disabled()" (click)="check()">@if (loading()) {<span aria-hidden="true">Checking...</span><span class="sc-sr">Check Status, busy</span>} @else {Check Status}</ui-button>
3610
+ <ui-button variant="primary" size="sm" data-testid="connect-check-status-button" [disabled]="disabled()" (click)="check()">@if (loading()) {<span aria-hidden="true">{{ labels.t('stripeStripeConnect.checking') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.checkStatusBusy') }}</span>} @else { {{ labels.t('stripeStripeConnect.checkStatus') }} }</ui-button>
3499
3611
  </ui-stack>
3500
3612
  </ui-stack>
3501
3613
  } @else {
3502
3614
  <ui-stack gap="sm" class="sc-state" tabindex="-1" data-testid="connect-status-incomplete" [attr.aria-busy]="loading() ? 'true' : null">
3503
- <span class="sc-badge"><ui-badge label="Account setup incomplete" variant="red" data-testid="connect-incomplete-badge" /></span>
3504
- <ui-text size="sm" text="Complete your Stripe account setup to start collecting payments from customers." />
3615
+ <span class="sc-badge"><ui-badge [label]="labels.t('stripeStripeConnect.accountSetupIncomplete')" variant="red" data-testid="connect-incomplete-badge" /></span>
3616
+ <ui-text size="sm" [text]="labels.t('stripeStripeConnect.completeYourStripeAccountSetup')" />
3505
3617
  <ui-stack direction="horizontal">
3506
- <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="disabled()" (click)="resume()">@if (loading()) {<span aria-hidden="true">Loading...</span><span class="sc-sr">Complete Setup, opens in a new tab, busy</span>} @else {Complete Setup<span class="sc-sr">, opens in a new tab</span>}</ui-button>
3618
+ <ui-button variant="primary" size="sm" data-testid="connect-complete-setup-button" [disabled]="disabled()" (click)="resume()">@if (loading()) {<span aria-hidden="true">{{ labels.t('common.loadingellipsis') }}</span><span class="sc-sr">{{ labels.t('stripeStripeConnect.completeSetupOpensInA') }}</span>} @else { {{ labels.t('stripeStripeConnect.completeSetup') }}<span class="sc-sr">{{ labels.t('stripeStripeConnect.opensInNewTabSr') }}</span>}</ui-button>
3507
3619
  </ui-stack>
3508
3620
  </ui-stack>
3509
3621
  }
@@ -3564,7 +3676,7 @@ i0.ɵɵngDeclareClassMetadata({
3564
3676
  type: i0.Output,
3565
3677
  args: ["detailsSubmittedChange"]
3566
3678
  }],
3567
- title: [{
3679
+ titleInput: [{
3568
3680
  type: i0.Input,
3569
3681
  args: [{
3570
3682
  isSignal: true,
@@ -3588,7 +3700,7 @@ i0.ɵɵngDeclareClassMetadata({
3588
3700
  required: false
3589
3701
  }]
3590
3702
  }],
3591
- startTitle: [{
3703
+ startTitleInput: [{
3592
3704
  type: i0.Input,
3593
3705
  args: [{
3594
3706
  isSignal: true,
@@ -3596,7 +3708,7 @@ i0.ɵɵngDeclareClassMetadata({
3596
3708
  required: false
3597
3709
  }]
3598
3710
  }],
3599
- startText: [{
3711
+ startTextInput: [{
3600
3712
  type: i0.Input,
3601
3713
  args: [{
3602
3714
  isSignal: true,
@@ -3604,7 +3716,7 @@ i0.ɵɵngDeclareClassMetadata({
3604
3716
  required: false
3605
3717
  }]
3606
3718
  }],
3607
- startLabel: [{
3719
+ startLabelInput: [{
3608
3720
  type: i0.Input,
3609
3721
  args: [{
3610
3722
  isSignal: true,
@@ -3668,15 +3780,26 @@ const STRIPE_PAYMENT_METHODS = [{
3668
3780
  value: "ACH",
3669
3781
  label: "ACH / Bank Transfer"
3670
3782
  }];
3783
+ const stripeMethodLabel = (value, english) => value === "CARD" ? uiText("stripePaymentMethod.methodCard") : value === "ACH" ? uiText("stripePaymentMethod.methodAch") : english;
3671
3784
  const stripeMethodType = (method) => method === "ACH" ? "us_bank_account" : "card";
3672
3785
  const STRIPE_METHOD_TEXTS = {
3673
- amountNeeded: "Enter an amount to continue.",
3674
- notCompleted: "Payment was not completed. Please try again or choose another method.",
3675
- achTitle: "ACH Payment Submitted",
3676
- achMessage: (amount) => `Your bank payment of ${amount} has been submitted for processing. ACH payments typically take 3–5 business days to complete.`,
3677
- verificationTitle: "Bank Verification Needed",
3678
- verificationMessage: (amount) => `Your bank payment of ${amount} was submitted. The bank account must be verified with the small deposits Stripe sends, then the payment completes.`,
3679
- receiptNote: "A receipt is sent once the payment has been fully processed and settled."
3786
+ get amountNeeded() {
3787
+ return uiText("stripePaymentMethod.amountNeeded");
3788
+ },
3789
+ get notCompleted() {
3790
+ return uiText("stripePaymentMethod.notCompleted");
3791
+ },
3792
+ get achTitle() {
3793
+ return uiText("stripePaymentMethod.achTitle");
3794
+ },
3795
+ achMessage: (amount) => uiText("stripePaymentMethod.achMessage", { amount }),
3796
+ get verificationTitle() {
3797
+ return uiText("stripePaymentMethod.verificationTitle");
3798
+ },
3799
+ verificationMessage: (amount) => uiText("stripePaymentMethod.verificationMessage", { amount }),
3800
+ get receiptNote() {
3801
+ return uiText("stripePaymentMethod.receiptNote");
3802
+ }
3680
3803
  };
3681
3804
  const WALLETS = {
3682
3805
  applePay: "never",
@@ -3688,6 +3811,7 @@ const FIELDS = { billingDetails: { address: {
3688
3811
  } } };
3689
3812
  var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3690
3813
  constructor() {
3814
+ this.labels = inject(UiLabelsService);
3691
3815
  this.injector = inject(Injector);
3692
3816
  this.host = inject(ElementRef);
3693
3817
  this.ctx = input.required(...ngDevMode ? [{ debugName: "ctx" }] : /* istanbul ignore next */ []);
@@ -3731,17 +3855,17 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3731
3855
  const money = (n) => formatCurrency(n, { currency: this.ctx().currency });
3732
3856
  const rows = [{
3733
3857
  key: "amount",
3734
- label: "Payment amount",
3858
+ label: this.labels.t("stripePaymentMethod.paymentAmount"),
3735
3859
  value: money(amount)
3736
3860
  }];
3737
3861
  if (fees.stripeFee !== void 0) rows.push({
3738
3862
  key: "processing",
3739
- label: `Processing fee${fees.stripeFeeLabel ? ` (${fees.stripeFeeLabel})` : ""}`,
3863
+ label: `${this.labels.t("stripePaymentMethod.processingFee")}${fees.stripeFeeLabel ? ` (${fees.stripeFeeLabel})` : ""}`,
3740
3864
  value: money(fees.stripeFee)
3741
3865
  });
3742
3866
  if (fees.platformFee !== void 0) rows.push({
3743
3867
  key: "platform",
3744
- label: `Platform fee${fees.platformFeeLabel ? ` (${fees.platformFeeLabel})` : ""}`,
3868
+ label: `${this.labels.t("stripePaymentMethod.platformFee")}${fees.platformFeeLabel ? ` (${fees.platformFeeLabel})` : ""}`,
3745
3869
  value: money(fees.platformFee)
3746
3870
  });
3747
3871
  return rows;
@@ -3751,13 +3875,13 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3751
3875
  if (!fees || this.lastAmount() == null || fees.totalAmount === void 0) return null;
3752
3876
  return {
3753
3877
  value: formatCurrency(fees.totalAmount, { currency: this.ctx().currency }),
3754
- subtitle: "Payment amount plus fees"
3878
+ subtitle: this.labels.t("stripePaymentMethod.amountPlusFees")
3755
3879
  };
3756
3880
  }, ...ngDevMode ? [{ debugName: "totalCard" }] : /* istanbul ignore next */ []);
3757
3881
  this.createIntentFn = async () => {
3758
3882
  const create = this.config().createIntent();
3759
3883
  const ctx = this.ctx();
3760
- if (!create || ctx.amount == null) throw new Error("Card payments are not available right now.");
3884
+ if (!create || ctx.amount == null) throw new Error(this.labels.t("stripePayment.msg.cardsUnavailable"));
3761
3885
  this.cancelIntent(true);
3762
3886
  const info = await callHost(() => create({
3763
3887
  amount: ctx.amount,
@@ -3767,7 +3891,7 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3767
3891
  notes: ctx.note || null,
3768
3892
  ...ctx.allocation
3769
3893
  }));
3770
- if (!info?.clientSecret) throw new Error("Failed to initialize payment. Please try again.");
3894
+ if (!info?.clientSecret) throw new Error(this.labels.t("stripePayment.msg.initFailed"));
3771
3895
  this.intent = info;
3772
3896
  this.intentFees.set({
3773
3897
  stripeFee: info.stripeFee,
@@ -3790,7 +3914,7 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3790
3914
  const estimating = this.estimating();
3791
3915
  const done = this.done();
3792
3916
  const estimateFailed = !!this.estimateError();
3793
- const label = notice ? "Done" : ctx.amount != null ? `Pay ${formatCurrency(this.total(), { currency: ctx.currency })}` : "Pay";
3917
+ const label = notice ? this.labels.t("common.done") : ctx.amount != null ? `${this.labels.t("stripePayment.pay")} ${formatCurrency(this.total(), { currency: ctx.currency })}` : this.labels.t("stripePayment.pay");
3794
3918
  untracked(() => ctx.setPrimary({
3795
3919
  label,
3796
3920
  loading: processing && !notice,
@@ -3815,7 +3939,7 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3815
3939
  }
3816
3940
  untracked(() => this.estimating.set(true));
3817
3941
  let hung = null;
3818
- const failure = "Could not calculate the fees. Please try again.";
3942
+ const failure = this.labels.t("stripePayment.msg.feesFailed");
3819
3943
  const timer = setTimeout(async () => {
3820
3944
  hung = setTimeout(() => {
3821
3945
  if (run !== this.estimateRun) return;
@@ -3884,7 +4008,7 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3884
4008
  }
3885
4009
  onReady() {
3886
4010
  this.complete.set(false);
3887
- this.ctx().announce("Payment form ready");
4011
+ this.ctx().announce(this.labels.t("stripePaymentMethod.announceReady"));
3888
4012
  }
3889
4013
  onFailed(failure) {
3890
4014
  this.error.set(failure.message);
@@ -3899,7 +4023,7 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
3899
4023
  this.error.set("");
3900
4024
  this.processing.set(true);
3901
4025
  ctx.setBusy(true);
3902
- ctx.announce("Processing payment");
4026
+ ctx.announce(this.labels.t("stripePaymentMethod.announceProcessing"));
3903
4027
  let finished = false;
3904
4028
  try {
3905
4029
  const event = await payment.confirm();
@@ -4022,20 +4146,20 @@ var PaymentStripeBodyComponent = class PaymentStripeBodyComponent {
4022
4146
  @if (estimateError()) {
4023
4147
  <div class="psm-error">
4024
4148
  <ui-alert variant="warning" data-testid="stripe-method-estimate-error">{{ estimateError() }}
4025
- <ui-button variant="secondary" size="sm" data-testid="stripe-method-estimate-retry" (click)="retryEstimate()">Try again</ui-button>
4149
+ <ui-button variant="secondary" size="sm" data-testid="stripe-method-estimate-retry" (click)="retryEstimate()">{{ labels.t('common.tryAgain') }}</ui-button>
4026
4150
  </ui-alert>
4027
4151
  </div>
4028
4152
  }
4029
4153
  @if (lastAmount() != null) {
4030
4154
  <ui-stripe-payment #payment mode="payment" [publishableKey]="config().publishableKey()" [stripeAccount]="config().stripeAccount()" [deferred]="deferred()"
4031
4155
  [createIntent]="createIntentFn" [paymentMethodTypes]="[methodType()]" [showSubmit]="false" [showErrors]="false" [autoHandleCardAction]="true"
4032
- [wallets]="wallets" [fields]="fields" [defaultValues]="defaultValues()" [appearance]="$any(config().appearance())" [appearanceFromTokens]="true" label="Payment details"
4156
+ [wallets]="wallets" [fields]="fields" [defaultValues]="defaultValues()" [appearance]="$any(config().appearance())" [appearanceFromTokens]="true" [label]="labels.t('stripePaymentStripeMethod.paymentDetails')"
4033
4157
  (ready)="onReady()" (elementChange)="complete.set($event.complete)" (failed)="onFailed($event)" (loadError)="onFailed($event)" />
4034
4158
  @if (totalCard(); as card) {
4035
- <ui-kpi-card class="psm-total" data-testid="stripe-method-total" label="Total charged" [value]="card.value" [subtitle]="card.subtitle" icon="dollar" color="blue" valueColor="blue" />
4159
+ <ui-kpi-card class="psm-total" data-testid="stripe-method-total" [label]="labels.t('stripePaymentStripeMethod.totalCharged')" [value]="card.value" [subtitle]="card.subtitle" icon="dollar" color="blue" valueColor="blue" />
4036
4160
  }
4037
4161
  @if (feeRows().length) {
4038
- <dl class="psm-fees" data-testid="stripe-method-fees" aria-label="Payment total">
4162
+ <dl class="psm-fees" data-testid="stripe-method-fees" [attr.aria-label]="labels.t('stripePaymentStripeMethod.paymentTotal')">
4039
4163
  @for (row of feeRows(); track row.key) {
4040
4164
  <div class="psm-fee" [attr.data-testid]="'stripe-fee-' + row.key"><dt>{{ row.label }}</dt><dd>{{ row.value }}</dd></div>
4041
4165
  }
@@ -4227,20 +4351,20 @@ i0.ɵɵngDeclareClassMetadata({
4227
4351
  @if (estimateError()) {
4228
4352
  <div class="psm-error">
4229
4353
  <ui-alert variant="warning" data-testid="stripe-method-estimate-error">{{ estimateError() }}
4230
- <ui-button variant="secondary" size="sm" data-testid="stripe-method-estimate-retry" (click)="retryEstimate()">Try again</ui-button>
4354
+ <ui-button variant="secondary" size="sm" data-testid="stripe-method-estimate-retry" (click)="retryEstimate()">{{ labels.t('common.tryAgain') }}</ui-button>
4231
4355
  </ui-alert>
4232
4356
  </div>
4233
4357
  }
4234
4358
  @if (lastAmount() != null) {
4235
4359
  <ui-stripe-payment #payment mode="payment" [publishableKey]="config().publishableKey()" [stripeAccount]="config().stripeAccount()" [deferred]="deferred()"
4236
4360
  [createIntent]="createIntentFn" [paymentMethodTypes]="[methodType()]" [showSubmit]="false" [showErrors]="false" [autoHandleCardAction]="true"
4237
- [wallets]="wallets" [fields]="fields" [defaultValues]="defaultValues()" [appearance]="$any(config().appearance())" [appearanceFromTokens]="true" label="Payment details"
4361
+ [wallets]="wallets" [fields]="fields" [defaultValues]="defaultValues()" [appearance]="$any(config().appearance())" [appearanceFromTokens]="true" [label]="labels.t('stripePaymentStripeMethod.paymentDetails')"
4238
4362
  (ready)="onReady()" (elementChange)="complete.set($event.complete)" (failed)="onFailed($event)" (loadError)="onFailed($event)" />
4239
4363
  @if (totalCard(); as card) {
4240
- <ui-kpi-card class="psm-total" data-testid="stripe-method-total" label="Total charged" [value]="card.value" [subtitle]="card.subtitle" icon="dollar" color="blue" valueColor="blue" />
4364
+ <ui-kpi-card class="psm-total" data-testid="stripe-method-total" [label]="labels.t('stripePaymentStripeMethod.totalCharged')" [value]="card.value" [subtitle]="card.subtitle" icon="dollar" color="blue" valueColor="blue" />
4241
4365
  }
4242
4366
  @if (feeRows().length) {
4243
- <dl class="psm-fees" data-testid="stripe-method-fees" aria-label="Payment total">
4367
+ <dl class="psm-fees" data-testid="stripe-method-fees" [attr.aria-label]="labels.t('stripePaymentStripeMethod.paymentTotal')">
4244
4368
  @for (row of feeRows(); track row.key) {
4245
4369
  <div class="psm-fee" [attr.data-testid]="'stripe-fee-' + row.key"><dt>{{ row.label }}</dt><dd>{{ row.value }}</dd></div>
4246
4370
  }
@@ -4290,10 +4414,21 @@ var StripePaymentMethodComponent = class StripePaymentMethodComponent extends Pa
4290
4414
  this.stripeAccount = input(null, ...ngDevMode ? [{ debugName: "stripeAccount" }] : /* istanbul ignore next */ []);
4291
4415
  this.billingDetails = input(null, ...ngDevMode ? [{ debugName: "billingDetails" }] : /* istanbul ignore next */ []);
4292
4416
  this.appearance = input(null, ...ngDevMode ? [{ debugName: "appearance" }] : /* istanbul ignore next */ []);
4293
- this.methodList = input(STRIPE_PAYMENT_METHODS, ...ngDevMode ? [{ debugName: "methodList" }] : /* istanbul ignore next */ []);
4417
+ this.methodListInput = input(null, {
4418
+ ...ngDevMode ? { debugName: "methodListInput" } : /* istanbul ignore next */ {},
4419
+ alias: "methodList"
4420
+ });
4421
+ this.methodList = computed(() => this.methodListInput() ?? STRIPE_PAYMENT_METHODS.map((m) => ({
4422
+ ...m,
4423
+ label: stripeMethodLabel(m.value, m.label)
4424
+ })), ...ngDevMode ? [{ debugName: "methodList" }] : /* istanbul ignore next */ []);
4294
4425
  this.estimateTimeoutMs = input(1e4, ...ngDevMode ? [{ debugName: "estimateTimeoutMs" }] : /* istanbul ignore next */ []);
4295
4426
  this.feesRequired = input(false, ...ngDevMode ? [{ debugName: "feesRequired" }] : /* istanbul ignore next */ []);
4296
- this.receiptNote = input(STRIPE_METHOD_TEXTS.receiptNote, ...ngDevMode ? [{ debugName: "receiptNote" }] : /* istanbul ignore next */ []);
4427
+ this.receiptNoteInput = input(null, {
4428
+ ...ngDevMode ? { debugName: "receiptNoteInput" } : /* istanbul ignore next */ {},
4429
+ alias: "receiptNote"
4430
+ });
4431
+ this.receiptNote = computed(() => this.receiptNoteInput() ?? STRIPE_METHOD_TEXTS.receiptNote, ...ngDevMode ? [{ debugName: "receiptNote" }] : /* istanbul ignore next */ []);
4297
4432
  this.body = viewChild("body", ...ngDevMode ? [{ debugName: "body" }] : /* istanbul ignore next */ []);
4298
4433
  this.methods = this.methodList;
4299
4434
  this.template = this.body;
@@ -4372,8 +4507,8 @@ var StripePaymentMethodComponent = class StripePaymentMethodComponent extends Pa
4372
4507
  isRequired: false,
4373
4508
  transformFunction: null
4374
4509
  },
4375
- methodList: {
4376
- classPropertyName: "methodList",
4510
+ methodListInput: {
4511
+ classPropertyName: "methodListInput",
4377
4512
  publicName: "methodList",
4378
4513
  isSignal: true,
4379
4514
  isRequired: false,
@@ -4393,8 +4528,8 @@ var StripePaymentMethodComponent = class StripePaymentMethodComponent extends Pa
4393
4528
  isRequired: false,
4394
4529
  transformFunction: null
4395
4530
  },
4396
- receiptNote: {
4397
- classPropertyName: "receiptNote",
4531
+ receiptNoteInput: {
4532
+ classPropertyName: "receiptNoteInput",
4398
4533
  publicName: "receiptNote",
4399
4534
  isSignal: true,
4400
4535
  isRequired: false,
@@ -4512,7 +4647,7 @@ i0.ɵɵngDeclareClassMetadata({
4512
4647
  required: false
4513
4648
  }]
4514
4649
  }],
4515
- methodList: [{
4650
+ methodListInput: [{
4516
4651
  type: i0.Input,
4517
4652
  args: [{
4518
4653
  isSignal: true,
@@ -4536,7 +4671,7 @@ i0.ɵɵngDeclareClassMetadata({
4536
4671
  required: false
4537
4672
  }]
4538
4673
  }],
4539
- receiptNote: [{
4674
+ receiptNoteInput: [{
4540
4675
  type: i0.Input,
4541
4676
  args: [{
4542
4677
  isSignal: true,