@12-apps/payments-frontend 3.12.0 → 3.14.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ import { useState, type ReactNode } from 'react';
6
6
  import type { PlatformHomologationStatus } from '@12-apps/payments-backend';
7
7
 
8
8
  import { CARD_SX } from './ConnectEnvironmentCard';
9
+ import { usePlatformCopy } from './copy-context';
9
10
 
10
11
  /**
11
12
  * The homologação outcome record (FUT-483, packaged by FUT-573) — the durable
@@ -44,12 +45,6 @@ export interface HomologacaoSaveState {
44
45
  success: boolean;
45
46
  }
46
47
 
47
- const STATUS_LABEL: Record<PlatformHomologationStatus, string> = {
48
- SUBMITTED: 'Submitted',
49
- APPROVED: 'Approved',
50
- REJECTED: 'Rejected',
51
- };
52
-
53
48
  const STATUS_COLOR: Record<PlatformHomologationStatus, 'warning' | 'success' | 'error'> = {
54
49
  SUBMITTED: 'warning',
55
50
  APPROVED: 'success',
@@ -57,10 +52,11 @@ const STATUS_COLOR: Record<PlatformHomologationStatus, 'warning' | 'success' | '
57
52
  };
58
53
 
59
54
  function StatusChip({ record }: { record: PlatformHomologationRecordView | null }): ReactNode {
55
+ const copy = usePlatformCopy().outcome;
60
56
  if (record === null) {
61
57
  return (
62
58
  <Chip
63
- label="Not submitted"
59
+ label={copy.notSubmitted}
64
60
  size="small"
65
61
  variant="outlined"
66
62
  data-testid="homologacao-status-chip"
@@ -69,7 +65,7 @@ function StatusChip({ record }: { record: PlatformHomologationRecordView | null
69
65
  }
70
66
  return (
71
67
  <Chip
72
- label={STATUS_LABEL[record.status]}
68
+ label={copy.statuses[record.status] ?? record.status}
73
69
  size="small"
74
70
  color={STATUS_COLOR[record.status]}
75
71
  data-testid="homologacao-status-chip"
@@ -88,11 +84,12 @@ function StatusChip({ record }: { record: PlatformHomologationRecordView | null
88
84
  const formatDateTime = (iso: string): string => new Date(iso).toLocaleString();
89
85
 
90
86
  function RecordTrail({ record }: { record: PlatformHomologationRecordView }): ReactNode {
87
+ const copy = usePlatformCopy().outcome;
91
88
  return (
92
89
  <Typography variant="caption" color="text.secondary" component="p">
93
- {record.submittedAt ? `Submitted ${formatDateTime(record.submittedAt)}. ` : ''}
94
- {record.decidedAt ? `Decided ${formatDateTime(record.decidedAt)}. ` : ''}
95
- {record.updatedBy ? `Recorded by ${record.updatedBy}.` : ''}
90
+ {record.submittedAt ? copy.submittedAt(formatDateTime(record.submittedAt)) : ''}
91
+ {record.decidedAt ? copy.decidedAt(formatDateTime(record.decidedAt)) : ''}
92
+ {record.updatedBy ? copy.recordedBy(record.updatedBy) : ''}
96
93
  </Typography>
97
94
  );
98
95
  }
@@ -106,6 +103,7 @@ interface HomologacaoOutcomeCardProps {
106
103
 
107
104
  export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): ReactNode {
108
105
  const { record, onSave, save } = props;
106
+ const copy = usePlatformCopy().outcome;
109
107
  const [status, setStatus] = useState<PlatformHomologationStatus>(record?.status ?? 'SUBMITTED');
110
108
  const [protocol, setProtocol] = useState(record?.protocol ?? '');
111
109
  const [notes, setNotes] = useState(record?.notes ?? '');
@@ -114,7 +112,7 @@ export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): Reac
114
112
  <Stack spacing={1.5} data-testid="homologacao-outcome-card" sx={CARD_SX}>
115
113
  <Box sx={{ display: 'flex', alignItems: 'center', gap: 1.5 }}>
116
114
  <Typography variant="body2" fontWeight={600}>
117
- Homologation status
115
+ {copy.heading}
118
116
  </Typography>
119
117
  <StatusChip record={record} />
120
118
  </Box>
@@ -123,7 +121,7 @@ export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): Reac
123
121
  <TextField
124
122
  select
125
123
  size="small"
126
- label="Status"
124
+ label={copy.statusLabel}
127
125
  value={status}
128
126
  onChange={(event) => setStatus(event.target.value as PlatformHomologationStatus)}
129
127
  slotProps={{
@@ -131,24 +129,24 @@ export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): Reac
131
129
  htmlInput: { 'data-testid': 'homologacao-status-select' },
132
130
  }}
133
131
  >
134
- {(Object.keys(STATUS_LABEL) as PlatformHomologationStatus[]).map((key) => (
132
+ {(Object.keys(STATUS_COLOR) as PlatformHomologationStatus[]).map((key) => (
135
133
  <option key={key} value={key}>
136
- {STATUS_LABEL[key]}
134
+ {copy.statuses[key] ?? key}
137
135
  </option>
138
136
  ))}
139
137
  </TextField>
140
138
  <TextField
141
139
  size="small"
142
- aria-label="Protocol"
143
- placeholder="Protocol (Pipefy card / ticket)"
140
+ aria-label={copy.protocolLabel}
141
+ placeholder={copy.protocolPlaceholder}
144
142
  value={protocol}
145
143
  onChange={(event) => setProtocol(event.target.value)}
146
144
  slotProps={{ htmlInput: { 'data-testid': 'homologacao-protocol' } }}
147
145
  />
148
146
  <TextField
149
147
  size="small"
150
- aria-label="Notes"
151
- placeholder="Notes (PagBank's reply, context…)"
148
+ aria-label={copy.notesLabel}
149
+ placeholder={copy.notesPlaceholder}
152
150
  value={notes}
153
151
  onChange={(event) => setNotes(event.target.value)}
154
152
  slotProps={{ htmlInput: { 'data-testid': 'homologacao-notes' } }}
@@ -160,7 +158,7 @@ export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): Reac
160
158
  onClick={() => onSave({ status, protocol, notes })}
161
159
  data-testid="homologacao-save"
162
160
  >
163
- Record
161
+ {copy.save}
164
162
  </Button>
165
163
  </Box>
166
164
  {save.error !== null ? (
@@ -170,7 +168,7 @@ export function HomologacaoOutcomeCard(props: HomologacaoOutcomeCardProps): Reac
170
168
  ) : null}
171
169
  {save.success ? (
172
170
  <Alert severity="success" data-testid="homologacao-save-ok">
173
- Record updated.
171
+ {copy.saved}
174
172
  </Alert>
175
173
  ) : null}
176
174
  </Stack>
@@ -13,6 +13,8 @@ import {
13
13
  type HomologacaoSaveState,
14
14
  type PlatformHomologationRecordView,
15
15
  } from './HomologacaoOutcomeCard';
16
+ import type { PlatformHomologacaoCopy } from './copy';
17
+ import { PlatformCopyProvider, usePlatformCopy } from './copy-context';
16
18
 
17
19
  /**
18
20
  * The PLATFORM's PagBank homologação screen (FUT-483, packaged by FUT-573).
@@ -49,10 +51,13 @@ export interface PlatformHomologacaoProps {
49
51
  * card shows it verbatim.
50
52
  */
51
53
  onGenerateAnexo: () => Promise<void>;
54
+ /** Every word these three cards render. REQUIRED — no default copy. */
55
+ copy: PlatformHomologacaoCopy;
52
56
  }
53
57
 
54
58
  /** The evidence-file half: real sandbox calls, downloaded as a text file. */
55
59
  function AnexoCard({ onGenerate }: { onGenerate: () => Promise<void> }): ReactNode {
60
+ const copy = usePlatformCopy().anexo;
56
61
  const [error, setError] = useState<string | null>(null);
57
62
  const [busy, setBusy] = useState(false);
58
63
 
@@ -62,7 +67,7 @@ function AnexoCard({ onGenerate }: { onGenerate: () => Promise<void> }): ReactNo
62
67
  try {
63
68
  await onGenerate();
64
69
  } catch (cause) {
65
- setError(cause instanceof Error ? cause.message : 'Could not generate the attachment.');
70
+ setError(cause instanceof Error ? cause.message : copy.generateFailed);
66
71
  } finally {
67
72
  setBusy(false);
68
73
  }
@@ -71,13 +76,10 @@ function AnexoCard({ onGenerate }: { onGenerate: () => Promise<void> }): ReactNo
71
76
  return (
72
77
  <Stack spacing={1.5} data-testid="homologacao-anexo-card" sx={CARD_SX}>
73
78
  <Typography variant="body2" fontWeight={600}>
74
- Evidence attachment
79
+ {copy.heading}
75
80
  </Typography>
76
81
  <Typography variant="body2" color="text.secondary" component="p">
77
- The form demands the requests and responses of the calls sent to PagBank's APIs. The
78
- button below makes those calls for real against the test environment (Sandbox), on the
79
- platform's own token — nothing is actually charged — and downloads the file ready to
80
- attach, with the token redacted.
82
+ {copy.body}
81
83
  </Typography>
82
84
  <Box>
83
85
  <Button
@@ -87,7 +89,7 @@ function AnexoCard({ onGenerate }: { onGenerate: () => Promise<void> }): ReactNo
87
89
  onClick={() => void generate()}
88
90
  data-testid="homologacao-anexo-button"
89
91
  >
90
- Generate attachment
92
+ {copy.generate}
91
93
  </Button>
92
94
  </Box>
93
95
  {error !== null ? (
@@ -102,10 +104,12 @@ function AnexoCard({ onGenerate }: { onGenerate: () => Promise<void> }): ReactNo
102
104
  export function PlatformHomologacao(props: PlatformHomologacaoProps): ReactNode {
103
105
  const { record, guide, onSaveRecord, save, onGenerateAnexo } = props;
104
106
  return (
105
- <Stack spacing={2} data-testid="platform-homologacao">
106
- <HomologacaoOutcomeCard record={record} onSave={onSaveRecord} save={save} />
107
- <HomologacaoGuideCard guide={guide} />
108
- <AnexoCard onGenerate={onGenerateAnexo} />
109
- </Stack>
107
+ <PlatformCopyProvider copy={props.copy}>
108
+ <Stack spacing={2} data-testid="platform-homologacao">
109
+ <HomologacaoOutcomeCard record={record} onSave={onSaveRecord} save={save} />
110
+ <HomologacaoGuideCard guide={guide} />
111
+ <AnexoCard onGenerate={onGenerateAnexo} />
112
+ </Stack>
113
+ </PlatformCopyProvider>
110
114
  );
111
115
  }
@@ -0,0 +1,45 @@
1
+ 'use client';
2
+
3
+ import { createContext, useContext, type JSX, type ReactNode } from 'react';
4
+
5
+ import type { PlatformHomologacaoCopy } from './copy';
6
+
7
+ /**
8
+ * The platform screens' words, for the eight components that render them.
9
+ *
10
+ * A CONTEXT rather than a prop, for the same reason the settings surface uses
11
+ * one: this is a tree of small cards — the outcome form, the paste-ready
12
+ * answers, the anexo, the environment cards and the fields inside them — and
13
+ * threading one object through all of them as props is how a copy port comes
14
+ * to exist, be required, and go unread.
15
+ *
16
+ * It stays a single REQUIRED prop at the two mounts (`PlatformHomologacao` and
17
+ * `ConnectApplicationPanel`), which is the only place a host has to answer.
18
+ */
19
+ const PlatformCopyContext = createContext<PlatformHomologacaoCopy | null>(null);
20
+
21
+ export function PlatformCopyProvider({
22
+ copy,
23
+ children,
24
+ }: {
25
+ copy: PlatformHomologacaoCopy;
26
+ children: ReactNode;
27
+ }): JSX.Element {
28
+ return <PlatformCopyContext.Provider value={copy}>{children}</PlatformCopyContext.Provider>;
29
+ }
30
+
31
+ /**
32
+ * The words these screens render — THROWS outside a provider rather than
33
+ * falling back.
34
+ *
35
+ * A fallback could only be this package's own answer, handed silently to the
36
+ * next platform's operator. Failing at the mount is the point: it is the one
37
+ * moment a host can still be told it forgot.
38
+ */
39
+ export function usePlatformCopy(): PlatformHomologacaoCopy {
40
+ const copy = useContext(PlatformCopyContext);
41
+ if (!copy) {
42
+ throw new Error('usePlatformCopy must be rendered inside a <PlatformCopyProvider>');
43
+ }
44
+ return copy;
45
+ }
@@ -0,0 +1,113 @@
1
+ /**
2
+ * Every word the PLATFORM's homologação screens render.
3
+ *
4
+ * The reader here is not a buyer and not a merchant: it is whoever operates
5
+ * the platform, submitting a vendor homologação on behalf of every tenant on
6
+ * it. That made this surface look internal enough to write literals into for a
7
+ * long time, and it is not — a second platform adopting
8
+ * `@12-apps/payments-frontend` mounts these same four cards, and its operator
9
+ * reads whatever this package decided, in whatever language it decided.
10
+ *
11
+ * So the same rule as every other surface here: REQUIRED, no defaults. A pack
12
+ * for one language ships as `PT_BR_PLATFORM_HOMOLOGACAO_COPY` and a host
13
+ * passes it by hand.
14
+ *
15
+ * What is NOT here, deliberately: `HomologacaoGuide.fieldLabels` and the guide's
16
+ * three URLs. Those are PagBank's own form field names and pages, answered by
17
+ * the backend adapter, and a translation of them produces a submission their
18
+ * form does not accept.
19
+ */
20
+
21
+ /** The outcome card: what was submitted, and what came back. */
22
+ export interface HomologacaoOutcomeCopy {
23
+ heading: string;
24
+ /** The status a record carries — and what "no record at all" reads as. */
25
+ statusLabel: string;
26
+ notSubmitted: string;
27
+ /** The two free-text fields, each with a visible-less input. */
28
+ protocolLabel: string;
29
+ protocolPlaceholder: string;
30
+ notesLabel: string;
31
+ notesPlaceholder: string;
32
+ /** Save, and the confirmation after it. */
33
+ save: string;
34
+ saved: string;
35
+ /** The three statuses a record can carry, keyed by the stored value. */
36
+ statuses: Readonly<Record<string, string>>;
37
+ /**
38
+ * The trail under the heading, one clause per timestamp the record has. Each
39
+ * takes its own value because the ORDER of word and date differs by language
40
+ * and this line concatenates whichever clauses exist.
41
+ */
42
+ submittedAt(when: string): string;
43
+ decidedAt(when: string): string;
44
+ recordedBy(who: string): string;
45
+ }
46
+
47
+ /** The paste-ready answers card, and the three links woven through its lede. */
48
+ export interface HomologacaoGuideCopy {
49
+ heading: string;
50
+ /**
51
+ * The instruction paragraph, in the runs it renders as: text, link, text,
52
+ * link, text, link, text. Split because two of the links sit MID-SENTENCE,
53
+ * so a single string with placeholders could not carry them.
54
+ */
55
+ ledeBeforeForm: string;
56
+ formLink: string;
57
+ ledeBeforeSupport: string;
58
+ supportLink: string;
59
+ ledeBeforeDocs: string;
60
+ docsLink: string;
61
+ ledeAfterDocs: string;
62
+ }
63
+
64
+ /** The evidence-file card. */
65
+ export interface HomologacaoAnexoCopy {
66
+ heading: string;
67
+ body: string;
68
+ generate: string;
69
+ /** A generate that threw something carrying no message of its own. */
70
+ generateFailed: string;
71
+ }
72
+
73
+ /** The Connect application panel, and the environment card under it. */
74
+ export interface ConnectApplicationCopy {
75
+ /** The callback the deployment uses — the value that must be registered. */
76
+ expectedRedirectHeading: string;
77
+ consultAgain: string;
78
+ /** No application resolved for this environment at all. */
79
+ noApplication: string;
80
+ /**
81
+ * The three verdicts on the registered `redirect_uri`: it matches, it does
82
+ * not, or PagBank reported none to compare against. A mismatch is the whole
83
+ * reason this card exists, so all three read as findings rather than states.
84
+ */
85
+ redirectMatches: string;
86
+ redirectDiffers: string;
87
+ redirectUnreported: string;
88
+ /** The application's own fields, as PagBank reports them. */
89
+ fields: {
90
+ name: string;
91
+ site: string;
92
+ description: string;
93
+ logo: string;
94
+ redirectUri: string;
95
+ };
96
+ /** What a field with no value reads as, and an unreported redirect_uri. */
97
+ fieldEmpty: string;
98
+ redirectNotReported: string;
99
+ /** Where the environment's application comes from, and its disclosure. */
100
+ resolvedFrom: string;
101
+ showConfig: string;
102
+ hideConfig: string;
103
+ /** The heading above whatever extra keys PagBank's response carried. */
104
+ extraKeys: string;
105
+ }
106
+
107
+ /** The whole platform surface, in one object a host passes at the mount. */
108
+ export interface PlatformHomologacaoCopy {
109
+ outcome: HomologacaoOutcomeCopy;
110
+ guide: HomologacaoGuideCopy;
111
+ anexo: HomologacaoAnexoCopy;
112
+ connect: ConnectApplicationCopy;
113
+ }
@@ -0,0 +1,93 @@
1
+ import type { PlatformHomologacaoCopy } from './copy';
2
+
3
+ /**
4
+ * The en-US pack for the platform's homologação screens.
5
+ *
6
+ * A NAMED pack, which is how this repo ships a language: a host imports it and
7
+ * passes it by hand.
8
+ *
9
+ * ## What is translated here, and what is not
10
+ *
11
+ * These screens are read by the platform OPERATOR filling PagBank's form, and
12
+ * that is what the words are for — so the instructions, headings and statuses
13
+ * are English here.
14
+ *
15
+ * What stays is everything the operator has to MATCH against PagBank's own
16
+ * surfaces: `redirect_uri` is the parameter name in the API response, "SIP" and
17
+ * "Pipefy" are the names of the systems they will open, `ACCESS_DENIED` is the
18
+ * error string they are quoting in the ticket, and "homologação" is what
19
+ * PagBank calls the process — an operator searching support for
20
+ * "homologation" finds nothing.
21
+ *
22
+ * The ANSWERS the form is filled with are a different matter and are not here
23
+ * at all: they live in `@12-apps/payments-backend`'s `PT_BR_HOMOLOGACAO_ANSWERS`
24
+ * and stay Portuguese, because a PagBank reviewer reads them and several are
25
+ * multiple-choice options on the form itself.
26
+ */
27
+ export const EN_US_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
28
+ outcome: {
29
+ heading: 'Homologação status',
30
+ statusLabel: 'Status',
31
+ notSubmitted: 'Not submitted',
32
+ protocolLabel: 'Protocol',
33
+ protocolPlaceholder: 'Protocol (Pipefy card / ticket)',
34
+ notesLabel: 'Notes',
35
+ notesPlaceholder: "Notes (PagBank's reply, context…)",
36
+ save: 'Record',
37
+ saved: 'Record updated.',
38
+ // The KEYS are the stored status values, not words.
39
+ statuses: { SUBMITTED: 'Submitted', APPROVED: 'Approved', REJECTED: 'Rejected' },
40
+ // Three fragments the screen concatenates into one line, so the first two
41
+ // keep their trailing space and the last one ends the sentence.
42
+ submittedAt: (when) => `Submitted ${when}. `,
43
+ decidedAt: (when) => `Decided ${when}. `,
44
+ recordedBy: (who) => `Recorded by ${who}.`,
45
+ },
46
+ guide: {
47
+ heading: 'Homologação form — answers ready to paste',
48
+ // Five fragments wrapping two links. Each keeps its own leading or
49
+ // trailing space; a translation that made them whole sentences would break
50
+ // the line the screen actually renders.
51
+ ledeBeforeForm: 'Open the ',
52
+ formLink: 'official homologação form',
53
+ ledeBeforeSupport: ' and fill it in with the values below. In parallel, open a ticket on ',
54
+ supportLink: 'SIP — PagBank integration support',
55
+ ledeBeforeDocs:
56
+ ' quoting the 403 ACCESS_DENIED: what you answer first decides whether the form covers Connect. Documentation: ',
57
+ docsLink: 'requesting homologação',
58
+ ledeAfterDocs: '.',
59
+ },
60
+ anexo: {
61
+ heading: 'Evidence attachment',
62
+ body:
63
+ "The form asks for the requests and responses of the calls sent to PagBank's APIs. The file is generated from this platform's real calls, with the token redacted.",
64
+ generate: 'Generate attachment',
65
+ generateFailed: 'Could not generate the attachment.',
66
+ },
67
+ connect: {
68
+ expectedRedirectHeading: 'The callback this deploy uses (the value that must be registered)',
69
+ consultAgain: 'Look it up again',
70
+ noApplication: 'No application configured in this environment.',
71
+ // `redirect_uri` is the parameter name in PagBank's own response — an
72
+ // operator compares the two strings character by character.
73
+ redirectMatches: 'The registered redirect_uri matches the callback this deploy uses.',
74
+ redirectDiffers:
75
+ 'The redirect_uri registered with PagBank differs from the callback this deploy uses.',
76
+ redirectUnreported:
77
+ "PagBank's response carried no redirect_uri, so it could not be compared with the callback.",
78
+ fields: {
79
+ name: 'Name (shown to the store owner)',
80
+ site: 'Site',
81
+ description: 'Description',
82
+ logo: 'Logo',
83
+ redirectUri: 'registered redirect_uri',
84
+ },
85
+ fieldEmpty: '—',
86
+ redirectNotReported: 'not reported',
87
+ resolvedFrom:
88
+ "This environment's application is resolved strictly from these variables, with no fallback between environments:",
89
+ showConfig: 'Show environment variables',
90
+ hideConfig: 'Hide environment variables',
91
+ extraKeys: 'Other fields returned',
92
+ },
93
+ };
@@ -0,0 +1,73 @@
1
+ import type { PlatformHomologacaoCopy } from './copy';
2
+
3
+ /**
4
+ * The pt-BR pack for the platform's homologação screens.
5
+ *
6
+ * A NAMED pack, which is how this repo ships a language: a host imports it and
7
+ * passes it by hand, so choosing Portuguese is a line in that host's diff
8
+ * rather than a silence in this package.
9
+ *
10
+ * The English these screens rendered as literals is deliberately NOT what this
11
+ * pack says. Those sentences were written for a developer reading the code;
12
+ * these are written for the operator filling PagBank's form, which is the
13
+ * register the surface is actually in.
14
+ */
15
+ export const PT_BR_PLATFORM_HOMOLOGACAO_COPY: PlatformHomologacaoCopy = {
16
+ outcome: {
17
+ heading: 'Situação da homologação',
18
+ statusLabel: 'Situação',
19
+ notSubmitted: 'Não enviada',
20
+ protocolLabel: 'Protocolo',
21
+ protocolPlaceholder: 'Protocolo (card do Pipefy / chamado)',
22
+ notesLabel: 'Observações',
23
+ notesPlaceholder: 'Observações (resposta do PagBank, contexto…)',
24
+ save: 'Registrar',
25
+ saved: 'Registro atualizado.',
26
+ statuses: { SUBMITTED: 'Enviada', APPROVED: 'Aprovada', REJECTED: 'Recusada' },
27
+ submittedAt: (when) => `Enviada em ${when}. `,
28
+ decidedAt: (when) => `Decidida em ${when}. `,
29
+ recordedBy: (who) => `Registrado por ${who}.`,
30
+ },
31
+ guide: {
32
+ heading: 'Formulário de homologação — respostas prontas para colar',
33
+ ledeBeforeForm: 'Abra o ',
34
+ formLink: 'formulário oficial de homologação',
35
+ ledeBeforeSupport: ' e preencha com os valores abaixo. Em paralelo, abra um chamado no ',
36
+ supportLink: 'SIP — suporte de integração PagBank',
37
+ ledeBeforeDocs:
38
+ ' citando o 403 ACCESS_DENIED: o que responder primeiro define se o formulário cobre o Connect. Documentação: ',
39
+ docsLink: 'solicitar homologação',
40
+ ledeAfterDocs: '.',
41
+ },
42
+ anexo: {
43
+ heading: 'Anexo de evidências',
44
+ body:
45
+ 'O formulário pede as requisições e as respostas das chamadas enviadas às APIs do PagBank. O arquivo é gerado a partir das chamadas reais desta plataforma, com o token redigido.',
46
+ generate: 'Gerar anexo',
47
+ generateFailed: 'Não foi possível gerar o anexo.',
48
+ },
49
+ connect: {
50
+ expectedRedirectHeading: 'Callback que este deploy usa (o valor que precisa estar registrado)',
51
+ consultAgain: 'Consultar de novo',
52
+ noApplication: 'Nenhuma aplicação configurada neste ambiente.',
53
+ redirectMatches: 'O redirect_uri registrado confere com o callback que este deploy usa.',
54
+ redirectDiffers:
55
+ 'O redirect_uri registrado no PagBank é diferente do callback que este deploy usa.',
56
+ redirectUnreported:
57
+ 'A resposta do PagBank não trouxe redirect_uri, então não foi possível comparar com o callback.',
58
+ fields: {
59
+ name: 'Nome (exibido ao lojista)',
60
+ site: 'Site',
61
+ description: 'Descrição',
62
+ logo: 'Logo',
63
+ redirectUri: 'redirect_uri registrado',
64
+ },
65
+ fieldEmpty: '—',
66
+ redirectNotReported: 'não informado',
67
+ resolvedFrom:
68
+ 'A aplicação deste ambiente é resolvida estritamente a partir destas variáveis, sem fallback entre ambientes:',
69
+ showConfig: 'Mostrar variáveis de ambiente',
70
+ hideConfig: 'Ocultar variáveis de ambiente',
71
+ extraKeys: 'Outros campos retornados',
72
+ },
73
+ };
@@ -289,6 +289,12 @@ export interface SetupGuideCopy {
289
289
  confirmedByYou: string;
290
290
  /** Reopen a section the owner already confirmed. */
291
291
  reviewAction: string;
292
+ /**
293
+ * The sentence beside the confirm button. It exists because the owner is
294
+ * vouching for work done in the PROVIDER's dashboard, not here — a bare
295
+ * button gives them nothing to weigh that against.
296
+ */
297
+ confirmPrompt: string;
292
298
  /**
293
299
  * The copy-to-clipboard button beside a reference value, and what it says
294
300
  * for the two seconds after a successful copy.