* feat(mailer): add i18n support for all transactional emails with pt-BR translations - Create Liquid i18n filter (LiquidFilters::I18nFilter) exposing I18n.t() as `t` filter with interpolation support via positional args - Replace hardcoded English strings in all 26 Liquid email templates with i18n keys - Replace hardcoded English strings in all 5 Devise ERB email templates (OSS + enterprise) with t() calls, using raw output (<%==) to prevent HTML-encoding of apostrophes - Translate all mailer subjects to use I18n.t() for locale-aware rendering - Add comprehensive pt-BR translations for all transactional emails - Add SSO-specific i18n keys for enterprise confirmation instructions - Fix ApplicationRecord#to_drop to walk STI hierarchy (e.g. SuperAdmin -> UserDrop) * fix: address CodeRabbit review feedback - Use _html suffix for Devise translation keys to prevent XSS while keeping apostrophes unencoded (Rails escapes interpolations automatically) - Replace hardcoded English in SLA templates with full_body i18n keys - Fix _target="blank" typo to target="_blank" in attachment links - Add i18n for tiktok_disconnect subject and create liquid template - Extract brand_name to private method in AccountNotificationMailer * fix: address round 2 review feedback Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
75 lines
2.7 KiB
Ruby
75 lines
2.7 KiB
Ruby
class AdministratorNotifications::AccountNotificationMailer < AdministratorNotifications::BaseMailer
|
|
def account_deletion_user_initiated(account, reason)
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.account_deletion_user_initiated.subject', brand_name: brand_name)
|
|
action_url = settings_url('general')
|
|
meta = {
|
|
'account_name' => account.name,
|
|
'deletion_date' => format_deletion_date(account.custom_attributes['marked_for_deletion_at']),
|
|
'reason' => reason
|
|
}
|
|
|
|
send_notification(subject, action_url: action_url, meta: meta)
|
|
end
|
|
|
|
def account_deletion_for_inactivity(account, reason)
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.account_deletion_for_inactivity.subject', brand_name: brand_name)
|
|
action_url = settings_url('general')
|
|
meta = {
|
|
'account_name' => account.name,
|
|
'deletion_date' => format_deletion_date(account.custom_attributes['marked_for_deletion_at']),
|
|
'reason' => reason
|
|
}
|
|
|
|
send_notification(subject, action_url: action_url, meta: meta)
|
|
end
|
|
|
|
def contact_import_complete(resource)
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.contact_import_complete.subject')
|
|
|
|
action_url = if resource.failed_records.attached?
|
|
Rails.application.routes.url_helpers.rails_blob_url(resource.failed_records)
|
|
else
|
|
"#{ENV.fetch('FRONTEND_URL', nil)}/app/accounts/#{resource.account.id}/contacts"
|
|
end
|
|
|
|
meta = {
|
|
'failed_contacts' => resource.total_records - resource.processed_records,
|
|
'imported_contacts' => resource.processed_records
|
|
}
|
|
|
|
send_notification(subject, action_url: action_url, meta: meta)
|
|
end
|
|
|
|
def contact_import_failed
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.contact_import_failed.subject')
|
|
send_notification(subject)
|
|
end
|
|
|
|
def contact_export_complete(file_url, email_to)
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.contact_export_complete.subject')
|
|
send_notification(subject, to: email_to, action_url: file_url)
|
|
end
|
|
|
|
def automation_rule_disabled(rule)
|
|
subject = I18n.t('mailer.administrator_notifications.account_notifications.automation_rule_disabled.subject')
|
|
action_url = settings_url('automation/list')
|
|
meta = { 'rule_name' => rule.name }
|
|
|
|
send_notification(subject, action_url: action_url, meta: meta)
|
|
end
|
|
|
|
private
|
|
|
|
def brand_name
|
|
GlobalConfig.get('BRAND_NAME')['BRAND_NAME'].presence || 'Chatwoot'
|
|
end
|
|
|
|
def format_deletion_date(deletion_date_str)
|
|
return 'Unknown' if deletion_date_str.blank?
|
|
|
|
Time.zone.parse(deletion_date_str).strftime('%B %d, %Y')
|
|
rescue StandardError
|
|
'Unknown'
|
|
end
|
|
end
|