diff --git a/config/locales/i18n.yml b/config/locales/i18n.yml
index 5bbacbd0..fc09f656 100644
--- a/config/locales/i18n.yml
+++ b/config/locales/i18n.yml
@@ -577,6 +577,35 @@ en: &en
opened: Opened
sent: Sent
awaiting: Awaiting
+ document_id: Document ID
+ envelope_id: Envelope ID
+ event_log: Event Log
+ verify: Verify
+ testing_log_not_for_production_use: Testing Log - Not for Production Use
+ original_sha256: Original SHA256
+ result_sha256: Result SHA256
+ generated_at: Generated at
+ email_verification: Email verification
+ phone_verification: Phone verification
+ session_id: Session ID
+ type_field: '%{type} Field'
+ paid_price: 'Paid %{price}'
+ verified: Verified
+ unverified: Unverified
+ submission_event_names:
+ send_email_to_html: 'Email sent to %{submitter_name}'
+ send_reminder_email_to_html: 'Reminder email sent to %{submitter_name}'
+ send_sms_to_html: 'SMS sent to %{submitter_name}'
+ send_2fa_sms_to_html: 'Verification SMS sent to %{submitter_name}'
+ open_email_by_html: 'Email opened by %{submitter_name}'
+ click_email_by_html: 'Email link clicked by %{submitter_name}'
+ click_sms_by_html: 'SMS link clicked by %{submitter_name}'
+ phone_verified_by_html: 'Phone verified by %{submitter_name}'
+ start_form_by_html: 'Submission started by %{submitter_name}'
+ view_form_by_html: 'Form viewed by %{submitter_name}'
+ invite_party_by_html: 'Invited %{invited_submitter_name} by %{submitter_name}'
+ complete_form_by_html: 'Submission completed by %{submitter_name}'
+ api_complete_form_by_html: 'Submission completed via API by %{submitter_name}'
import_list:
select_worksheet: Select Worksheet
open: Open
@@ -1158,6 +1187,35 @@ es: &es
opened: Abierto
sent: Enviado
awaiting: Pendiente
+ document_id: ID del Documento
+ envelope_id: ID del Sobre
+ event_log: Registro de Eventos
+ verify: Verificar
+ testing_log_not_for_production_use: Registro de Pruebas - No para Uso en Producción
+ original_sha256: SHA256 Original
+ result_sha256: SHA256 del Resultado
+ generated_at: Generado el
+ email_verification: Verificación de correo electrónico
+ phone_verification: Verificación telefónica
+ session_id: ID de la Sesión
+ type_field: 'Campo %{type}'
+ paid_price: 'Pagado %{price}'
+ verified: Verificado
+ unverified: No verificado
+ submission_event_names:
+ send_email_to_html: 'Correo electrónico enviado a %{submitter_name}'
+ send_reminder_email_to_html: 'Correo de recordatorio enviado a %{submitter_name}'
+ send_sms_to_html: 'SMS enviado a %{submitter_name}'
+ send_2fa_sms_to_html: 'SMS de verificación enviado a %{submitter_name}'
+ open_email_by_html: 'Correo electrónico abierto por %{submitter_name}'
+ click_email_by_html: 'Enlace del correo electrónico clicado por %{submitter_name}'
+ click_sms_by_html: 'Enlace del SMS clicado por %{submitter_name}'
+ phone_verified_by_html: 'Teléfono verificado por %{submitter_name}'
+ start_form_by_html: 'Envío iniciado por %{submitter_name}'
+ view_form_by_html: 'Formulario visto por %{submitter_name}'
+ invite_party_by_html: 'Invitado %{invited_submitter_name} por %{submitter_name}'
+ complete_form_by_html: 'Envío completado por %{submitter_name}'
+ api_complete_form_by_html: 'Envío completado vía API por %{submitter_name}'
import_list:
select_worksheet: Seleccionar hoja de cálculo
open: Abrir
@@ -1739,6 +1797,35 @@ it: &it
opened: Aperto
sent: Inviato
awaiting: In attesa
+ document_id: ID del Documento
+ envelope_id: ID della Busta
+ event_log: Registro degli Eventi
+ verify: Verifica
+ testing_log_not_for_production_use: Registro di Test - Non per Uso in Produzione
+ original_sha256: SHA256 Originale
+ result_sha256: SHA256 del Risultato
+ generated_at: Generato il
+ email_verification: Verifica e-mail
+ phone_verification: Verifica telefono
+ session_id: ID della Sessione
+ type_field: 'Campo %{type}'
+ paid_price: 'Pagato %{price}'
+ verified: Verificato
+ unverified: Non verificato
+ submission_event_names:
+ send_email_to_html: 'E-mail inviato a %{submitter_name}'
+ send_reminder_email_to_html: 'E-mail di promemoria inviato a %{submitter_name}'
+ send_sms_to_html: 'SMS inviato a %{submitter_name}'
+ send_2fa_sms_to_html: 'SMS di verifica inviato a %{submitter_name}'
+ open_email_by_html: 'E-mail aperta da %{submitter_name}'
+ click_email_by_html: "Link dell'e-mail cliccato da %{submitter_name}"
+ click_sms_by_html: "Link dell'SMS cliccato da %{submitter_name}"
+ phone_verified_by_html: 'Telefono verificato da %{submitter_name}'
+ start_form_by_html: 'Invio iniziato da %{submitter_name}'
+ view_form_by_html: 'Modulo visualizzato da %{submitter_name}'
+ invite_party_by_html: 'Invitato %{invited_submitter_name} da %{submitter_name}'
+ complete_form_by_html: 'Invio completato da %{submitter_name}'
+ api_complete_form_by_html: 'Invio completato tramite API da %{submitter_name}'
import_list:
select_worksheet: Seleziona il foglio di lavoro
open: Apri
@@ -2321,6 +2408,35 @@ fr: &fr
opened: Ouvert
sent: Envoyé
awaiting: En attente
+ document_id: ID du document
+ envelope_id: ID de l'enveloppe
+ event_log: Journal d'événements
+ verify: Vérifier
+ testing_log_not_for_production_use: Journal de test - Ne pas utiliser en production
+ original_sha256: SHA256 original
+ result_sha256: SHA256 du résultat
+ generated_at: Généré le
+ email_verification: Vérification de l'e-mail
+ phone_verification: Vérification du téléphone
+ session_id: ID de session
+ type_field: 'Champ %{type}'
+ paid_price: 'Payé %{price}'
+ verified: Vérifié
+ unverified: Non vérifié
+ submission_event_names:
+ send_email_to_html: 'E-mail envoyé à %{submitter_name}'
+ send_reminder_email_to_html: 'E-mail de rappel envoyé à %{submitter_name}'
+ send_sms_to_html: 'SMS envoyé à %{submitter_name}'
+ send_2fa_sms_to_html: 'SMS de vérification envoyé à %{submitter_name}'
+ open_email_by_html: 'E-mail ouvert par %{submitter_name}'
+ click_email_by_html: "Lien de l'e-mail cliqué par %{submitter_name}"
+ click_sms_by_html: 'Lien du SMS cliqué par %{submitter_name}'
+ phone_verified_by_html: 'Téléphone vérifié par %{submitter_name}'
+ start_form_by_html: 'Soumission commencée par %{submitter_name}'
+ view_form_by_html: 'Formulaire consulté par %{submitter_name}'
+ invite_party_by_html: 'Invité %{invited_submitter_name} par %{submitter_name}'
+ complete_form_by_html: 'Soumission terminée par %{submitter_name}'
+ api_complete_form_by_html: "Soumission terminée via l'API par %{submitter_name}"
import_list:
select_worksheet: Sélectionner la feuille de calcul
open: Ouvrir
@@ -2902,6 +3018,35 @@ pt: &pt
opened: Aberto
sent: Enviado
awaiting: Aguardando
+ document_id: ID do Documento
+ envelope_id: ID do Envelope
+ event_log: Log de Eventos
+ verify: Verificar
+ testing_log_not_for_production_use: Log de Teste - Não para Uso em Produção
+ original_sha256: SHA256 Original
+ result_sha256: SHA256 do Resultado
+ generated_at: Gerado em
+ email_verification: Verificação de E-mail
+ phone_verification: Verificação de Telefone
+ session_id: ID da Sessão
+ type_field: 'Campo %{type}'
+ paid_price: 'Pago %{price}'
+ verified: Verificado
+ unverified: Não verificado
+ submission_event_names:
+ send_email_to_html: 'E-mail enviado para %{submitter_name}'
+ send_reminder_email_to_html: 'E-mail de lembrete enviado para %{submitter_name}'
+ send_sms_to_html: 'SMS enviado para %{submitter_name}'
+ send_2fa_sms_to_html: 'SMS de verificação enviado para %{submitter_name}'
+ open_email_by_html: 'E-mail aberto por %{submitter_name}'
+ click_email_by_html: 'Link do e-mail clicado por %{submitter_name}'
+ click_sms_by_html: 'Link do SMS clicado por %{submitter_name}'
+ phone_verified_by_html: 'Telefone verificado por %{submitter_name}'
+ start_form_by_html: 'Submissão iniciada por %{submitter_name}'
+ view_form_by_html: 'Formulário visualizado por %{submitter_name}'
+ invite_party_by_html: 'Convidado %{invited_submitter_name} por %{submitter_name}'
+ complete_form_by_html: 'Submissão concluída por %{submitter_name}'
+ api_complete_form_by_html: 'Submissão concluída via API por %{submitter_name}'
import_list:
select_worksheet: Selecionar planilha
open: Abrir
@@ -3483,6 +3628,35 @@ de: &de
opened: Geöffnet
sent: Gesendet
awaiting: Ausstehend
+ document_id: Dokumenten-ID
+ envelope_id: Umschlag-ID
+ event_log: Ereignisprotokoll
+ verify: Überprüfen
+ testing_log_not_for_production_use: Testprotokoll - Nicht für den Produktionseinsatz
+ original_sha256: Original SHA256
+ result_sha256: Ergebnis SHA256
+ generated_at: Generiert am
+ email_verification: E-Mail-Verifizierung
+ phone_verification: Telefonverifizierung
+ session_id: Sitzungs-ID
+ type_field: '%{type} Feld'
+ paid_price: 'Bezahlt %{price}'
+ verified: Verifiziert
+ unverified: Nicht verifiziert
+ submission_event_names:
+ send_email_to_html: 'E-Mail gesendet an %{submitter_name}'
+ send_reminder_email_to_html: 'Erinnerungs-E-Mail gesendet an %{submitter_name}'
+ send_sms_to_html: 'SMS gesendet an %{submitter_name}'
+ send_2fa_sms_to_html: 'Verifizierungs-SMS gesendet an %{submitter_name}'
+ open_email_by_html: 'E-Mail geöffnet von %{submitter_name}'
+ click_email_by_html: 'E-Mail-Link angeklickt von %{submitter_name}'
+ click_sms_by_html: 'SMS-Link angeklickt von %{submitter_name}'
+ phone_verified_by_html: 'Telefon verifiziert von %{submitter_name}'
+ start_form_by_html: 'Einreichung gestartet von %{submitter_name}'
+ view_form_by_html: 'Formular angesehen von %{submitter_name}'
+ invite_party_by_html: 'Eingeladen %{invited_submitter_name} von %{submitter_name}'
+ complete_form_by_html: 'Einreichung abgeschlossen von %{submitter_name}'
+ api_complete_form_by_html: 'Einreichung über API abgeschlossen von %{submitter_name}'
import_list:
select_worksheet: Arbeitsblatt auswählen
open: Öffnen
diff --git a/lib/submission_events.rb b/lib/submission_events.rb
index e4f93e9e..1705ba41 100644
--- a/lib/submission_events.rb
+++ b/lib/submission_events.rb
@@ -3,22 +3,6 @@
module SubmissionEvents
TRACKING_PARAM_LENGTH = 6
- EVENT_NAMES = {
- send_email: 'Email sent',
- send_reminder_email: 'Reminder email sent',
- send_sms: 'SMS sent',
- send_2fa_sms: 'Verification SMS sent',
- open_email: 'Email opened',
- click_email: 'Email link clicked',
- click_sms: 'SMS link clicked',
- phone_verified: 'Phone verified',
- start_form: 'Submission started',
- view_form: 'Form viewed',
- invite_party: 'Invited',
- complete_form: 'Submission completed',
- api_complete_form: 'Submission completed via API'
- }.freeze
-
module_function
def build_tracking_param(submitter, event_type = 'click_email')
diff --git a/lib/submissions/generate_audit_trail.rb b/lib/submissions/generate_audit_trail.rb
index 5eb39b8f..dbb46c02 100644
--- a/lib/submissions/generate_audit_trail.rb
+++ b/lib/submissions/generate_audit_trail.rb
@@ -12,9 +12,6 @@ module Submissions
'Helvetica'
end
- VERIFIED_TEXT = 'Verified'
- UNVERIFIED_TEXT = 'Unverified'
-
CURRENCY_SYMBOLS = {
'USD' => '$',
'EUR' => '€',
@@ -32,35 +29,37 @@ module Submissions
# rubocop:disable Metrics
def call(submission)
- document = build_audit_trail(submission)
-
account = submission.account
- pkcs = Accounts.load_signing_pkcs(account)
- tsa_url = Accounts.load_timeserver_url(account)
+ I18n.with_locale(account.locale) do
+ document = build_audit_trail(submission)
- io = StringIO.new
+ pkcs = Accounts.load_signing_pkcs(account)
+ tsa_url = Accounts.load_timeserver_url(account)
- document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
+ io = StringIO.new
- last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
+ document.trailer.info[:Creator] = "#{Docuseal.product_name} (#{Docuseal::PRODUCT_URL})"
- sign_params = {
- reason: sign_reason,
- **Submissions::GenerateResultAttachments.build_signing_params(last_submitter, pkcs, tsa_url)
- }
+ last_submitter = submission.submitters.select(&:completed_at).max_by(&:completed_at)
- document.sign(io, **sign_params)
+ sign_params = {
+ reason: sign_reason,
+ **Submissions::GenerateResultAttachments.build_signing_params(last_submitter, pkcs, tsa_url)
+ }
- Submissions::GenerateResultAttachments.maybe_enable_ltv(io, sign_params)
+ document.sign(io, **sign_params)
- ActiveStorage::Attachment.create!(
- blob: ActiveStorage::Blob.create_and_upload!(
- io: io.tap(&:rewind), filename: "Audit Log - #{submission.template.name}.pdf"
- ),
- name: 'audit_trail',
- record: submission
- )
+ Submissions::GenerateResultAttachments.maybe_enable_ltv(io, sign_params)
+
+ ActiveStorage::Attachment.create!(
+ blob: ActiveStorage::Blob.create_and_upload!(
+ io: io.tap(&:rewind), filename: "#{I18n.t('audit_log')} - #{submission.template.name}.pdf"
+ ),
+ name: 'audit_trail',
+ record: submission
+ )
+ end
end
def build_audit_trail(submission)
@@ -130,7 +129,7 @@ module Submissions
TESTING_FOOTER
end
else
- "Document ID: #{document_id}"
+ "#{I18n.t('document_id')}: #{document_id}"
end
text = HexaPDF::Layout::TextFragment.create(
@@ -158,17 +157,19 @@ module Submissions
composer.column(columns: 1) do |column|
add_logo(column, submission)
- column.text(account.testing? ? 'Testing Log - Not for Production Use' : 'Audit Log',
+ column.text(account.testing? ? I18n.t('testing_log_not_for_production_use') : I18n.t('audit_log'),
font_size: 16,
padding: [10, 0, 0, 0],
position: :float, text_align: :right)
end
composer.column(columns: 1) do |column|
- column.text("Envelope ID: #{submission.id}", font_size: 12, padding: [15, 0, 8, 0], position: :float)
+ column.text("#{I18n.t('envelope_id')}: #{submission.id}", font_size: 12,
+ padding: [15, 0, 8, 0],
+ position: :float)
unless submission.source.in?(%w[embed api])
- column.formatted_text([{ link: verify_url, text: 'Verify', style: :link }],
+ column.formatted_text([{ link: verify_url, text: I18n.t('verify'), style: :link }],
font_size: 9, padding: [15, 0, 10, 0], position: :float, text_align: :right)
end
end
@@ -197,13 +198,13 @@ module Submissions
),
composer.document.layout.formatted_text_box(
[
- { text: "Original SHA256:\n", font: [FONT_NAME, { variant: :bold }] },
+ { text: "#{I18n.t('original_sha256')}:\n", font: [FONT_NAME, { variant: :bold }] },
original_documents.map { |d| d.metadata['sha256'] || d.checksum }.join("\n"),
"\n",
- { text: "Result SHA256:\n", font: [FONT_NAME, { variant: :bold }] },
+ { text: "#{I18n.t('result_sha256')}:\n", font: [FONT_NAME, { variant: :bold }] },
document.metadata['sha256'] || document.checksum,
"\n",
- { text: 'Generated at: ', font: [FONT_NAME, { variant: :bold }] },
+ { text: "#{I18n.t('generated_at')}: ", font: [FONT_NAME, { variant: :bold }] },
"#{I18n.l(document.created_at.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
"#{TimeUtils.timezone_abbr(account.timezone, document.created_at)}"
], line_spacing: 1.3
@@ -250,13 +251,13 @@ module Submissions
composer.document.layout.formatted_text_box(
[
submitter.email && click_email_event && {
- text: "Email verification: #{VERIFIED_TEXT}\n"
+ text: "#{I18n.t('email_verification')}: #{I18n.t('verified')}\n"
},
submitter.phone && is_phone_verified && {
- text: "Phone verification: #{VERIFIED_TEXT}\n"
+ text: "#{I18n.t('phone_verification')}: #{I18n.t('verified')}\n"
},
completed_event.data['ip'] && { text: "IP: #{completed_event.data['ip']}\n" },
- completed_event.data['sid'] && { text: "Session ID: #{completed_event.data['sid']}\n" },
+ completed_event.data['sid'] && { text: "#{I18n.t('session_id')}: #{completed_event.data['sid']}\n" },
completed_event.data['ua'] && { text: "User agent: #{completed_event.data['ua']}\n" },
"\n"
].compact_blank, line_spacing: 1.3, padding: [10, 20, 20, 0]
@@ -284,7 +285,8 @@ module Submissions
[
{
text: TextUtils.maybe_rtl_reverse(field_name).upcase.presence ||
- "#{field['type']} Field #{submitter_field_counters[field['type']]}\n".upcase,
+ "#{I18n.t('type_field',
+ type: field['type'])} #{submitter_field_counters[field['type']]}\n".upcase,
font_size: 6
}
].compact_blank,
@@ -316,7 +318,8 @@ module Submissions
price = ApplicationController.helpers.number_to_currency(field['preferences']['price'], unit:)
- composer.formatted_text_box([{ text: "Paid #{price}\n" }], padding: [0, 0, 10, 0])
+ composer.formatted_text_box([{ text: "#{I18n.t('paid_price', price:)}\n" }],
+ padding: [0, 0, 10, 0])
end
composer.formatted_text_box(
@@ -354,31 +357,38 @@ module Submissions
composer.draw_box(divider)
end
- composer.text('Event Log', font_size: 12, padding: [10, 0, 20, 0])
+ composer.text(I18n.t('event_log'), font_size: 12, padding: [10, 0, 20, 0])
events_data = submission.submission_events.sort_by(&:event_timestamp).map do |event|
submitter = submission.submitters.find { |e| e.id == event.submitter_id }
+ submitter_name =
+ if event.event_type.include?('sms') || event.event_type.include?('phone')
+ event.data['phone'] || submitter.phone
+ else
+ submitter.name || submitter.email || submitter.phone
+ end
- text = SubmissionEvents::EVENT_NAMES[event.event_type.to_sym]
-
- if event.event_type == 'invite_party' &&
- (invited_submitter = submission.submitters.find { |e| e.uuid == event.data['uuid'] }) &&
- (name = submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name'))
- text += ['', invited_submitter.name || invited_submitter.email || invited_submitter.phone, name].join(' ')
- end
+ text =
+ if event.event_type == 'invite_party' &&
+ (invited_submitter = submission.submitters.find { |e| e.uuid == event.data['uuid'] }) &&
+ (name = submission.template_submitters.find { |e| e['uuid'] == event.data['uuid'] }&.dig('name'))
+ invited_submitter_name = [invited_submitter.name || invited_submitter.email || invited_submitter.phone,
+ name].join(' ')
+ I18n.t('submission_event_names.invite_party_by_html', invited_submitter_name:,
+ submitter_name:)
+ elsif event.event_type.include?('send_')
+ I18n.t("submission_event_names.#{event.event_type}_to_html", submitter_name:)
+ else
+ I18n.t("submission_event_names.#{event.event_type}_by_html", submitter_name:)
+ end
[
"#{I18n.l(event.event_timestamp.in_time_zone(account.timezone), format: :long, locale: account.locale)} " \
"#{TimeUtils.timezone_abbr(account.timezone, event.event_timestamp)}",
composer.document.layout.formatted_text_box(
[
- { text:, font: [FONT_NAME, { variant: :bold }] },
- event.event_type.include?('send_') ? ' to ' : ' by ',
- if event.event_type.include?('sms') || event.event_type.include?('phone')
- event.data['phone'] || submitter.phone
- else
- submitter.name || submitter.email || submitter.phone
- end
+ { text: text[%r{(.*?)}, 1], font: [FONT_NAME, { variant: :bold }] },
+ text[%r{(.*?)(.*)}, 2]
]
)
]
diff --git a/lib/submissions/generate_combined_attachment.rb b/lib/submissions/generate_combined_attachment.rb
index cf1838af..1c7bc1f3 100644
--- a/lib/submissions/generate_combined_attachment.rb
+++ b/lib/submissions/generate_combined_attachment.rb
@@ -38,7 +38,9 @@ module Submissions
def build_combined_pdf(submitter)
pdfs_index = Submissions::GenerateResultAttachments.generate_pdfs(submitter)
- audit_trail = Submissions::GenerateAuditTrail.build_audit_trail(submitter.submission)
+ audit_trail = I18n.with_locale(submitter.account.locale) do
+ Submissions::GenerateAuditTrail.build_audit_trail(submitter.submission)
+ end
audit_trail.dispatch_message(:complete_objects)