@vinaverse/tokens 0.1.0-alpha.10 → 0.1.0-alpha.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -18,7 +18,10 @@ property is the path without its mode, kebab-cased (`cssVariable('color.light.ag
18
18
 
19
19
  `@vinaverse/tokens/copy` holds the words every kit says (English, Spanish, Brazilian Portuguese), with the rules on
20
20
  them: a tenant's overrides on top, never the AI disclosure in a built-in language and in another only a translation
21
- that still discloses; never "assistant", "bot" or "crew". Also the locale's text direction and Intl formatting.
21
+ that still discloses; never "assistant", "bot" or "crew". A count of 1 reads in its own form ("1 message", "1
22
+ character left"): a key with a `One` sibling (`historyMessagesOne`) says it when `count` is 1. A tenant that overrides
23
+ the counted words gives the `One` form too, or theirs is said at every count. Also the locale's text direction and Intl
24
+ formatting.
22
25
 
23
26
  How the kits use them: [docs/architecture/ui-kits.md](../../docs/architecture/ui-kits.md).
24
27
 
@@ -51,6 +51,7 @@ var en = {
51
51
  questionStep: "Question {step} of {total}",
52
52
  questionAddPhoto: "Add a photo",
53
53
  questionCharactersLeft: "{count} characters left",
54
+ questionCharactersLeftOne: "{count} character left",
54
55
  priceFrom: "From {price}",
55
56
  /** A listing with no rating yet; empty draws nothing, a tenant's word ("New") draws in the rating's place. */
56
57
  ratingNone: "",
@@ -75,7 +76,28 @@ var en = {
75
76
  welcomeFallback: "Hi, I'm {agent}. How can I help?",
76
77
  privacy: "Privacy",
77
78
  cardsInRow: "{count} results, swipe for more",
78
- open: "Open"
79
+ cardsInRowOne: "{count} result",
80
+ open: "Open",
81
+ /** History: the person's past conversations, and reading one back. */
82
+ historyEmpty: "No conversations yet",
83
+ historyEmptyBody: "Your conversations with {agent} will show here.",
84
+ historyFailed: "Couldn't load your conversations.",
85
+ historyOff: "History is not available.",
86
+ historyMessages: "{count} messages",
87
+ historyMessagesOne: "{count} message",
88
+ historyEnded: "Ended",
89
+ historyContinue: "Continue",
90
+ historyDelete: "Delete",
91
+ historyDeleteTitle: "Delete this conversation?",
92
+ historyDeleteBody: "It's removed from your history everywhere.",
93
+ historyDeleteFailed: "Couldn't delete this conversation.",
94
+ cancel: "Cancel",
95
+ transcriptFailed: "Couldn't load this conversation.",
96
+ transcriptGone: "This conversation is no longer available.",
97
+ transcriptEarlier: "Earlier messages",
98
+ /** Under the person's message a guardrail refused. */
99
+ messageRefused: "Not answered",
100
+ loading: "Loading\u2026"
79
101
  };
80
102
  var es = {
81
103
  disclosureFallback: "Est\xE1s hablando con un agente de IA. Con la tecnolog\xEDa de Vinaverse.",
@@ -127,6 +149,7 @@ var es = {
127
149
  questionStep: "Pregunta {step} de {total}",
128
150
  questionAddPhoto: "Agregar una foto",
129
151
  questionCharactersLeft: "Quedan {count} caracteres",
152
+ questionCharactersLeftOne: "Queda {count} car\xE1cter",
130
153
  priceFrom: "Desde {price}",
131
154
  ratingNone: "",
132
155
  nextAvailable: "Pr\xF3ximo: {time}",
@@ -149,7 +172,26 @@ var es = {
149
172
  welcomeFallback: "Hola, soy {agent}. \xBFEn qu\xE9 te ayudo?",
150
173
  privacy: "Privacidad",
151
174
  cardsInRow: "{count} resultados, desliza para ver m\xE1s",
152
- open: "Abrir"
175
+ cardsInRowOne: "{count} resultado",
176
+ open: "Abrir",
177
+ historyEmpty: "A\xFAn no hay conversaciones",
178
+ historyEmptyBody: "Tus conversaciones con {agent} aparecer\xE1n aqu\xED.",
179
+ historyFailed: "No se pudieron cargar tus conversaciones.",
180
+ historyOff: "El historial no est\xE1 disponible.",
181
+ historyMessages: "{count} mensajes",
182
+ historyMessagesOne: "{count} mensaje",
183
+ historyEnded: "Terminada",
184
+ historyContinue: "Continuar",
185
+ historyDelete: "Eliminar",
186
+ historyDeleteTitle: "\xBFEliminar esta conversaci\xF3n?",
187
+ historyDeleteBody: "Se elimina de tu historial en todas partes.",
188
+ historyDeleteFailed: "No se pudo eliminar esta conversaci\xF3n.",
189
+ cancel: "Cancelar",
190
+ transcriptFailed: "No se pudo cargar esta conversaci\xF3n.",
191
+ transcriptGone: "Esta conversaci\xF3n ya no est\xE1 disponible.",
192
+ transcriptEarlier: "Mensajes anteriores",
193
+ messageRefused: "Sin respuesta",
194
+ loading: "Cargando\u2026"
153
195
  };
154
196
  var ptBR = {
155
197
  disclosureFallback: "Voc\xEA est\xE1 conversando com um agente de IA. Com tecnologia Vinaverse.",
@@ -201,6 +243,7 @@ var ptBR = {
201
243
  questionStep: "Pergunta {step} de {total}",
202
244
  questionAddPhoto: "Adicionar uma foto",
203
245
  questionCharactersLeft: "Restam {count} caracteres",
246
+ questionCharactersLeftOne: "Resta {count} caractere",
204
247
  priceFrom: "A partir de {price}",
205
248
  ratingNone: "",
206
249
  nextAvailable: "Pr\xF3ximo hor\xE1rio: {time}",
@@ -223,7 +266,26 @@ var ptBR = {
223
266
  welcomeFallback: "Oi, sou {agent}. Como posso ajudar?",
224
267
  privacy: "Privacidade",
225
268
  cardsInRow: "{count} resultados, deslize para ver mais",
226
- open: "Abrir"
269
+ cardsInRowOne: "{count} resultado",
270
+ open: "Abrir",
271
+ historyEmpty: "Nenhuma conversa ainda",
272
+ historyEmptyBody: "Suas conversas com {agent} v\xE3o aparecer aqui.",
273
+ historyFailed: "N\xE3o foi poss\xEDvel carregar suas conversas.",
274
+ historyOff: "O hist\xF3rico n\xE3o est\xE1 dispon\xEDvel.",
275
+ historyMessages: "{count} mensagens",
276
+ historyMessagesOne: "{count} mensagem",
277
+ historyEnded: "Encerrada",
278
+ historyContinue: "Continuar",
279
+ historyDelete: "Excluir",
280
+ historyDeleteTitle: "Excluir esta conversa?",
281
+ historyDeleteBody: "Ela \xE9 removida do seu hist\xF3rico em todos os lugares.",
282
+ historyDeleteFailed: "N\xE3o foi poss\xEDvel excluir esta conversa.",
283
+ cancel: "Cancelar",
284
+ transcriptFailed: "N\xE3o foi poss\xEDvel carregar esta conversa.",
285
+ transcriptGone: "Esta conversa n\xE3o est\xE1 mais dispon\xEDvel.",
286
+ transcriptEarlier: "Mensagens anteriores",
287
+ messageRefused: "Sem resposta",
288
+ loading: "Carregando\u2026"
227
289
  };
228
290
  var COPY = {
229
291
  en,
@@ -257,8 +319,9 @@ function createTranslate(locale, overrides = {}) {
257
319
  if (FIXED.has(key) && !(own === null && discloses(key, value)))
258
320
  continue;
259
321
  merged[key] = value;
322
+ if (!(`${key}One` in overrides)) delete merged[`${key}One`];
260
323
  }
261
- return (key, vars) => (merged[key] ?? en[key]).replace(
324
+ return (key, vars) => ((vars?.count === 1 ? merged[`${key}One`] : void 0) ?? merged[key] ?? en[key]).replace(
262
325
  /\{(\w+)\}/g,
263
326
  (all, name) => vars && name in vars ? String(vars[name]) : all
264
327
  );
@@ -375,6 +438,19 @@ function formatDate(date, locale) {
375
438
  return date;
376
439
  }
377
440
  }
441
+ function formatDateTime(at, locale, timeZone) {
442
+ const date = new Date(at);
443
+ if (Number.isNaN(date.getTime())) return at;
444
+ try {
445
+ return new Intl.DateTimeFormat(locale, {
446
+ dateStyle: "medium",
447
+ timeStyle: "short",
448
+ ...timeZone ? { timeZone } : {}
449
+ }).format(date);
450
+ } catch {
451
+ return date.toISOString();
452
+ }
453
+ }
378
454
 
379
455
  exports.AI_MARK = AI_MARK;
380
456
  exports.BANNED_WORDS = BANNED_WORDS;
@@ -383,6 +459,7 @@ exports.bannedWordsIn = bannedWordsIn;
383
459
  exports.builtInCopy = builtInCopy;
384
460
  exports.createTranslate = createTranslate;
385
461
  exports.formatDate = formatDate;
462
+ exports.formatDateTime = formatDateTime;
386
463
  exports.formatDayTime = formatDayTime;
387
464
  exports.formatMoney = formatMoney;
388
465
  exports.formatTimeRange = formatTimeRange;
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/copy/copy.ts","../../src/copy/format.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// The words a Vinaverse UI says, in English, Spanish and Brazilian Portuguese, each overridable by the tenant except\n// the fallback disclosure. People first: \"agent\", never \"assistant\"; a person from the business is a person, by role.\n// `{name}` placeholders are filled from `vars`.\n\nconst en = {\n disclosureFallback: \"You're chatting with an AI agent. Powered by Vinaverse.\",\n agentLabel: 'AI agent',\n agentFallbackName: 'the agent',\n you: 'You',\n staffLabel: '{by} · person',\n staffFallbackRole: 'the team',\n composerPlaceholder: 'Message {agent}',\n composerPlaceholderTakeover: 'Message {by}',\n send: 'Send',\n stop: 'Stop',\n typeAnswerBelow: 'Type your answer below.',\n bannerConnecting: 'Connecting…',\n bannerReconnecting: 'Reconnecting…',\n bannerOffline: \"You're offline. Messages send when you're back.\",\n bannerContinuedElsewhere: 'This conversation continued on another device.',\n bannerUnavailable: \"Couldn't connect.\",\n continueHere: 'Continue here',\n tryAgain: 'Try again',\n talkToPerson: 'Talk to a person',\n messageSending: 'Sending',\n messageHeld: 'Sends when you continue',\n messageNotSent: 'Not sent',\n messageDelivered: 'Delivered',\n messageCutOff: 'This reply was cut off.',\n takeoverStarted: 'A person from {by} is replying now.',\n takeoverEnded: '{agent} is back.',\n handoffCreated: \"We've passed this to the team. They'll reply {expected}.\",\n handoffCreatedNoTime: \"We've passed this to the team. They'll reply soon.\",\n flowSent: 'Your answers were sent.',\n flowNotSent: \"Your answers couldn't be sent yet.\",\n turnFailed: 'Something went wrong.',\n working: '{agent} is working on it…',\n proposalConfirm: 'Confirm',\n proposalDecline: 'Decline',\n proposalChange: 'Change',\n proposalConfirmed: 'Confirmed',\n proposalDeclined: 'Declined',\n proposalFailed: \"Couldn't be confirmed\",\n proposalExpired: 'Expired',\n proposalSettled: 'No longer open',\n questionSubmit: 'Send',\n questionSkip: 'Skip',\n questionOther: 'Other',\n questionSearch: 'Search',\n questionAnswered: 'Answered',\n questionReplaced: 'Replaced by a newer question',\n questionStep: 'Question {step} of {total}',\n questionAddPhoto: 'Add a photo',\n questionCharactersLeft: '{count} characters left',\n priceFrom: 'From {price}',\n /** A listing with no rating yet; empty draws nothing, a tenant's word (\"New\") draws in the rating's place. */\n ratingNone: '',\n nextAvailable: 'Next: {time}',\n /** A time today and tomorrow, as `nextAvailable` says it (`{time}`: \"10:00 AM\"). */\n today: 'today, {time}',\n tomorrow: 'tomorrow, {time}',\n agentEnded: 'This conversation ended',\n agentEndedBody: 'Start a new one whenever you like.',\n agentStartOver: 'Start a new conversation',\n agentUnreachable: \"Couldn't reach {agent}\",\n agentUnreachableBody: 'Check your connection and try again.',\n agentOff: \"{agent} isn't available right now\",\n agentOffBody: 'Please try again later.',\n helpful: 'Was this helpful?',\n helpfulYes: 'Yes',\n helpfulNo: 'No',\n helpfulThanks: 'Thanks for telling us.',\n launcherOpen: 'Open {agent}',\n launcherGreeting: \"Hi, I'm {agent}. Ask me what you need.\",\n close: 'Close',\n welcomeFallback: \"Hi, I'm {agent}. How can I help?\",\n privacy: 'Privacy',\n cardsInRow: '{count} results, swipe for more',\n open: 'Open',\n} as const;\n\nexport type CopyKey = keyof typeof en;\nexport type Copy = Readonly<Record<CopyKey, string>>;\n/** A tenant's words, by key; a key left out (or undefined) keeps the built-in one. */\nexport type CopyOverrides = { readonly [K in CopyKey]?: string | undefined };\n\nconst es: Copy = {\n disclosureFallback:\n 'Estás hablando con un agente de IA. Con la tecnología de Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'el agente',\n you: 'Tú',\n staffLabel: '{by} · persona',\n staffFallbackRole: 'el equipo',\n composerPlaceholder: 'Escribe a {agent}',\n composerPlaceholderTakeover: 'Escribe a {by}',\n send: 'Enviar',\n stop: 'Detener',\n typeAnswerBelow: 'Escribe tu respuesta abajo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sin conexión. Los mensajes se envían cuando vuelvas.',\n bannerContinuedElsewhere: 'Esta conversación continuó en otro dispositivo.',\n bannerUnavailable: 'No se pudo conectar.',\n continueHere: 'Continuar aquí',\n tryAgain: 'Intentar de nuevo',\n talkToPerson: 'Hablar con una persona',\n messageSending: 'Enviando',\n messageHeld: 'Se envía cuando continúes',\n messageNotSent: 'No enviado',\n messageDelivered: 'Entregado',\n messageCutOff: 'Esta respuesta quedó incompleta.',\n takeoverStarted: 'Una persona de {by} está respondiendo.',\n takeoverEnded: '{agent} volvió.',\n handoffCreated: 'Le pasamos esto al equipo. Responderán {expected}.',\n handoffCreatedNoTime: 'Le pasamos esto al equipo. Responderán pronto.',\n flowSent: 'Tus respuestas se enviaron.',\n flowNotSent: 'Tus respuestas aún no se pudieron enviar.',\n turnFailed: 'Algo salió mal.',\n working: '{agent} está en ello…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Rechazar',\n proposalChange: 'Cambiar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Rechazado',\n proposalFailed: 'No se pudo confirmar',\n proposalExpired: 'Vencido',\n proposalSettled: 'Ya no está abierto',\n questionSubmit: 'Enviar',\n questionSkip: 'Omitir',\n questionOther: 'Otro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Reemplazada por una pregunta más reciente',\n questionStep: 'Pregunta {step} de {total}',\n questionAddPhoto: 'Agregar una foto',\n questionCharactersLeft: 'Quedan {count} caracteres',\n priceFrom: 'Desde {price}',\n ratingNone: '',\n nextAvailable: 'Próximo: {time}',\n today: 'hoy, {time}',\n tomorrow: 'mañana, {time}',\n agentEnded: 'Esta conversación terminó',\n agentEndedBody: 'Empieza una nueva cuando quieras.',\n agentStartOver: 'Empezar una conversación nueva',\n agentUnreachable: 'No se pudo contactar a {agent}',\n agentUnreachableBody: 'Revisa tu conexión e inténtalo de nuevo.',\n agentOff: '{agent} no está disponible ahora',\n agentOffBody: 'Inténtalo de nuevo más tarde.',\n helpful: '¿Te sirvió?',\n helpfulYes: 'Sí',\n helpfulNo: 'No',\n helpfulThanks: 'Gracias por contarnos.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Hola, soy {agent}. Pregúntame lo que necesites.',\n close: 'Cerrar',\n welcomeFallback: 'Hola, soy {agent}. ¿En qué te ayudo?',\n privacy: 'Privacidad',\n cardsInRow: '{count} resultados, desliza para ver más',\n open: 'Abrir',\n};\n\nconst ptBR: Copy = {\n disclosureFallback:\n 'Você está conversando com um agente de IA. Com tecnologia Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'o agente',\n you: 'Você',\n staffLabel: '{by} · pessoa',\n staffFallbackRole: 'a equipe',\n composerPlaceholder: 'Mensagem para {agent}',\n composerPlaceholderTakeover: 'Mensagem para {by}',\n send: 'Enviar',\n stop: 'Parar',\n typeAnswerBelow: 'Digite sua resposta abaixo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sem conexão. As mensagens são enviadas quando você voltar.',\n bannerContinuedElsewhere: 'Esta conversa continuou em outro aparelho.',\n bannerUnavailable: 'Não foi possível conectar.',\n continueHere: 'Continuar aqui',\n tryAgain: 'Tentar de novo',\n talkToPerson: 'Falar com uma pessoa',\n messageSending: 'Enviando',\n messageHeld: 'Será enviada quando você continuar',\n messageNotSent: 'Não enviada',\n messageDelivered: 'Entregue',\n messageCutOff: 'Esta resposta foi interrompida.',\n takeoverStarted: 'Uma pessoa de {by} está respondendo agora.',\n takeoverEnded: '{agent} voltou.',\n handoffCreated: 'Passamos isso para a equipe. Eles vão responder {expected}.',\n handoffCreatedNoTime:\n 'Passamos isso para a equipe. Eles vão responder em breve.',\n flowSent: 'Suas respostas foram enviadas.',\n flowNotSent: 'Ainda não foi possível enviar suas respostas.',\n turnFailed: 'Algo deu errado.',\n working: '{agent} está cuidando disso…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Recusar',\n proposalChange: 'Alterar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Recusado',\n proposalFailed: 'Não foi possível confirmar',\n proposalExpired: 'Expirado',\n proposalSettled: 'Não está mais aberto',\n questionSubmit: 'Enviar',\n questionSkip: 'Pular',\n questionOther: 'Outro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Substituída por uma pergunta mais recente',\n questionStep: 'Pergunta {step} de {total}',\n questionAddPhoto: 'Adicionar uma foto',\n questionCharactersLeft: 'Restam {count} caracteres',\n priceFrom: 'A partir de {price}',\n ratingNone: '',\n nextAvailable: 'Próximo horário: {time}',\n today: 'hoje, {time}',\n tomorrow: 'amanhã, {time}',\n agentEnded: 'Esta conversa terminou',\n agentEndedBody: 'Comece uma nova quando quiser.',\n agentStartOver: 'Começar uma conversa nova',\n agentUnreachable: 'Não foi possível falar com {agent}',\n agentUnreachableBody: 'Verifique sua conexão e tente de novo.',\n agentOff: '{agent} não está disponível agora',\n agentOffBody: 'Tente de novo mais tarde.',\n helpful: 'Isso ajudou?',\n helpfulYes: 'Sim',\n helpfulNo: 'Não',\n helpfulThanks: 'Obrigado por avisar.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Oi, sou {agent}. Pergunte o que precisar.',\n close: 'Fechar',\n welcomeFallback: 'Oi, sou {agent}. Como posso ajudar?',\n privacy: 'Privacidade',\n cardsInRow: '{count} resultados, deslize para ver mais',\n open: 'Abrir',\n};\n\n/** The built-in languages; any other locale falls back to English, its own `copy` overrides aside. */\nexport const COPY: Readonly<Record<'en' | 'es' | 'pt-BR', Copy>> = {\n en,\n es,\n 'pt-BR': ptBR,\n};\n\n/**\n * Keys a tenant may not override in a built-in language: the AI disclosure is the platform's, never removed or reworded.\n * In a language without built-in copy the tenant supplies them, translated, so the disclosure reads in the person's\n * language, and only a translation that still discloses is taken (`discloses`): the label says AI, the disclosure says\n * AI and names Vinaverse.\n */\nconst FIXED: ReadonlySet<CopyKey> = new Set([\n 'disclosureFallback',\n 'agentLabel',\n]);\n\n/**\n * \"AI\" as languages write it: AI, IA (es, pt, fr, it, ro), KI (de, nl, da, no, sv), SI (pl), YZ (tr), ИИ (ru), ШІ\n * (uk), and the words for it in Arabic, Hebrew, Hindi, Chinese, Japanese and Korean.\n */\nexport const AI_MARK =\n /(?:^|[^\\p{L}])(?:AI|IA|KI|SI|YZ|ИИ|ШІ)(?:$|[^\\p{L}])|الذكاء الاصطناعي|بالذكاء|בינה מלאכותית|एआई|कृत्रिम बुद्धि|人工智能|人工知能|인공지능/u;\n\n/**\n * Whether a tenant's text for a fixed key still makes the AI disclosure: the label says AI; the disclosure says AI\n * and names Vinaverse. A tenant's translation that does not is ignored, and the English built-in shows instead.\n */\nfunction discloses(key: string, value: string): boolean {\n if (!AI_MARK.test(value)) return false;\n return key !== 'disclosureFallback' || value.includes('Vinaverse');\n}\n\nexport type Translate = (\n key: CopyKey,\n vars?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The built-in copy for a locale: its language (`es-US` → `es`, `pt-PT` → `pt-BR`), else null. */\nfunction builtIn(locale: string | undefined): Copy | null {\n const language = (locale ?? 'en').split(/[-_]/)[0]?.toLowerCase();\n if (language === 'en') return COPY.en;\n if (language === 'es') return COPY.es;\n if (language === 'pt') return COPY['pt-BR'];\n return null;\n}\n\n/** The built-in copy for a locale, English when the language has none. */\nexport function builtInCopy(locale: string | undefined): Copy {\n return builtIn(locale) ?? COPY.en;\n}\n\n/** A translator for a locale, with the tenant's overrides on top (fixed keys excepted). */\nexport function createTranslate(\n locale: string | undefined,\n overrides: CopyOverrides = {},\n): Translate {\n const own = builtIn(locale);\n const merged: Record<string, string> = { ...(own ?? COPY.en) };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === undefined) continue;\n if (FIXED.has(key as CopyKey) && !(own === null && discloses(key, value)))\n continue;\n merged[key] = value;\n }\n return (key, vars) =>\n (merged[key] ?? en[key]).replace(/\\{(\\w+)\\}/g, (all, name: string) =>\n vars && name in vars ? String(vars[name]) : all,\n );\n}\n\n/**\n * Words a Vinaverse UI never says to people (a tenant override that uses them gets a development warning): the\n * runtime is an agent, never an assistant or a bot; and never \"crew\".\n */\nexport const BANNED_WORDS: readonly RegExp[] = [\n /\\bassistant/i,\n /\\basistente/i,\n /\\bassistent/i,\n /\\bbot\\b/i,\n /\\bcrew\\b/i,\n];\n\n/** The overrides that use a banned word, by key. */\nexport function bannedWordsIn(overrides: CopyOverrides): CopyKey[] {\n return (Object.entries(overrides) as [CopyKey, string | undefined][])\n .filter(([, v]) => v !== undefined && BANNED_WORDS.some((w) => w.test(v)))\n .map(([k]) => k);\n}\n","// Dates, times, money and text direction in the person's locale, through Intl (Hermes has it), with a plain fallback\n// where a runtime lacks it.\n\n/** Languages and scripts written right to left. */\nconst RTL_LANGUAGES = new Set([\n 'ar',\n 'he',\n 'iw',\n 'fa',\n 'ur',\n 'ps',\n 'yi',\n 'dv',\n 'ckb',\n 'sd',\n 'ug',\n 'syr',\n]);\nconst RTL_SCRIPTS = new Set([\n 'arab',\n 'hebr',\n 'thaa',\n 'syrc',\n 'nkoo',\n 'adlm',\n 'rohg',\n]);\n\n/** `rtl` for Arabic, Hebrew, Persian, Urdu and the other right-to-left languages and scripts; `ltr` otherwise. */\nexport function textDirection(locale: string | undefined): 'ltr' | 'rtl' {\n const parts = (locale ?? '').toLowerCase().split(/[-_]/);\n if (parts.some((p) => p.length === 4 && RTL_SCRIPTS.has(p))) return 'rtl';\n return RTL_LANGUAGES.has(parts[0] ?? '') ? 'rtl' : 'ltr';\n}\n\n/** An amount in minor units (`amount` cents) in its currency: `$85.00`. */\nexport function formatMoney(\n amountMinor: number,\n currency: string,\n locale?: string,\n): string {\n try {\n const format = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n });\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2;\n return format.format(amountMinor / 10 ** digits);\n } catch {\n return `${currency} ${(amountMinor / 100).toFixed(2)}`;\n }\n}\n\n/** A start and an end: \"Wed, Oct 14, 10:00 – 11:30 AM\" in the locale and time zone. */\nexport function formatTimeRange(\n start: string,\n end: string | undefined,\n locale?: string,\n timeZone?: string,\n): string {\n const from = new Date(start);\n if (Number.isNaN(from.getTime())) return start;\n const options: Intl.DateTimeFormatOptions = {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n };\n try {\n const format = new Intl.DateTimeFormat(locale, options);\n const to = end ? new Date(end) : null;\n if (!to || Number.isNaN(to.getTime())) return format.format(from);\n return typeof format.formatRange === 'function'\n ? format.formatRange(from, to)\n : `${format.format(from)} – ${format.format(to)}`;\n } catch {\n return from.toISOString();\n }\n}\n\n/** The day a moment falls on in a time zone, as a day count, so two days compare across DST. */\nfunction dayOf(at: Date, timeZone: string | undefined): number {\n const [y, m, d] = new Intl.DateTimeFormat('en-CA', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n })\n .format(at)\n .split('-')\n .map(Number);\n return Date.UTC(y as number, (m as number) - 1, d as number) / 86_400_000;\n}\n\n/**\n * A moment as a person says it: \"today, 10:00 AM\" and \"tomorrow, 10:00 AM\" (`today` and `tomorrow` are the copy's\n * words, with `{time}`), else the date and time (\"Fri, Oct 17, 10:00 AM\"), in the locale and time zone. `now` is the\n * clock it is judged by.\n */\nexport function formatDayTime(\n start: string,\n words: { readonly today: string; readonly tomorrow: string },\n locale?: string,\n timeZone?: string,\n now: number = Date.now(),\n): string {\n const at = new Date(start);\n if (Number.isNaN(at.getTime())) return start;\n try {\n const days = dayOf(at, timeZone) - dayOf(new Date(now), timeZone);\n const word = days === 0 ? words.today : days === 1 ? words.tomorrow : '';\n if (!word) return formatTimeRange(start, undefined, locale, timeZone);\n const time = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n }).format(at);\n return word.replace('{time}', time);\n } catch {\n return formatTimeRange(start, undefined, locale, timeZone);\n }\n}\n\n/** A calendar date (`YYYY-MM-DD`) in the locale: \"October 14, 2026\". */\nexport function formatDate(date: string, locale?: string): string {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(date);\n if (!m) return date;\n try {\n return new Intl.DateTimeFormat(locale, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n timeZone: 'UTC',\n }).format(new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]))));\n } catch {\n return date;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/copy/copy.ts","../../src/copy/format.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["// The words a Vinaverse UI says, in English, Spanish and Brazilian Portuguese, each overridable by the tenant except\n// the fallback disclosure. People first: \"agent\", never \"assistant\"; a person from the business is a person, by role.\n// `{name}` placeholders are filled from `vars`. A key with a `One` form (`historyMessagesOne`) says it for a `count` of 1.\n\nconst en = {\n disclosureFallback: \"You're chatting with an AI agent. Powered by Vinaverse.\",\n agentLabel: 'AI agent',\n agentFallbackName: 'the agent',\n you: 'You',\n staffLabel: '{by} · person',\n staffFallbackRole: 'the team',\n composerPlaceholder: 'Message {agent}',\n composerPlaceholderTakeover: 'Message {by}',\n send: 'Send',\n stop: 'Stop',\n typeAnswerBelow: 'Type your answer below.',\n bannerConnecting: 'Connecting…',\n bannerReconnecting: 'Reconnecting…',\n bannerOffline: \"You're offline. Messages send when you're back.\",\n bannerContinuedElsewhere: 'This conversation continued on another device.',\n bannerUnavailable: \"Couldn't connect.\",\n continueHere: 'Continue here',\n tryAgain: 'Try again',\n talkToPerson: 'Talk to a person',\n messageSending: 'Sending',\n messageHeld: 'Sends when you continue',\n messageNotSent: 'Not sent',\n messageDelivered: 'Delivered',\n messageCutOff: 'This reply was cut off.',\n takeoverStarted: 'A person from {by} is replying now.',\n takeoverEnded: '{agent} is back.',\n handoffCreated: \"We've passed this to the team. They'll reply {expected}.\",\n handoffCreatedNoTime: \"We've passed this to the team. They'll reply soon.\",\n flowSent: 'Your answers were sent.',\n flowNotSent: \"Your answers couldn't be sent yet.\",\n turnFailed: 'Something went wrong.',\n working: '{agent} is working on it…',\n proposalConfirm: 'Confirm',\n proposalDecline: 'Decline',\n proposalChange: 'Change',\n proposalConfirmed: 'Confirmed',\n proposalDeclined: 'Declined',\n proposalFailed: \"Couldn't be confirmed\",\n proposalExpired: 'Expired',\n proposalSettled: 'No longer open',\n questionSubmit: 'Send',\n questionSkip: 'Skip',\n questionOther: 'Other',\n questionSearch: 'Search',\n questionAnswered: 'Answered',\n questionReplaced: 'Replaced by a newer question',\n questionStep: 'Question {step} of {total}',\n questionAddPhoto: 'Add a photo',\n questionCharactersLeft: '{count} characters left',\n questionCharactersLeftOne: '{count} character left',\n priceFrom: 'From {price}',\n /** A listing with no rating yet; empty draws nothing, a tenant's word (\"New\") draws in the rating's place. */\n ratingNone: '',\n nextAvailable: 'Next: {time}',\n /** A time today and tomorrow, as `nextAvailable` says it (`{time}`: \"10:00 AM\"). */\n today: 'today, {time}',\n tomorrow: 'tomorrow, {time}',\n agentEnded: 'This conversation ended',\n agentEndedBody: 'Start a new one whenever you like.',\n agentStartOver: 'Start a new conversation',\n agentUnreachable: \"Couldn't reach {agent}\",\n agentUnreachableBody: 'Check your connection and try again.',\n agentOff: \"{agent} isn't available right now\",\n agentOffBody: 'Please try again later.',\n helpful: 'Was this helpful?',\n helpfulYes: 'Yes',\n helpfulNo: 'No',\n helpfulThanks: 'Thanks for telling us.',\n launcherOpen: 'Open {agent}',\n launcherGreeting: \"Hi, I'm {agent}. Ask me what you need.\",\n close: 'Close',\n welcomeFallback: \"Hi, I'm {agent}. How can I help?\",\n privacy: 'Privacy',\n cardsInRow: '{count} results, swipe for more',\n cardsInRowOne: '{count} result',\n open: 'Open',\n /** History: the person's past conversations, and reading one back. */\n historyEmpty: 'No conversations yet',\n historyEmptyBody: 'Your conversations with {agent} will show here.',\n historyFailed: \"Couldn't load your conversations.\",\n historyOff: 'History is not available.',\n historyMessages: '{count} messages',\n historyMessagesOne: '{count} message',\n historyEnded: 'Ended',\n historyContinue: 'Continue',\n historyDelete: 'Delete',\n historyDeleteTitle: 'Delete this conversation?',\n historyDeleteBody: \"It's removed from your history everywhere.\",\n historyDeleteFailed: \"Couldn't delete this conversation.\",\n cancel: 'Cancel',\n transcriptFailed: \"Couldn't load this conversation.\",\n transcriptGone: 'This conversation is no longer available.',\n transcriptEarlier: 'Earlier messages',\n /** Under the person's message a guardrail refused. */\n messageRefused: 'Not answered',\n loading: 'Loading…',\n} as const;\n\nexport type CopyKey = keyof typeof en;\nexport type Copy = Readonly<Record<CopyKey, string>>;\n/** A tenant's words, by key; a key left out (or undefined) keeps the built-in one. */\nexport type CopyOverrides = { readonly [K in CopyKey]?: string | undefined };\n\nconst es: Copy = {\n disclosureFallback:\n 'Estás hablando con un agente de IA. Con la tecnología de Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'el agente',\n you: 'Tú',\n staffLabel: '{by} · persona',\n staffFallbackRole: 'el equipo',\n composerPlaceholder: 'Escribe a {agent}',\n composerPlaceholderTakeover: 'Escribe a {by}',\n send: 'Enviar',\n stop: 'Detener',\n typeAnswerBelow: 'Escribe tu respuesta abajo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sin conexión. Los mensajes se envían cuando vuelvas.',\n bannerContinuedElsewhere: 'Esta conversación continuó en otro dispositivo.',\n bannerUnavailable: 'No se pudo conectar.',\n continueHere: 'Continuar aquí',\n tryAgain: 'Intentar de nuevo',\n talkToPerson: 'Hablar con una persona',\n messageSending: 'Enviando',\n messageHeld: 'Se envía cuando continúes',\n messageNotSent: 'No enviado',\n messageDelivered: 'Entregado',\n messageCutOff: 'Esta respuesta quedó incompleta.',\n takeoverStarted: 'Una persona de {by} está respondiendo.',\n takeoverEnded: '{agent} volvió.',\n handoffCreated: 'Le pasamos esto al equipo. Responderán {expected}.',\n handoffCreatedNoTime: 'Le pasamos esto al equipo. Responderán pronto.',\n flowSent: 'Tus respuestas se enviaron.',\n flowNotSent: 'Tus respuestas aún no se pudieron enviar.',\n turnFailed: 'Algo salió mal.',\n working: '{agent} está en ello…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Rechazar',\n proposalChange: 'Cambiar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Rechazado',\n proposalFailed: 'No se pudo confirmar',\n proposalExpired: 'Vencido',\n proposalSettled: 'Ya no está abierto',\n questionSubmit: 'Enviar',\n questionSkip: 'Omitir',\n questionOther: 'Otro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Reemplazada por una pregunta más reciente',\n questionStep: 'Pregunta {step} de {total}',\n questionAddPhoto: 'Agregar una foto',\n questionCharactersLeft: 'Quedan {count} caracteres',\n questionCharactersLeftOne: 'Queda {count} carácter',\n priceFrom: 'Desde {price}',\n ratingNone: '',\n nextAvailable: 'Próximo: {time}',\n today: 'hoy, {time}',\n tomorrow: 'mañana, {time}',\n agentEnded: 'Esta conversación terminó',\n agentEndedBody: 'Empieza una nueva cuando quieras.',\n agentStartOver: 'Empezar una conversación nueva',\n agentUnreachable: 'No se pudo contactar a {agent}',\n agentUnreachableBody: 'Revisa tu conexión e inténtalo de nuevo.',\n agentOff: '{agent} no está disponible ahora',\n agentOffBody: 'Inténtalo de nuevo más tarde.',\n helpful: '¿Te sirvió?',\n helpfulYes: 'Sí',\n helpfulNo: 'No',\n helpfulThanks: 'Gracias por contarnos.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Hola, soy {agent}. Pregúntame lo que necesites.',\n close: 'Cerrar',\n welcomeFallback: 'Hola, soy {agent}. ¿En qué te ayudo?',\n privacy: 'Privacidad',\n cardsInRow: '{count} resultados, desliza para ver más',\n cardsInRowOne: '{count} resultado',\n open: 'Abrir',\n historyEmpty: 'Aún no hay conversaciones',\n historyEmptyBody: 'Tus conversaciones con {agent} aparecerán aquí.',\n historyFailed: 'No se pudieron cargar tus conversaciones.',\n historyOff: 'El historial no está disponible.',\n historyMessages: '{count} mensajes',\n historyMessagesOne: '{count} mensaje',\n historyEnded: 'Terminada',\n historyContinue: 'Continuar',\n historyDelete: 'Eliminar',\n historyDeleteTitle: '¿Eliminar esta conversación?',\n historyDeleteBody: 'Se elimina de tu historial en todas partes.',\n historyDeleteFailed: 'No se pudo eliminar esta conversación.',\n cancel: 'Cancelar',\n transcriptFailed: 'No se pudo cargar esta conversación.',\n transcriptGone: 'Esta conversación ya no está disponible.',\n transcriptEarlier: 'Mensajes anteriores',\n messageRefused: 'Sin respuesta',\n loading: 'Cargando…',\n};\n\nconst ptBR: Copy = {\n disclosureFallback:\n 'Você está conversando com um agente de IA. Com tecnologia Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'o agente',\n you: 'Você',\n staffLabel: '{by} · pessoa',\n staffFallbackRole: 'a equipe',\n composerPlaceholder: 'Mensagem para {agent}',\n composerPlaceholderTakeover: 'Mensagem para {by}',\n send: 'Enviar',\n stop: 'Parar',\n typeAnswerBelow: 'Digite sua resposta abaixo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sem conexão. As mensagens são enviadas quando você voltar.',\n bannerContinuedElsewhere: 'Esta conversa continuou em outro aparelho.',\n bannerUnavailable: 'Não foi possível conectar.',\n continueHere: 'Continuar aqui',\n tryAgain: 'Tentar de novo',\n talkToPerson: 'Falar com uma pessoa',\n messageSending: 'Enviando',\n messageHeld: 'Será enviada quando você continuar',\n messageNotSent: 'Não enviada',\n messageDelivered: 'Entregue',\n messageCutOff: 'Esta resposta foi interrompida.',\n takeoverStarted: 'Uma pessoa de {by} está respondendo agora.',\n takeoverEnded: '{agent} voltou.',\n handoffCreated: 'Passamos isso para a equipe. Eles vão responder {expected}.',\n handoffCreatedNoTime:\n 'Passamos isso para a equipe. Eles vão responder em breve.',\n flowSent: 'Suas respostas foram enviadas.',\n flowNotSent: 'Ainda não foi possível enviar suas respostas.',\n turnFailed: 'Algo deu errado.',\n working: '{agent} está cuidando disso…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Recusar',\n proposalChange: 'Alterar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Recusado',\n proposalFailed: 'Não foi possível confirmar',\n proposalExpired: 'Expirado',\n proposalSettled: 'Não está mais aberto',\n questionSubmit: 'Enviar',\n questionSkip: 'Pular',\n questionOther: 'Outro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Substituída por uma pergunta mais recente',\n questionStep: 'Pergunta {step} de {total}',\n questionAddPhoto: 'Adicionar uma foto',\n questionCharactersLeft: 'Restam {count} caracteres',\n questionCharactersLeftOne: 'Resta {count} caractere',\n priceFrom: 'A partir de {price}',\n ratingNone: '',\n nextAvailable: 'Próximo horário: {time}',\n today: 'hoje, {time}',\n tomorrow: 'amanhã, {time}',\n agentEnded: 'Esta conversa terminou',\n agentEndedBody: 'Comece uma nova quando quiser.',\n agentStartOver: 'Começar uma conversa nova',\n agentUnreachable: 'Não foi possível falar com {agent}',\n agentUnreachableBody: 'Verifique sua conexão e tente de novo.',\n agentOff: '{agent} não está disponível agora',\n agentOffBody: 'Tente de novo mais tarde.',\n helpful: 'Isso ajudou?',\n helpfulYes: 'Sim',\n helpfulNo: 'Não',\n helpfulThanks: 'Obrigado por avisar.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Oi, sou {agent}. Pergunte o que precisar.',\n close: 'Fechar',\n welcomeFallback: 'Oi, sou {agent}. Como posso ajudar?',\n privacy: 'Privacidade',\n cardsInRow: '{count} resultados, deslize para ver mais',\n cardsInRowOne: '{count} resultado',\n open: 'Abrir',\n historyEmpty: 'Nenhuma conversa ainda',\n historyEmptyBody: 'Suas conversas com {agent} vão aparecer aqui.',\n historyFailed: 'Não foi possível carregar suas conversas.',\n historyOff: 'O histórico não está disponível.',\n historyMessages: '{count} mensagens',\n historyMessagesOne: '{count} mensagem',\n historyEnded: 'Encerrada',\n historyContinue: 'Continuar',\n historyDelete: 'Excluir',\n historyDeleteTitle: 'Excluir esta conversa?',\n historyDeleteBody: 'Ela é removida do seu histórico em todos os lugares.',\n historyDeleteFailed: 'Não foi possível excluir esta conversa.',\n cancel: 'Cancelar',\n transcriptFailed: 'Não foi possível carregar esta conversa.',\n transcriptGone: 'Esta conversa não está mais disponível.',\n transcriptEarlier: 'Mensagens anteriores',\n messageRefused: 'Sem resposta',\n loading: 'Carregando…',\n};\n\n/** The built-in languages; any other locale falls back to English, its own `copy` overrides aside. */\nexport const COPY: Readonly<Record<'en' | 'es' | 'pt-BR', Copy>> = {\n en,\n es,\n 'pt-BR': ptBR,\n};\n\n/**\n * Keys a tenant may not override in a built-in language: the AI disclosure is the platform's, never removed or reworded.\n * In a language without built-in copy the tenant supplies them, translated, so the disclosure reads in the person's\n * language, and only a translation that still discloses is taken (`discloses`): the label says AI, the disclosure says\n * AI and names Vinaverse.\n */\nconst FIXED: ReadonlySet<CopyKey> = new Set([\n 'disclosureFallback',\n 'agentLabel',\n]);\n\n/**\n * \"AI\" as languages write it: AI, IA (es, pt, fr, it, ro), KI (de, nl, da, no, sv), SI (pl), YZ (tr), ИИ (ru), ШІ\n * (uk), and the words for it in Arabic, Hebrew, Hindi, Chinese, Japanese and Korean.\n */\nexport const AI_MARK =\n /(?:^|[^\\p{L}])(?:AI|IA|KI|SI|YZ|ИИ|ШІ)(?:$|[^\\p{L}])|الذكاء الاصطناعي|بالذكاء|בינה מלאכותית|एआई|कृत्रिम बुद्धि|人工智能|人工知能|인공지능/u;\n\n/**\n * Whether a tenant's text for a fixed key still makes the AI disclosure: the label says AI; the disclosure says AI\n * and names Vinaverse. A tenant's translation that does not is ignored, and the English built-in shows instead.\n */\nfunction discloses(key: string, value: string): boolean {\n if (!AI_MARK.test(value)) return false;\n return key !== 'disclosureFallback' || value.includes('Vinaverse');\n}\n\nexport type Translate = (\n key: CopyKey,\n vars?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The built-in copy for a locale: its language (`es-US` → `es`, `pt-PT` → `pt-BR`), else null. */\nfunction builtIn(locale: string | undefined): Copy | null {\n const language = (locale ?? 'en').split(/[-_]/)[0]?.toLowerCase();\n if (language === 'en') return COPY.en;\n if (language === 'es') return COPY.es;\n if (language === 'pt') return COPY['pt-BR'];\n return null;\n}\n\n/** The built-in copy for a locale, English when the language has none. */\nexport function builtInCopy(locale: string | undefined): Copy {\n return builtIn(locale) ?? COPY.en;\n}\n\n/** A translator for a locale, with the tenant's overrides on top (fixed keys excepted). */\nexport function createTranslate(\n locale: string | undefined,\n overrides: CopyOverrides = {},\n): Translate {\n const own = builtIn(locale);\n const merged: Record<string, string> = { ...(own ?? COPY.en) };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === undefined) continue;\n if (FIXED.has(key as CopyKey) && !(own === null && discloses(key, value)))\n continue;\n merged[key] = value;\n // The tenant's words for a count, without their own `One` form: theirs for every count, never ours for 1.\n if (!(`${key}One` in overrides)) delete merged[`${key}One`];\n }\n return (key, vars) =>\n (\n (vars?.count === 1 ? merged[`${key}One`] : undefined) ??\n merged[key] ??\n en[key]\n ).replace(/\\{(\\w+)\\}/g, (all, name: string) =>\n vars && name in vars ? String(vars[name]) : all,\n );\n}\n\n/**\n * Words a Vinaverse UI never says to people (a tenant override that uses them gets a development warning): the\n * runtime is an agent, never an assistant or a bot; and never \"crew\".\n */\nexport const BANNED_WORDS: readonly RegExp[] = [\n /\\bassistant/i,\n /\\basistente/i,\n /\\bassistent/i,\n /\\bbot\\b/i,\n /\\bcrew\\b/i,\n];\n\n/** The overrides that use a banned word, by key. */\nexport function bannedWordsIn(overrides: CopyOverrides): CopyKey[] {\n return (Object.entries(overrides) as [CopyKey, string | undefined][])\n .filter(([, v]) => v !== undefined && BANNED_WORDS.some((w) => w.test(v)))\n .map(([k]) => k);\n}\n","// Dates, times, money and text direction in the person's locale, through Intl (Hermes has it), with a plain fallback\n// where a runtime lacks it.\n\n/** Languages and scripts written right to left. */\nconst RTL_LANGUAGES = new Set([\n 'ar',\n 'he',\n 'iw',\n 'fa',\n 'ur',\n 'ps',\n 'yi',\n 'dv',\n 'ckb',\n 'sd',\n 'ug',\n 'syr',\n]);\nconst RTL_SCRIPTS = new Set([\n 'arab',\n 'hebr',\n 'thaa',\n 'syrc',\n 'nkoo',\n 'adlm',\n 'rohg',\n]);\n\n/** `rtl` for Arabic, Hebrew, Persian, Urdu and the other right-to-left languages and scripts; `ltr` otherwise. */\nexport function textDirection(locale: string | undefined): 'ltr' | 'rtl' {\n const parts = (locale ?? '').toLowerCase().split(/[-_]/);\n if (parts.some((p) => p.length === 4 && RTL_SCRIPTS.has(p))) return 'rtl';\n return RTL_LANGUAGES.has(parts[0] ?? '') ? 'rtl' : 'ltr';\n}\n\n/** An amount in minor units (`amount` cents) in its currency: `$85.00`. */\nexport function formatMoney(\n amountMinor: number,\n currency: string,\n locale?: string,\n): string {\n try {\n const format = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n });\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2;\n return format.format(amountMinor / 10 ** digits);\n } catch {\n return `${currency} ${(amountMinor / 100).toFixed(2)}`;\n }\n}\n\n/** A start and an end: \"Wed, Oct 14, 10:00 – 11:30 AM\" in the locale and time zone. */\nexport function formatTimeRange(\n start: string,\n end: string | undefined,\n locale?: string,\n timeZone?: string,\n): string {\n const from = new Date(start);\n if (Number.isNaN(from.getTime())) return start;\n const options: Intl.DateTimeFormatOptions = {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n };\n try {\n const format = new Intl.DateTimeFormat(locale, options);\n const to = end ? new Date(end) : null;\n if (!to || Number.isNaN(to.getTime())) return format.format(from);\n return typeof format.formatRange === 'function'\n ? format.formatRange(from, to)\n : `${format.format(from)} – ${format.format(to)}`;\n } catch {\n return from.toISOString();\n }\n}\n\n/** The day a moment falls on in a time zone, as a day count, so two days compare across DST. */\nfunction dayOf(at: Date, timeZone: string | undefined): number {\n const [y, m, d] = new Intl.DateTimeFormat('en-CA', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n })\n .format(at)\n .split('-')\n .map(Number);\n return Date.UTC(y as number, (m as number) - 1, d as number) / 86_400_000;\n}\n\n/**\n * A moment as a person says it: \"today, 10:00 AM\" and \"tomorrow, 10:00 AM\" (`today` and `tomorrow` are the copy's\n * words, with `{time}`), else the date and time (\"Fri, Oct 17, 10:00 AM\"), in the locale and time zone. `now` is the\n * clock it is judged by.\n */\nexport function formatDayTime(\n start: string,\n words: { readonly today: string; readonly tomorrow: string },\n locale?: string,\n timeZone?: string,\n now: number = Date.now(),\n): string {\n const at = new Date(start);\n if (Number.isNaN(at.getTime())) return start;\n try {\n const days = dayOf(at, timeZone) - dayOf(new Date(now), timeZone);\n const word = days === 0 ? words.today : days === 1 ? words.tomorrow : '';\n if (!word) return formatTimeRange(start, undefined, locale, timeZone);\n const time = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n }).format(at);\n return word.replace('{time}', time);\n } catch {\n return formatTimeRange(start, undefined, locale, timeZone);\n }\n}\n\n/** A calendar date (`YYYY-MM-DD`) in the locale: \"October 14, 2026\". */\nexport function formatDate(date: string, locale?: string): string {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(date);\n if (!m) return date;\n try {\n return new Intl.DateTimeFormat(locale, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n timeZone: 'UTC',\n }).format(new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]))));\n } catch {\n return date;\n }\n}\n\n/** A moment with its date and time in the locale and zone: \"Oct 15, 2026, 9:30 AM\"; the text as given when it is not one. */\nexport function formatDateTime(\n at: string,\n locale?: string,\n timeZone?: string,\n): string {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return at;\n try {\n return new Intl.DateTimeFormat(locale, {\n dateStyle: 'medium',\n timeStyle: 'short',\n ...(timeZone ? { timeZone } : {}),\n }).format(date);\n } catch {\n return date.toISOString();\n }\n}\n"]}
@@ -48,6 +48,7 @@ declare const en: {
48
48
  readonly questionStep: "Question {step} of {total}";
49
49
  readonly questionAddPhoto: "Add a photo";
50
50
  readonly questionCharactersLeft: "{count} characters left";
51
+ readonly questionCharactersLeftOne: "{count} character left";
51
52
  readonly priceFrom: "From {price}";
52
53
  /** A listing with no rating yet; empty draws nothing, a tenant's word ("New") draws in the rating's place. */
53
54
  readonly ratingNone: "";
@@ -72,7 +73,28 @@ declare const en: {
72
73
  readonly welcomeFallback: "Hi, I'm {agent}. How can I help?";
73
74
  readonly privacy: "Privacy";
74
75
  readonly cardsInRow: "{count} results, swipe for more";
76
+ readonly cardsInRowOne: "{count} result";
75
77
  readonly open: "Open";
78
+ /** History: the person's past conversations, and reading one back. */
79
+ readonly historyEmpty: "No conversations yet";
80
+ readonly historyEmptyBody: "Your conversations with {agent} will show here.";
81
+ readonly historyFailed: "Couldn't load your conversations.";
82
+ readonly historyOff: "History is not available.";
83
+ readonly historyMessages: "{count} messages";
84
+ readonly historyMessagesOne: "{count} message";
85
+ readonly historyEnded: "Ended";
86
+ readonly historyContinue: "Continue";
87
+ readonly historyDelete: "Delete";
88
+ readonly historyDeleteTitle: "Delete this conversation?";
89
+ readonly historyDeleteBody: "It's removed from your history everywhere.";
90
+ readonly historyDeleteFailed: "Couldn't delete this conversation.";
91
+ readonly cancel: "Cancel";
92
+ readonly transcriptFailed: "Couldn't load this conversation.";
93
+ readonly transcriptGone: "This conversation is no longer available.";
94
+ readonly transcriptEarlier: "Earlier messages";
95
+ /** Under the person's message a guardrail refused. */
96
+ readonly messageRefused: "Not answered";
97
+ readonly loading: "Loading…";
76
98
  };
77
99
  type CopyKey = keyof typeof en;
78
100
  type Copy = Readonly<Record<CopyKey, string>>;
@@ -117,5 +139,7 @@ declare function formatDayTime(start: string, words: {
117
139
  }, locale?: string, timeZone?: string, now?: number): string;
118
140
  /** A calendar date (`YYYY-MM-DD`) in the locale: "October 14, 2026". */
119
141
  declare function formatDate(date: string, locale?: string): string;
142
+ /** A moment with its date and time in the locale and zone: "Oct 15, 2026, 9:30 AM"; the text as given when it is not one. */
143
+ declare function formatDateTime(at: string, locale?: string, timeZone?: string): string;
120
144
 
121
- export { AI_MARK, BANNED_WORDS, COPY, type Copy, type CopyKey, type CopyOverrides, type Translate, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDayTime, formatMoney, formatTimeRange, textDirection };
145
+ export { AI_MARK, BANNED_WORDS, COPY, type Copy, type CopyKey, type CopyOverrides, type Translate, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDateTime, formatDayTime, formatMoney, formatTimeRange, textDirection };
@@ -48,6 +48,7 @@ declare const en: {
48
48
  readonly questionStep: "Question {step} of {total}";
49
49
  readonly questionAddPhoto: "Add a photo";
50
50
  readonly questionCharactersLeft: "{count} characters left";
51
+ readonly questionCharactersLeftOne: "{count} character left";
51
52
  readonly priceFrom: "From {price}";
52
53
  /** A listing with no rating yet; empty draws nothing, a tenant's word ("New") draws in the rating's place. */
53
54
  readonly ratingNone: "";
@@ -72,7 +73,28 @@ declare const en: {
72
73
  readonly welcomeFallback: "Hi, I'm {agent}. How can I help?";
73
74
  readonly privacy: "Privacy";
74
75
  readonly cardsInRow: "{count} results, swipe for more";
76
+ readonly cardsInRowOne: "{count} result";
75
77
  readonly open: "Open";
78
+ /** History: the person's past conversations, and reading one back. */
79
+ readonly historyEmpty: "No conversations yet";
80
+ readonly historyEmptyBody: "Your conversations with {agent} will show here.";
81
+ readonly historyFailed: "Couldn't load your conversations.";
82
+ readonly historyOff: "History is not available.";
83
+ readonly historyMessages: "{count} messages";
84
+ readonly historyMessagesOne: "{count} message";
85
+ readonly historyEnded: "Ended";
86
+ readonly historyContinue: "Continue";
87
+ readonly historyDelete: "Delete";
88
+ readonly historyDeleteTitle: "Delete this conversation?";
89
+ readonly historyDeleteBody: "It's removed from your history everywhere.";
90
+ readonly historyDeleteFailed: "Couldn't delete this conversation.";
91
+ readonly cancel: "Cancel";
92
+ readonly transcriptFailed: "Couldn't load this conversation.";
93
+ readonly transcriptGone: "This conversation is no longer available.";
94
+ readonly transcriptEarlier: "Earlier messages";
95
+ /** Under the person's message a guardrail refused. */
96
+ readonly messageRefused: "Not answered";
97
+ readonly loading: "Loading…";
76
98
  };
77
99
  type CopyKey = keyof typeof en;
78
100
  type Copy = Readonly<Record<CopyKey, string>>;
@@ -117,5 +139,7 @@ declare function formatDayTime(start: string, words: {
117
139
  }, locale?: string, timeZone?: string, now?: number): string;
118
140
  /** A calendar date (`YYYY-MM-DD`) in the locale: "October 14, 2026". */
119
141
  declare function formatDate(date: string, locale?: string): string;
142
+ /** A moment with its date and time in the locale and zone: "Oct 15, 2026, 9:30 AM"; the text as given when it is not one. */
143
+ declare function formatDateTime(at: string, locale?: string, timeZone?: string): string;
120
144
 
121
- export { AI_MARK, BANNED_WORDS, COPY, type Copy, type CopyKey, type CopyOverrides, type Translate, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDayTime, formatMoney, formatTimeRange, textDirection };
145
+ export { AI_MARK, BANNED_WORDS, COPY, type Copy, type CopyKey, type CopyOverrides, type Translate, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDateTime, formatDayTime, formatMoney, formatTimeRange, textDirection };
@@ -49,6 +49,7 @@ var en = {
49
49
  questionStep: "Question {step} of {total}",
50
50
  questionAddPhoto: "Add a photo",
51
51
  questionCharactersLeft: "{count} characters left",
52
+ questionCharactersLeftOne: "{count} character left",
52
53
  priceFrom: "From {price}",
53
54
  /** A listing with no rating yet; empty draws nothing, a tenant's word ("New") draws in the rating's place. */
54
55
  ratingNone: "",
@@ -73,7 +74,28 @@ var en = {
73
74
  welcomeFallback: "Hi, I'm {agent}. How can I help?",
74
75
  privacy: "Privacy",
75
76
  cardsInRow: "{count} results, swipe for more",
76
- open: "Open"
77
+ cardsInRowOne: "{count} result",
78
+ open: "Open",
79
+ /** History: the person's past conversations, and reading one back. */
80
+ historyEmpty: "No conversations yet",
81
+ historyEmptyBody: "Your conversations with {agent} will show here.",
82
+ historyFailed: "Couldn't load your conversations.",
83
+ historyOff: "History is not available.",
84
+ historyMessages: "{count} messages",
85
+ historyMessagesOne: "{count} message",
86
+ historyEnded: "Ended",
87
+ historyContinue: "Continue",
88
+ historyDelete: "Delete",
89
+ historyDeleteTitle: "Delete this conversation?",
90
+ historyDeleteBody: "It's removed from your history everywhere.",
91
+ historyDeleteFailed: "Couldn't delete this conversation.",
92
+ cancel: "Cancel",
93
+ transcriptFailed: "Couldn't load this conversation.",
94
+ transcriptGone: "This conversation is no longer available.",
95
+ transcriptEarlier: "Earlier messages",
96
+ /** Under the person's message a guardrail refused. */
97
+ messageRefused: "Not answered",
98
+ loading: "Loading\u2026"
77
99
  };
78
100
  var es = {
79
101
  disclosureFallback: "Est\xE1s hablando con un agente de IA. Con la tecnolog\xEDa de Vinaverse.",
@@ -125,6 +147,7 @@ var es = {
125
147
  questionStep: "Pregunta {step} de {total}",
126
148
  questionAddPhoto: "Agregar una foto",
127
149
  questionCharactersLeft: "Quedan {count} caracteres",
150
+ questionCharactersLeftOne: "Queda {count} car\xE1cter",
128
151
  priceFrom: "Desde {price}",
129
152
  ratingNone: "",
130
153
  nextAvailable: "Pr\xF3ximo: {time}",
@@ -147,7 +170,26 @@ var es = {
147
170
  welcomeFallback: "Hola, soy {agent}. \xBFEn qu\xE9 te ayudo?",
148
171
  privacy: "Privacidad",
149
172
  cardsInRow: "{count} resultados, desliza para ver m\xE1s",
150
- open: "Abrir"
173
+ cardsInRowOne: "{count} resultado",
174
+ open: "Abrir",
175
+ historyEmpty: "A\xFAn no hay conversaciones",
176
+ historyEmptyBody: "Tus conversaciones con {agent} aparecer\xE1n aqu\xED.",
177
+ historyFailed: "No se pudieron cargar tus conversaciones.",
178
+ historyOff: "El historial no est\xE1 disponible.",
179
+ historyMessages: "{count} mensajes",
180
+ historyMessagesOne: "{count} mensaje",
181
+ historyEnded: "Terminada",
182
+ historyContinue: "Continuar",
183
+ historyDelete: "Eliminar",
184
+ historyDeleteTitle: "\xBFEliminar esta conversaci\xF3n?",
185
+ historyDeleteBody: "Se elimina de tu historial en todas partes.",
186
+ historyDeleteFailed: "No se pudo eliminar esta conversaci\xF3n.",
187
+ cancel: "Cancelar",
188
+ transcriptFailed: "No se pudo cargar esta conversaci\xF3n.",
189
+ transcriptGone: "Esta conversaci\xF3n ya no est\xE1 disponible.",
190
+ transcriptEarlier: "Mensajes anteriores",
191
+ messageRefused: "Sin respuesta",
192
+ loading: "Cargando\u2026"
151
193
  };
152
194
  var ptBR = {
153
195
  disclosureFallback: "Voc\xEA est\xE1 conversando com um agente de IA. Com tecnologia Vinaverse.",
@@ -199,6 +241,7 @@ var ptBR = {
199
241
  questionStep: "Pergunta {step} de {total}",
200
242
  questionAddPhoto: "Adicionar uma foto",
201
243
  questionCharactersLeft: "Restam {count} caracteres",
244
+ questionCharactersLeftOne: "Resta {count} caractere",
202
245
  priceFrom: "A partir de {price}",
203
246
  ratingNone: "",
204
247
  nextAvailable: "Pr\xF3ximo hor\xE1rio: {time}",
@@ -221,7 +264,26 @@ var ptBR = {
221
264
  welcomeFallback: "Oi, sou {agent}. Como posso ajudar?",
222
265
  privacy: "Privacidade",
223
266
  cardsInRow: "{count} resultados, deslize para ver mais",
224
- open: "Abrir"
267
+ cardsInRowOne: "{count} resultado",
268
+ open: "Abrir",
269
+ historyEmpty: "Nenhuma conversa ainda",
270
+ historyEmptyBody: "Suas conversas com {agent} v\xE3o aparecer aqui.",
271
+ historyFailed: "N\xE3o foi poss\xEDvel carregar suas conversas.",
272
+ historyOff: "O hist\xF3rico n\xE3o est\xE1 dispon\xEDvel.",
273
+ historyMessages: "{count} mensagens",
274
+ historyMessagesOne: "{count} mensagem",
275
+ historyEnded: "Encerrada",
276
+ historyContinue: "Continuar",
277
+ historyDelete: "Excluir",
278
+ historyDeleteTitle: "Excluir esta conversa?",
279
+ historyDeleteBody: "Ela \xE9 removida do seu hist\xF3rico em todos os lugares.",
280
+ historyDeleteFailed: "N\xE3o foi poss\xEDvel excluir esta conversa.",
281
+ cancel: "Cancelar",
282
+ transcriptFailed: "N\xE3o foi poss\xEDvel carregar esta conversa.",
283
+ transcriptGone: "Esta conversa n\xE3o est\xE1 mais dispon\xEDvel.",
284
+ transcriptEarlier: "Mensagens anteriores",
285
+ messageRefused: "Sem resposta",
286
+ loading: "Carregando\u2026"
225
287
  };
226
288
  var COPY = {
227
289
  en,
@@ -255,8 +317,9 @@ function createTranslate(locale, overrides = {}) {
255
317
  if (FIXED.has(key) && !(own === null && discloses(key, value)))
256
318
  continue;
257
319
  merged[key] = value;
320
+ if (!(`${key}One` in overrides)) delete merged[`${key}One`];
258
321
  }
259
- return (key, vars) => (merged[key] ?? en[key]).replace(
322
+ return (key, vars) => ((vars?.count === 1 ? merged[`${key}One`] : void 0) ?? merged[key] ?? en[key]).replace(
260
323
  /\{(\w+)\}/g,
261
324
  (all, name) => vars && name in vars ? String(vars[name]) : all
262
325
  );
@@ -373,7 +436,20 @@ function formatDate(date, locale) {
373
436
  return date;
374
437
  }
375
438
  }
439
+ function formatDateTime(at, locale, timeZone) {
440
+ const date = new Date(at);
441
+ if (Number.isNaN(date.getTime())) return at;
442
+ try {
443
+ return new Intl.DateTimeFormat(locale, {
444
+ dateStyle: "medium",
445
+ timeStyle: "short",
446
+ ...timeZone ? { timeZone } : {}
447
+ }).format(date);
448
+ } catch {
449
+ return date.toISOString();
450
+ }
451
+ }
376
452
 
377
- export { AI_MARK, BANNED_WORDS, COPY, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDayTime, formatMoney, formatTimeRange, textDirection };
453
+ export { AI_MARK, BANNED_WORDS, COPY, bannedWordsIn, builtInCopy, createTranslate, formatDate, formatDateTime, formatDayTime, formatMoney, formatTimeRange, textDirection };
378
454
  //# sourceMappingURL=index.js.map
379
455
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/copy/copy.ts","../../src/copy/format.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// The words a Vinaverse UI says, in English, Spanish and Brazilian Portuguese, each overridable by the tenant except\n// the fallback disclosure. People first: \"agent\", never \"assistant\"; a person from the business is a person, by role.\n// `{name}` placeholders are filled from `vars`.\n\nconst en = {\n disclosureFallback: \"You're chatting with an AI agent. Powered by Vinaverse.\",\n agentLabel: 'AI agent',\n agentFallbackName: 'the agent',\n you: 'You',\n staffLabel: '{by} · person',\n staffFallbackRole: 'the team',\n composerPlaceholder: 'Message {agent}',\n composerPlaceholderTakeover: 'Message {by}',\n send: 'Send',\n stop: 'Stop',\n typeAnswerBelow: 'Type your answer below.',\n bannerConnecting: 'Connecting…',\n bannerReconnecting: 'Reconnecting…',\n bannerOffline: \"You're offline. Messages send when you're back.\",\n bannerContinuedElsewhere: 'This conversation continued on another device.',\n bannerUnavailable: \"Couldn't connect.\",\n continueHere: 'Continue here',\n tryAgain: 'Try again',\n talkToPerson: 'Talk to a person',\n messageSending: 'Sending',\n messageHeld: 'Sends when you continue',\n messageNotSent: 'Not sent',\n messageDelivered: 'Delivered',\n messageCutOff: 'This reply was cut off.',\n takeoverStarted: 'A person from {by} is replying now.',\n takeoverEnded: '{agent} is back.',\n handoffCreated: \"We've passed this to the team. They'll reply {expected}.\",\n handoffCreatedNoTime: \"We've passed this to the team. They'll reply soon.\",\n flowSent: 'Your answers were sent.',\n flowNotSent: \"Your answers couldn't be sent yet.\",\n turnFailed: 'Something went wrong.',\n working: '{agent} is working on it…',\n proposalConfirm: 'Confirm',\n proposalDecline: 'Decline',\n proposalChange: 'Change',\n proposalConfirmed: 'Confirmed',\n proposalDeclined: 'Declined',\n proposalFailed: \"Couldn't be confirmed\",\n proposalExpired: 'Expired',\n proposalSettled: 'No longer open',\n questionSubmit: 'Send',\n questionSkip: 'Skip',\n questionOther: 'Other',\n questionSearch: 'Search',\n questionAnswered: 'Answered',\n questionReplaced: 'Replaced by a newer question',\n questionStep: 'Question {step} of {total}',\n questionAddPhoto: 'Add a photo',\n questionCharactersLeft: '{count} characters left',\n priceFrom: 'From {price}',\n /** A listing with no rating yet; empty draws nothing, a tenant's word (\"New\") draws in the rating's place. */\n ratingNone: '',\n nextAvailable: 'Next: {time}',\n /** A time today and tomorrow, as `nextAvailable` says it (`{time}`: \"10:00 AM\"). */\n today: 'today, {time}',\n tomorrow: 'tomorrow, {time}',\n agentEnded: 'This conversation ended',\n agentEndedBody: 'Start a new one whenever you like.',\n agentStartOver: 'Start a new conversation',\n agentUnreachable: \"Couldn't reach {agent}\",\n agentUnreachableBody: 'Check your connection and try again.',\n agentOff: \"{agent} isn't available right now\",\n agentOffBody: 'Please try again later.',\n helpful: 'Was this helpful?',\n helpfulYes: 'Yes',\n helpfulNo: 'No',\n helpfulThanks: 'Thanks for telling us.',\n launcherOpen: 'Open {agent}',\n launcherGreeting: \"Hi, I'm {agent}. Ask me what you need.\",\n close: 'Close',\n welcomeFallback: \"Hi, I'm {agent}. How can I help?\",\n privacy: 'Privacy',\n cardsInRow: '{count} results, swipe for more',\n open: 'Open',\n} as const;\n\nexport type CopyKey = keyof typeof en;\nexport type Copy = Readonly<Record<CopyKey, string>>;\n/** A tenant's words, by key; a key left out (or undefined) keeps the built-in one. */\nexport type CopyOverrides = { readonly [K in CopyKey]?: string | undefined };\n\nconst es: Copy = {\n disclosureFallback:\n 'Estás hablando con un agente de IA. Con la tecnología de Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'el agente',\n you: 'Tú',\n staffLabel: '{by} · persona',\n staffFallbackRole: 'el equipo',\n composerPlaceholder: 'Escribe a {agent}',\n composerPlaceholderTakeover: 'Escribe a {by}',\n send: 'Enviar',\n stop: 'Detener',\n typeAnswerBelow: 'Escribe tu respuesta abajo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sin conexión. Los mensajes se envían cuando vuelvas.',\n bannerContinuedElsewhere: 'Esta conversación continuó en otro dispositivo.',\n bannerUnavailable: 'No se pudo conectar.',\n continueHere: 'Continuar aquí',\n tryAgain: 'Intentar de nuevo',\n talkToPerson: 'Hablar con una persona',\n messageSending: 'Enviando',\n messageHeld: 'Se envía cuando continúes',\n messageNotSent: 'No enviado',\n messageDelivered: 'Entregado',\n messageCutOff: 'Esta respuesta quedó incompleta.',\n takeoverStarted: 'Una persona de {by} está respondiendo.',\n takeoverEnded: '{agent} volvió.',\n handoffCreated: 'Le pasamos esto al equipo. Responderán {expected}.',\n handoffCreatedNoTime: 'Le pasamos esto al equipo. Responderán pronto.',\n flowSent: 'Tus respuestas se enviaron.',\n flowNotSent: 'Tus respuestas aún no se pudieron enviar.',\n turnFailed: 'Algo salió mal.',\n working: '{agent} está en ello…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Rechazar',\n proposalChange: 'Cambiar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Rechazado',\n proposalFailed: 'No se pudo confirmar',\n proposalExpired: 'Vencido',\n proposalSettled: 'Ya no está abierto',\n questionSubmit: 'Enviar',\n questionSkip: 'Omitir',\n questionOther: 'Otro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Reemplazada por una pregunta más reciente',\n questionStep: 'Pregunta {step} de {total}',\n questionAddPhoto: 'Agregar una foto',\n questionCharactersLeft: 'Quedan {count} caracteres',\n priceFrom: 'Desde {price}',\n ratingNone: '',\n nextAvailable: 'Próximo: {time}',\n today: 'hoy, {time}',\n tomorrow: 'mañana, {time}',\n agentEnded: 'Esta conversación terminó',\n agentEndedBody: 'Empieza una nueva cuando quieras.',\n agentStartOver: 'Empezar una conversación nueva',\n agentUnreachable: 'No se pudo contactar a {agent}',\n agentUnreachableBody: 'Revisa tu conexión e inténtalo de nuevo.',\n agentOff: '{agent} no está disponible ahora',\n agentOffBody: 'Inténtalo de nuevo más tarde.',\n helpful: '¿Te sirvió?',\n helpfulYes: 'Sí',\n helpfulNo: 'No',\n helpfulThanks: 'Gracias por contarnos.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Hola, soy {agent}. Pregúntame lo que necesites.',\n close: 'Cerrar',\n welcomeFallback: 'Hola, soy {agent}. ¿En qué te ayudo?',\n privacy: 'Privacidad',\n cardsInRow: '{count} resultados, desliza para ver más',\n open: 'Abrir',\n};\n\nconst ptBR: Copy = {\n disclosureFallback:\n 'Você está conversando com um agente de IA. Com tecnologia Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'o agente',\n you: 'Você',\n staffLabel: '{by} · pessoa',\n staffFallbackRole: 'a equipe',\n composerPlaceholder: 'Mensagem para {agent}',\n composerPlaceholderTakeover: 'Mensagem para {by}',\n send: 'Enviar',\n stop: 'Parar',\n typeAnswerBelow: 'Digite sua resposta abaixo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sem conexão. As mensagens são enviadas quando você voltar.',\n bannerContinuedElsewhere: 'Esta conversa continuou em outro aparelho.',\n bannerUnavailable: 'Não foi possível conectar.',\n continueHere: 'Continuar aqui',\n tryAgain: 'Tentar de novo',\n talkToPerson: 'Falar com uma pessoa',\n messageSending: 'Enviando',\n messageHeld: 'Será enviada quando você continuar',\n messageNotSent: 'Não enviada',\n messageDelivered: 'Entregue',\n messageCutOff: 'Esta resposta foi interrompida.',\n takeoverStarted: 'Uma pessoa de {by} está respondendo agora.',\n takeoverEnded: '{agent} voltou.',\n handoffCreated: 'Passamos isso para a equipe. Eles vão responder {expected}.',\n handoffCreatedNoTime:\n 'Passamos isso para a equipe. Eles vão responder em breve.',\n flowSent: 'Suas respostas foram enviadas.',\n flowNotSent: 'Ainda não foi possível enviar suas respostas.',\n turnFailed: 'Algo deu errado.',\n working: '{agent} está cuidando disso…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Recusar',\n proposalChange: 'Alterar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Recusado',\n proposalFailed: 'Não foi possível confirmar',\n proposalExpired: 'Expirado',\n proposalSettled: 'Não está mais aberto',\n questionSubmit: 'Enviar',\n questionSkip: 'Pular',\n questionOther: 'Outro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Substituída por uma pergunta mais recente',\n questionStep: 'Pergunta {step} de {total}',\n questionAddPhoto: 'Adicionar uma foto',\n questionCharactersLeft: 'Restam {count} caracteres',\n priceFrom: 'A partir de {price}',\n ratingNone: '',\n nextAvailable: 'Próximo horário: {time}',\n today: 'hoje, {time}',\n tomorrow: 'amanhã, {time}',\n agentEnded: 'Esta conversa terminou',\n agentEndedBody: 'Comece uma nova quando quiser.',\n agentStartOver: 'Começar uma conversa nova',\n agentUnreachable: 'Não foi possível falar com {agent}',\n agentUnreachableBody: 'Verifique sua conexão e tente de novo.',\n agentOff: '{agent} não está disponível agora',\n agentOffBody: 'Tente de novo mais tarde.',\n helpful: 'Isso ajudou?',\n helpfulYes: 'Sim',\n helpfulNo: 'Não',\n helpfulThanks: 'Obrigado por avisar.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Oi, sou {agent}. Pergunte o que precisar.',\n close: 'Fechar',\n welcomeFallback: 'Oi, sou {agent}. Como posso ajudar?',\n privacy: 'Privacidade',\n cardsInRow: '{count} resultados, deslize para ver mais',\n open: 'Abrir',\n};\n\n/** The built-in languages; any other locale falls back to English, its own `copy` overrides aside. */\nexport const COPY: Readonly<Record<'en' | 'es' | 'pt-BR', Copy>> = {\n en,\n es,\n 'pt-BR': ptBR,\n};\n\n/**\n * Keys a tenant may not override in a built-in language: the AI disclosure is the platform's, never removed or reworded.\n * In a language without built-in copy the tenant supplies them, translated, so the disclosure reads in the person's\n * language, and only a translation that still discloses is taken (`discloses`): the label says AI, the disclosure says\n * AI and names Vinaverse.\n */\nconst FIXED: ReadonlySet<CopyKey> = new Set([\n 'disclosureFallback',\n 'agentLabel',\n]);\n\n/**\n * \"AI\" as languages write it: AI, IA (es, pt, fr, it, ro), KI (de, nl, da, no, sv), SI (pl), YZ (tr), ИИ (ru), ШІ\n * (uk), and the words for it in Arabic, Hebrew, Hindi, Chinese, Japanese and Korean.\n */\nexport const AI_MARK =\n /(?:^|[^\\p{L}])(?:AI|IA|KI|SI|YZ|ИИ|ШІ)(?:$|[^\\p{L}])|الذكاء الاصطناعي|بالذكاء|בינה מלאכותית|एआई|कृत्रिम बुद्धि|人工智能|人工知能|인공지능/u;\n\n/**\n * Whether a tenant's text for a fixed key still makes the AI disclosure: the label says AI; the disclosure says AI\n * and names Vinaverse. A tenant's translation that does not is ignored, and the English built-in shows instead.\n */\nfunction discloses(key: string, value: string): boolean {\n if (!AI_MARK.test(value)) return false;\n return key !== 'disclosureFallback' || value.includes('Vinaverse');\n}\n\nexport type Translate = (\n key: CopyKey,\n vars?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The built-in copy for a locale: its language (`es-US` → `es`, `pt-PT` → `pt-BR`), else null. */\nfunction builtIn(locale: string | undefined): Copy | null {\n const language = (locale ?? 'en').split(/[-_]/)[0]?.toLowerCase();\n if (language === 'en') return COPY.en;\n if (language === 'es') return COPY.es;\n if (language === 'pt') return COPY['pt-BR'];\n return null;\n}\n\n/** The built-in copy for a locale, English when the language has none. */\nexport function builtInCopy(locale: string | undefined): Copy {\n return builtIn(locale) ?? COPY.en;\n}\n\n/** A translator for a locale, with the tenant's overrides on top (fixed keys excepted). */\nexport function createTranslate(\n locale: string | undefined,\n overrides: CopyOverrides = {},\n): Translate {\n const own = builtIn(locale);\n const merged: Record<string, string> = { ...(own ?? COPY.en) };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === undefined) continue;\n if (FIXED.has(key as CopyKey) && !(own === null && discloses(key, value)))\n continue;\n merged[key] = value;\n }\n return (key, vars) =>\n (merged[key] ?? en[key]).replace(/\\{(\\w+)\\}/g, (all, name: string) =>\n vars && name in vars ? String(vars[name]) : all,\n );\n}\n\n/**\n * Words a Vinaverse UI never says to people (a tenant override that uses them gets a development warning): the\n * runtime is an agent, never an assistant or a bot; and never \"crew\".\n */\nexport const BANNED_WORDS: readonly RegExp[] = [\n /\\bassistant/i,\n /\\basistente/i,\n /\\bassistent/i,\n /\\bbot\\b/i,\n /\\bcrew\\b/i,\n];\n\n/** The overrides that use a banned word, by key. */\nexport function bannedWordsIn(overrides: CopyOverrides): CopyKey[] {\n return (Object.entries(overrides) as [CopyKey, string | undefined][])\n .filter(([, v]) => v !== undefined && BANNED_WORDS.some((w) => w.test(v)))\n .map(([k]) => k);\n}\n","// Dates, times, money and text direction in the person's locale, through Intl (Hermes has it), with a plain fallback\n// where a runtime lacks it.\n\n/** Languages and scripts written right to left. */\nconst RTL_LANGUAGES = new Set([\n 'ar',\n 'he',\n 'iw',\n 'fa',\n 'ur',\n 'ps',\n 'yi',\n 'dv',\n 'ckb',\n 'sd',\n 'ug',\n 'syr',\n]);\nconst RTL_SCRIPTS = new Set([\n 'arab',\n 'hebr',\n 'thaa',\n 'syrc',\n 'nkoo',\n 'adlm',\n 'rohg',\n]);\n\n/** `rtl` for Arabic, Hebrew, Persian, Urdu and the other right-to-left languages and scripts; `ltr` otherwise. */\nexport function textDirection(locale: string | undefined): 'ltr' | 'rtl' {\n const parts = (locale ?? '').toLowerCase().split(/[-_]/);\n if (parts.some((p) => p.length === 4 && RTL_SCRIPTS.has(p))) return 'rtl';\n return RTL_LANGUAGES.has(parts[0] ?? '') ? 'rtl' : 'ltr';\n}\n\n/** An amount in minor units (`amount` cents) in its currency: `$85.00`. */\nexport function formatMoney(\n amountMinor: number,\n currency: string,\n locale?: string,\n): string {\n try {\n const format = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n });\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2;\n return format.format(amountMinor / 10 ** digits);\n } catch {\n return `${currency} ${(amountMinor / 100).toFixed(2)}`;\n }\n}\n\n/** A start and an end: \"Wed, Oct 14, 10:00 – 11:30 AM\" in the locale and time zone. */\nexport function formatTimeRange(\n start: string,\n end: string | undefined,\n locale?: string,\n timeZone?: string,\n): string {\n const from = new Date(start);\n if (Number.isNaN(from.getTime())) return start;\n const options: Intl.DateTimeFormatOptions = {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n };\n try {\n const format = new Intl.DateTimeFormat(locale, options);\n const to = end ? new Date(end) : null;\n if (!to || Number.isNaN(to.getTime())) return format.format(from);\n return typeof format.formatRange === 'function'\n ? format.formatRange(from, to)\n : `${format.format(from)} – ${format.format(to)}`;\n } catch {\n return from.toISOString();\n }\n}\n\n/** The day a moment falls on in a time zone, as a day count, so two days compare across DST. */\nfunction dayOf(at: Date, timeZone: string | undefined): number {\n const [y, m, d] = new Intl.DateTimeFormat('en-CA', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n })\n .format(at)\n .split('-')\n .map(Number);\n return Date.UTC(y as number, (m as number) - 1, d as number) / 86_400_000;\n}\n\n/**\n * A moment as a person says it: \"today, 10:00 AM\" and \"tomorrow, 10:00 AM\" (`today` and `tomorrow` are the copy's\n * words, with `{time}`), else the date and time (\"Fri, Oct 17, 10:00 AM\"), in the locale and time zone. `now` is the\n * clock it is judged by.\n */\nexport function formatDayTime(\n start: string,\n words: { readonly today: string; readonly tomorrow: string },\n locale?: string,\n timeZone?: string,\n now: number = Date.now(),\n): string {\n const at = new Date(start);\n if (Number.isNaN(at.getTime())) return start;\n try {\n const days = dayOf(at, timeZone) - dayOf(new Date(now), timeZone);\n const word = days === 0 ? words.today : days === 1 ? words.tomorrow : '';\n if (!word) return formatTimeRange(start, undefined, locale, timeZone);\n const time = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n }).format(at);\n return word.replace('{time}', time);\n } catch {\n return formatTimeRange(start, undefined, locale, timeZone);\n }\n}\n\n/** A calendar date (`YYYY-MM-DD`) in the locale: \"October 14, 2026\". */\nexport function formatDate(date: string, locale?: string): string {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(date);\n if (!m) return date;\n try {\n return new Intl.DateTimeFormat(locale, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n timeZone: 'UTC',\n }).format(new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]))));\n } catch {\n return date;\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/copy/copy.ts","../../src/copy/format.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["// The words a Vinaverse UI says, in English, Spanish and Brazilian Portuguese, each overridable by the tenant except\n// the fallback disclosure. People first: \"agent\", never \"assistant\"; a person from the business is a person, by role.\n// `{name}` placeholders are filled from `vars`. A key with a `One` form (`historyMessagesOne`) says it for a `count` of 1.\n\nconst en = {\n disclosureFallback: \"You're chatting with an AI agent. Powered by Vinaverse.\",\n agentLabel: 'AI agent',\n agentFallbackName: 'the agent',\n you: 'You',\n staffLabel: '{by} · person',\n staffFallbackRole: 'the team',\n composerPlaceholder: 'Message {agent}',\n composerPlaceholderTakeover: 'Message {by}',\n send: 'Send',\n stop: 'Stop',\n typeAnswerBelow: 'Type your answer below.',\n bannerConnecting: 'Connecting…',\n bannerReconnecting: 'Reconnecting…',\n bannerOffline: \"You're offline. Messages send when you're back.\",\n bannerContinuedElsewhere: 'This conversation continued on another device.',\n bannerUnavailable: \"Couldn't connect.\",\n continueHere: 'Continue here',\n tryAgain: 'Try again',\n talkToPerson: 'Talk to a person',\n messageSending: 'Sending',\n messageHeld: 'Sends when you continue',\n messageNotSent: 'Not sent',\n messageDelivered: 'Delivered',\n messageCutOff: 'This reply was cut off.',\n takeoverStarted: 'A person from {by} is replying now.',\n takeoverEnded: '{agent} is back.',\n handoffCreated: \"We've passed this to the team. They'll reply {expected}.\",\n handoffCreatedNoTime: \"We've passed this to the team. They'll reply soon.\",\n flowSent: 'Your answers were sent.',\n flowNotSent: \"Your answers couldn't be sent yet.\",\n turnFailed: 'Something went wrong.',\n working: '{agent} is working on it…',\n proposalConfirm: 'Confirm',\n proposalDecline: 'Decline',\n proposalChange: 'Change',\n proposalConfirmed: 'Confirmed',\n proposalDeclined: 'Declined',\n proposalFailed: \"Couldn't be confirmed\",\n proposalExpired: 'Expired',\n proposalSettled: 'No longer open',\n questionSubmit: 'Send',\n questionSkip: 'Skip',\n questionOther: 'Other',\n questionSearch: 'Search',\n questionAnswered: 'Answered',\n questionReplaced: 'Replaced by a newer question',\n questionStep: 'Question {step} of {total}',\n questionAddPhoto: 'Add a photo',\n questionCharactersLeft: '{count} characters left',\n questionCharactersLeftOne: '{count} character left',\n priceFrom: 'From {price}',\n /** A listing with no rating yet; empty draws nothing, a tenant's word (\"New\") draws in the rating's place. */\n ratingNone: '',\n nextAvailable: 'Next: {time}',\n /** A time today and tomorrow, as `nextAvailable` says it (`{time}`: \"10:00 AM\"). */\n today: 'today, {time}',\n tomorrow: 'tomorrow, {time}',\n agentEnded: 'This conversation ended',\n agentEndedBody: 'Start a new one whenever you like.',\n agentStartOver: 'Start a new conversation',\n agentUnreachable: \"Couldn't reach {agent}\",\n agentUnreachableBody: 'Check your connection and try again.',\n agentOff: \"{agent} isn't available right now\",\n agentOffBody: 'Please try again later.',\n helpful: 'Was this helpful?',\n helpfulYes: 'Yes',\n helpfulNo: 'No',\n helpfulThanks: 'Thanks for telling us.',\n launcherOpen: 'Open {agent}',\n launcherGreeting: \"Hi, I'm {agent}. Ask me what you need.\",\n close: 'Close',\n welcomeFallback: \"Hi, I'm {agent}. How can I help?\",\n privacy: 'Privacy',\n cardsInRow: '{count} results, swipe for more',\n cardsInRowOne: '{count} result',\n open: 'Open',\n /** History: the person's past conversations, and reading one back. */\n historyEmpty: 'No conversations yet',\n historyEmptyBody: 'Your conversations with {agent} will show here.',\n historyFailed: \"Couldn't load your conversations.\",\n historyOff: 'History is not available.',\n historyMessages: '{count} messages',\n historyMessagesOne: '{count} message',\n historyEnded: 'Ended',\n historyContinue: 'Continue',\n historyDelete: 'Delete',\n historyDeleteTitle: 'Delete this conversation?',\n historyDeleteBody: \"It's removed from your history everywhere.\",\n historyDeleteFailed: \"Couldn't delete this conversation.\",\n cancel: 'Cancel',\n transcriptFailed: \"Couldn't load this conversation.\",\n transcriptGone: 'This conversation is no longer available.',\n transcriptEarlier: 'Earlier messages',\n /** Under the person's message a guardrail refused. */\n messageRefused: 'Not answered',\n loading: 'Loading…',\n} as const;\n\nexport type CopyKey = keyof typeof en;\nexport type Copy = Readonly<Record<CopyKey, string>>;\n/** A tenant's words, by key; a key left out (or undefined) keeps the built-in one. */\nexport type CopyOverrides = { readonly [K in CopyKey]?: string | undefined };\n\nconst es: Copy = {\n disclosureFallback:\n 'Estás hablando con un agente de IA. Con la tecnología de Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'el agente',\n you: 'Tú',\n staffLabel: '{by} · persona',\n staffFallbackRole: 'el equipo',\n composerPlaceholder: 'Escribe a {agent}',\n composerPlaceholderTakeover: 'Escribe a {by}',\n send: 'Enviar',\n stop: 'Detener',\n typeAnswerBelow: 'Escribe tu respuesta abajo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sin conexión. Los mensajes se envían cuando vuelvas.',\n bannerContinuedElsewhere: 'Esta conversación continuó en otro dispositivo.',\n bannerUnavailable: 'No se pudo conectar.',\n continueHere: 'Continuar aquí',\n tryAgain: 'Intentar de nuevo',\n talkToPerson: 'Hablar con una persona',\n messageSending: 'Enviando',\n messageHeld: 'Se envía cuando continúes',\n messageNotSent: 'No enviado',\n messageDelivered: 'Entregado',\n messageCutOff: 'Esta respuesta quedó incompleta.',\n takeoverStarted: 'Una persona de {by} está respondiendo.',\n takeoverEnded: '{agent} volvió.',\n handoffCreated: 'Le pasamos esto al equipo. Responderán {expected}.',\n handoffCreatedNoTime: 'Le pasamos esto al equipo. Responderán pronto.',\n flowSent: 'Tus respuestas se enviaron.',\n flowNotSent: 'Tus respuestas aún no se pudieron enviar.',\n turnFailed: 'Algo salió mal.',\n working: '{agent} está en ello…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Rechazar',\n proposalChange: 'Cambiar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Rechazado',\n proposalFailed: 'No se pudo confirmar',\n proposalExpired: 'Vencido',\n proposalSettled: 'Ya no está abierto',\n questionSubmit: 'Enviar',\n questionSkip: 'Omitir',\n questionOther: 'Otro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Reemplazada por una pregunta más reciente',\n questionStep: 'Pregunta {step} de {total}',\n questionAddPhoto: 'Agregar una foto',\n questionCharactersLeft: 'Quedan {count} caracteres',\n questionCharactersLeftOne: 'Queda {count} carácter',\n priceFrom: 'Desde {price}',\n ratingNone: '',\n nextAvailable: 'Próximo: {time}',\n today: 'hoy, {time}',\n tomorrow: 'mañana, {time}',\n agentEnded: 'Esta conversación terminó',\n agentEndedBody: 'Empieza una nueva cuando quieras.',\n agentStartOver: 'Empezar una conversación nueva',\n agentUnreachable: 'No se pudo contactar a {agent}',\n agentUnreachableBody: 'Revisa tu conexión e inténtalo de nuevo.',\n agentOff: '{agent} no está disponible ahora',\n agentOffBody: 'Inténtalo de nuevo más tarde.',\n helpful: '¿Te sirvió?',\n helpfulYes: 'Sí',\n helpfulNo: 'No',\n helpfulThanks: 'Gracias por contarnos.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Hola, soy {agent}. Pregúntame lo que necesites.',\n close: 'Cerrar',\n welcomeFallback: 'Hola, soy {agent}. ¿En qué te ayudo?',\n privacy: 'Privacidad',\n cardsInRow: '{count} resultados, desliza para ver más',\n cardsInRowOne: '{count} resultado',\n open: 'Abrir',\n historyEmpty: 'Aún no hay conversaciones',\n historyEmptyBody: 'Tus conversaciones con {agent} aparecerán aquí.',\n historyFailed: 'No se pudieron cargar tus conversaciones.',\n historyOff: 'El historial no está disponible.',\n historyMessages: '{count} mensajes',\n historyMessagesOne: '{count} mensaje',\n historyEnded: 'Terminada',\n historyContinue: 'Continuar',\n historyDelete: 'Eliminar',\n historyDeleteTitle: '¿Eliminar esta conversación?',\n historyDeleteBody: 'Se elimina de tu historial en todas partes.',\n historyDeleteFailed: 'No se pudo eliminar esta conversación.',\n cancel: 'Cancelar',\n transcriptFailed: 'No se pudo cargar esta conversación.',\n transcriptGone: 'Esta conversación ya no está disponible.',\n transcriptEarlier: 'Mensajes anteriores',\n messageRefused: 'Sin respuesta',\n loading: 'Cargando…',\n};\n\nconst ptBR: Copy = {\n disclosureFallback:\n 'Você está conversando com um agente de IA. Com tecnologia Vinaverse.',\n agentLabel: 'Agente de IA',\n agentFallbackName: 'o agente',\n you: 'Você',\n staffLabel: '{by} · pessoa',\n staffFallbackRole: 'a equipe',\n composerPlaceholder: 'Mensagem para {agent}',\n composerPlaceholderTakeover: 'Mensagem para {by}',\n send: 'Enviar',\n stop: 'Parar',\n typeAnswerBelow: 'Digite sua resposta abaixo.',\n bannerConnecting: 'Conectando…',\n bannerReconnecting: 'Reconectando…',\n bannerOffline: 'Sem conexão. As mensagens são enviadas quando você voltar.',\n bannerContinuedElsewhere: 'Esta conversa continuou em outro aparelho.',\n bannerUnavailable: 'Não foi possível conectar.',\n continueHere: 'Continuar aqui',\n tryAgain: 'Tentar de novo',\n talkToPerson: 'Falar com uma pessoa',\n messageSending: 'Enviando',\n messageHeld: 'Será enviada quando você continuar',\n messageNotSent: 'Não enviada',\n messageDelivered: 'Entregue',\n messageCutOff: 'Esta resposta foi interrompida.',\n takeoverStarted: 'Uma pessoa de {by} está respondendo agora.',\n takeoverEnded: '{agent} voltou.',\n handoffCreated: 'Passamos isso para a equipe. Eles vão responder {expected}.',\n handoffCreatedNoTime:\n 'Passamos isso para a equipe. Eles vão responder em breve.',\n flowSent: 'Suas respostas foram enviadas.',\n flowNotSent: 'Ainda não foi possível enviar suas respostas.',\n turnFailed: 'Algo deu errado.',\n working: '{agent} está cuidando disso…',\n proposalConfirm: 'Confirmar',\n proposalDecline: 'Recusar',\n proposalChange: 'Alterar',\n proposalConfirmed: 'Confirmado',\n proposalDeclined: 'Recusado',\n proposalFailed: 'Não foi possível confirmar',\n proposalExpired: 'Expirado',\n proposalSettled: 'Não está mais aberto',\n questionSubmit: 'Enviar',\n questionSkip: 'Pular',\n questionOther: 'Outro',\n questionSearch: 'Buscar',\n questionAnswered: 'Respondida',\n questionReplaced: 'Substituída por uma pergunta mais recente',\n questionStep: 'Pergunta {step} de {total}',\n questionAddPhoto: 'Adicionar uma foto',\n questionCharactersLeft: 'Restam {count} caracteres',\n questionCharactersLeftOne: 'Resta {count} caractere',\n priceFrom: 'A partir de {price}',\n ratingNone: '',\n nextAvailable: 'Próximo horário: {time}',\n today: 'hoje, {time}',\n tomorrow: 'amanhã, {time}',\n agentEnded: 'Esta conversa terminou',\n agentEndedBody: 'Comece uma nova quando quiser.',\n agentStartOver: 'Começar uma conversa nova',\n agentUnreachable: 'Não foi possível falar com {agent}',\n agentUnreachableBody: 'Verifique sua conexão e tente de novo.',\n agentOff: '{agent} não está disponível agora',\n agentOffBody: 'Tente de novo mais tarde.',\n helpful: 'Isso ajudou?',\n helpfulYes: 'Sim',\n helpfulNo: 'Não',\n helpfulThanks: 'Obrigado por avisar.',\n launcherOpen: 'Abrir {agent}',\n launcherGreeting: 'Oi, sou {agent}. Pergunte o que precisar.',\n close: 'Fechar',\n welcomeFallback: 'Oi, sou {agent}. Como posso ajudar?',\n privacy: 'Privacidade',\n cardsInRow: '{count} resultados, deslize para ver mais',\n cardsInRowOne: '{count} resultado',\n open: 'Abrir',\n historyEmpty: 'Nenhuma conversa ainda',\n historyEmptyBody: 'Suas conversas com {agent} vão aparecer aqui.',\n historyFailed: 'Não foi possível carregar suas conversas.',\n historyOff: 'O histórico não está disponível.',\n historyMessages: '{count} mensagens',\n historyMessagesOne: '{count} mensagem',\n historyEnded: 'Encerrada',\n historyContinue: 'Continuar',\n historyDelete: 'Excluir',\n historyDeleteTitle: 'Excluir esta conversa?',\n historyDeleteBody: 'Ela é removida do seu histórico em todos os lugares.',\n historyDeleteFailed: 'Não foi possível excluir esta conversa.',\n cancel: 'Cancelar',\n transcriptFailed: 'Não foi possível carregar esta conversa.',\n transcriptGone: 'Esta conversa não está mais disponível.',\n transcriptEarlier: 'Mensagens anteriores',\n messageRefused: 'Sem resposta',\n loading: 'Carregando…',\n};\n\n/** The built-in languages; any other locale falls back to English, its own `copy` overrides aside. */\nexport const COPY: Readonly<Record<'en' | 'es' | 'pt-BR', Copy>> = {\n en,\n es,\n 'pt-BR': ptBR,\n};\n\n/**\n * Keys a tenant may not override in a built-in language: the AI disclosure is the platform's, never removed or reworded.\n * In a language without built-in copy the tenant supplies them, translated, so the disclosure reads in the person's\n * language, and only a translation that still discloses is taken (`discloses`): the label says AI, the disclosure says\n * AI and names Vinaverse.\n */\nconst FIXED: ReadonlySet<CopyKey> = new Set([\n 'disclosureFallback',\n 'agentLabel',\n]);\n\n/**\n * \"AI\" as languages write it: AI, IA (es, pt, fr, it, ro), KI (de, nl, da, no, sv), SI (pl), YZ (tr), ИИ (ru), ШІ\n * (uk), and the words for it in Arabic, Hebrew, Hindi, Chinese, Japanese and Korean.\n */\nexport const AI_MARK =\n /(?:^|[^\\p{L}])(?:AI|IA|KI|SI|YZ|ИИ|ШІ)(?:$|[^\\p{L}])|الذكاء الاصطناعي|بالذكاء|בינה מלאכותית|एआई|कृत्रिम बुद्धि|人工智能|人工知能|인공지능/u;\n\n/**\n * Whether a tenant's text for a fixed key still makes the AI disclosure: the label says AI; the disclosure says AI\n * and names Vinaverse. A tenant's translation that does not is ignored, and the English built-in shows instead.\n */\nfunction discloses(key: string, value: string): boolean {\n if (!AI_MARK.test(value)) return false;\n return key !== 'disclosureFallback' || value.includes('Vinaverse');\n}\n\nexport type Translate = (\n key: CopyKey,\n vars?: Readonly<Record<string, string | number>>,\n) => string;\n\n/** The built-in copy for a locale: its language (`es-US` → `es`, `pt-PT` → `pt-BR`), else null. */\nfunction builtIn(locale: string | undefined): Copy | null {\n const language = (locale ?? 'en').split(/[-_]/)[0]?.toLowerCase();\n if (language === 'en') return COPY.en;\n if (language === 'es') return COPY.es;\n if (language === 'pt') return COPY['pt-BR'];\n return null;\n}\n\n/** The built-in copy for a locale, English when the language has none. */\nexport function builtInCopy(locale: string | undefined): Copy {\n return builtIn(locale) ?? COPY.en;\n}\n\n/** A translator for a locale, with the tenant's overrides on top (fixed keys excepted). */\nexport function createTranslate(\n locale: string | undefined,\n overrides: CopyOverrides = {},\n): Translate {\n const own = builtIn(locale);\n const merged: Record<string, string> = { ...(own ?? COPY.en) };\n for (const [key, value] of Object.entries(overrides)) {\n if (value === undefined) continue;\n if (FIXED.has(key as CopyKey) && !(own === null && discloses(key, value)))\n continue;\n merged[key] = value;\n // The tenant's words for a count, without their own `One` form: theirs for every count, never ours for 1.\n if (!(`${key}One` in overrides)) delete merged[`${key}One`];\n }\n return (key, vars) =>\n (\n (vars?.count === 1 ? merged[`${key}One`] : undefined) ??\n merged[key] ??\n en[key]\n ).replace(/\\{(\\w+)\\}/g, (all, name: string) =>\n vars && name in vars ? String(vars[name]) : all,\n );\n}\n\n/**\n * Words a Vinaverse UI never says to people (a tenant override that uses them gets a development warning): the\n * runtime is an agent, never an assistant or a bot; and never \"crew\".\n */\nexport const BANNED_WORDS: readonly RegExp[] = [\n /\\bassistant/i,\n /\\basistente/i,\n /\\bassistent/i,\n /\\bbot\\b/i,\n /\\bcrew\\b/i,\n];\n\n/** The overrides that use a banned word, by key. */\nexport function bannedWordsIn(overrides: CopyOverrides): CopyKey[] {\n return (Object.entries(overrides) as [CopyKey, string | undefined][])\n .filter(([, v]) => v !== undefined && BANNED_WORDS.some((w) => w.test(v)))\n .map(([k]) => k);\n}\n","// Dates, times, money and text direction in the person's locale, through Intl (Hermes has it), with a plain fallback\n// where a runtime lacks it.\n\n/** Languages and scripts written right to left. */\nconst RTL_LANGUAGES = new Set([\n 'ar',\n 'he',\n 'iw',\n 'fa',\n 'ur',\n 'ps',\n 'yi',\n 'dv',\n 'ckb',\n 'sd',\n 'ug',\n 'syr',\n]);\nconst RTL_SCRIPTS = new Set([\n 'arab',\n 'hebr',\n 'thaa',\n 'syrc',\n 'nkoo',\n 'adlm',\n 'rohg',\n]);\n\n/** `rtl` for Arabic, Hebrew, Persian, Urdu and the other right-to-left languages and scripts; `ltr` otherwise. */\nexport function textDirection(locale: string | undefined): 'ltr' | 'rtl' {\n const parts = (locale ?? '').toLowerCase().split(/[-_]/);\n if (parts.some((p) => p.length === 4 && RTL_SCRIPTS.has(p))) return 'rtl';\n return RTL_LANGUAGES.has(parts[0] ?? '') ? 'rtl' : 'ltr';\n}\n\n/** An amount in minor units (`amount` cents) in its currency: `$85.00`. */\nexport function formatMoney(\n amountMinor: number,\n currency: string,\n locale?: string,\n): string {\n try {\n const format = new Intl.NumberFormat(locale, {\n style: 'currency',\n currency,\n });\n const digits = format.resolvedOptions().maximumFractionDigits ?? 2;\n return format.format(amountMinor / 10 ** digits);\n } catch {\n return `${currency} ${(amountMinor / 100).toFixed(2)}`;\n }\n}\n\n/** A start and an end: \"Wed, Oct 14, 10:00 – 11:30 AM\" in the locale and time zone. */\nexport function formatTimeRange(\n start: string,\n end: string | undefined,\n locale?: string,\n timeZone?: string,\n): string {\n const from = new Date(start);\n if (Number.isNaN(from.getTime())) return start;\n const options: Intl.DateTimeFormatOptions = {\n weekday: 'short',\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n };\n try {\n const format = new Intl.DateTimeFormat(locale, options);\n const to = end ? new Date(end) : null;\n if (!to || Number.isNaN(to.getTime())) return format.format(from);\n return typeof format.formatRange === 'function'\n ? format.formatRange(from, to)\n : `${format.format(from)} – ${format.format(to)}`;\n } catch {\n return from.toISOString();\n }\n}\n\n/** The day a moment falls on in a time zone, as a day count, so two days compare across DST. */\nfunction dayOf(at: Date, timeZone: string | undefined): number {\n const [y, m, d] = new Intl.DateTimeFormat('en-CA', {\n year: 'numeric',\n month: '2-digit',\n day: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n })\n .format(at)\n .split('-')\n .map(Number);\n return Date.UTC(y as number, (m as number) - 1, d as number) / 86_400_000;\n}\n\n/**\n * A moment as a person says it: \"today, 10:00 AM\" and \"tomorrow, 10:00 AM\" (`today` and `tomorrow` are the copy's\n * words, with `{time}`), else the date and time (\"Fri, Oct 17, 10:00 AM\"), in the locale and time zone. `now` is the\n * clock it is judged by.\n */\nexport function formatDayTime(\n start: string,\n words: { readonly today: string; readonly tomorrow: string },\n locale?: string,\n timeZone?: string,\n now: number = Date.now(),\n): string {\n const at = new Date(start);\n if (Number.isNaN(at.getTime())) return start;\n try {\n const days = dayOf(at, timeZone) - dayOf(new Date(now), timeZone);\n const word = days === 0 ? words.today : days === 1 ? words.tomorrow : '';\n if (!word) return formatTimeRange(start, undefined, locale, timeZone);\n const time = new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: '2-digit',\n ...(timeZone ? { timeZone } : {}),\n }).format(at);\n return word.replace('{time}', time);\n } catch {\n return formatTimeRange(start, undefined, locale, timeZone);\n }\n}\n\n/** A calendar date (`YYYY-MM-DD`) in the locale: \"October 14, 2026\". */\nexport function formatDate(date: string, locale?: string): string {\n const m = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(date);\n if (!m) return date;\n try {\n return new Intl.DateTimeFormat(locale, {\n year: 'numeric',\n month: 'long',\n day: 'numeric',\n timeZone: 'UTC',\n }).format(new Date(Date.UTC(Number(m[1]), Number(m[2]) - 1, Number(m[3]))));\n } catch {\n return date;\n }\n}\n\n/** A moment with its date and time in the locale and zone: \"Oct 15, 2026, 9:30 AM\"; the text as given when it is not one. */\nexport function formatDateTime(\n at: string,\n locale?: string,\n timeZone?: string,\n): string {\n const date = new Date(at);\n if (Number.isNaN(date.getTime())) return at;\n try {\n return new Intl.DateTimeFormat(locale, {\n dateStyle: 'medium',\n timeStyle: 'short',\n ...(timeZone ? { timeZone } : {}),\n }).format(date);\n } catch {\n return date.toISOString();\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vinaverse/tokens",
3
- "version": "0.1.0-alpha.10",
3
+ "version": "0.1.0-alpha.12",
4
4
  "description": "Vinaverse design tokens and copy shared by every UI kit: colors for light and dark, type, spacing, radii, motion, a contrast check; and the words the kits say, with the rules on them.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Vinaverse, Inc.",
@@ -78,7 +78,7 @@
78
78
  "name": "@vinaverse/tokens/copy (ESM, everything)",
79
79
  "path": "dist/copy/index.js",
80
80
  "import": "*",
81
- "limit": "4 kB"
81
+ "limit": "4.25 kB"
82
82
  }
83
83
  ],
84
84
  "scripts": {