feat: expand internationalization and add identity management
This release significantly expands internationalization support and adds comprehensive identity management features. Internationalization (i18n): - Add 5 new languages: Spanish, Italian, German, Dutch, Portuguese - Expand from 3 to 8 total supported languages - Redesign language switcher for better scalability (dropdown UI) - Complete translations for all features across all languages Identity Management: - Multiple sender identities with per-identity signatures - Sub-addressing support (user+tag@domain.com) - Context-aware tag suggestions for sub-addresses - Identity badges in email viewer and list - Full CRUD operations for managing identities Newsletter Management: - RFC 2369 List-Unsubscribe support (one-click unsubscribe) - HTTP and mailto unsubscribe methods - Security validation prevents XSS attacks - Two-step confirmation with persistent dismissal Security & Accessibility: - Dark mode email readability (intelligent color transformation) - WCAG 2.0 Level AA color contrast compliance - Comprehensive XSS prevention with validation utilities - Unit test coverage for security-critical code (57 validation tests) Testing: - Add unit tests for validation utilities - Add unit tests for email sanitization - Add unit tests for color transformation - Full test coverage for XSS attack vectors
This commit is contained in:
+170
-5
@@ -52,7 +52,13 @@
|
||||
"expand": "Expand",
|
||||
"collapse": "Collapse",
|
||||
"expand_tooltip": "Expand",
|
||||
"collapse_tooltip": "Collapse"
|
||||
"collapse_tooltip": "Collapse",
|
||||
"mobile": {
|
||||
"search": "Search",
|
||||
"compose": "Compose",
|
||||
"go_back": "Go back"
|
||||
},
|
||||
"clear_search": "Clear search"
|
||||
},
|
||||
"email_list": {
|
||||
"no_emails": "No emails",
|
||||
@@ -63,7 +69,19 @@
|
||||
"to_recipients": "To {{count}} recipients",
|
||||
"and_others": "and {{count}} others",
|
||||
"draft": "Draft",
|
||||
"starred": "Starred"
|
||||
"starred": "Starred",
|
||||
"conversations_count": "{count} of {total} conversations",
|
||||
"conversations_count_plus": "{count}+ conversations",
|
||||
"conversations_count_simple": "{count} conversations",
|
||||
"no_conversations": "No conversations",
|
||||
"loading_more": "Loading more emails...",
|
||||
"no_more_emails": "No more emails to load",
|
||||
"batch_actions": {
|
||||
"mark_read": "Mark as read",
|
||||
"mark_unread": "Mark as unread",
|
||||
"delete": "Delete",
|
||||
"clear_selection": "Clear selection"
|
||||
}
|
||||
},
|
||||
"email_viewer": {
|
||||
"no_email_selected": "No email selected",
|
||||
@@ -129,6 +147,9 @@
|
||||
"minutes": "minutes"
|
||||
},
|
||||
"unknown_sender": "Unknown",
|
||||
"recipient_me": "me",
|
||||
"recipient_and_others": "{name} and {count} others",
|
||||
"recipient_to_prefix": "To:",
|
||||
"authentication": {
|
||||
"title": "Authentication",
|
||||
"status": {
|
||||
@@ -167,7 +188,35 @@
|
||||
"green": "Green",
|
||||
"blue": "Blue",
|
||||
"purple": "Purple",
|
||||
"pink": "Pink",
|
||||
"none": "None"
|
||||
},
|
||||
"tooltips": {
|
||||
"reply": "Reply",
|
||||
"archive": "Archive",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"spam": {
|
||||
"button_title": "Report spam",
|
||||
"not_spam_title": "Mark as legitimate",
|
||||
"toast_success": "Moved to Junk",
|
||||
"toast_batch": "{count} emails moved to Junk",
|
||||
"toast_undo": "Undo",
|
||||
"toast_not_spam_success": "Moved to Inbox",
|
||||
"toast_not_spam_batch": "{count} emails moved to Inbox",
|
||||
"error": "Failed to report spam",
|
||||
"error_not_spam": "Failed to restore email"
|
||||
},
|
||||
"unsubscribe_banner": {
|
||||
"label": "Newsletter",
|
||||
"button": "Unsubscribe",
|
||||
"confirm_title": "Unsubscribe from this sender?",
|
||||
"confirm_button": "Confirm",
|
||||
"cancel": "Cancel",
|
||||
"success_http": "Unsubscribe page opened in new tab",
|
||||
"success_mailto": "Unsubscribe request sent to your email client",
|
||||
"error": "Unable to unsubscribe",
|
||||
"dismiss": "Dismiss"
|
||||
}
|
||||
},
|
||||
"email_composer": {
|
||||
@@ -200,6 +249,12 @@
|
||||
"bcc_label": "Bcc:",
|
||||
"subject_label": "Subject:",
|
||||
"file_size_kb": "KB",
|
||||
"prefix": {
|
||||
"forward": "Fwd:",
|
||||
"reply": "Re:"
|
||||
},
|
||||
"no_subject": "(No Subject)",
|
||||
"unknown_sender": "Unknown",
|
||||
"quote": {
|
||||
"reply_header": "On {{date}}, {{sender}} wrote:",
|
||||
"forward_header": "---------- Forwarded message ----------",
|
||||
@@ -207,7 +262,8 @@
|
||||
"date": "Date: {{date}}",
|
||||
"subject": "Subject: {{subject}}",
|
||||
"to": "To: {{recipients}}"
|
||||
}
|
||||
},
|
||||
"remove_sub_address": "Remove sub-address"
|
||||
},
|
||||
"common": {
|
||||
"loading": "Loading...",
|
||||
@@ -243,7 +299,20 @@
|
||||
"error_loading": "Failed to load emails",
|
||||
"new_email": "New email",
|
||||
"new_email_from": "From {sender}",
|
||||
"click_to_view": "Click to view"
|
||||
"click_to_view": "Click to view",
|
||||
"email_moved": "Email moved",
|
||||
"emails_moved": "{count} emails moved",
|
||||
"moved_to_mailbox": "Moved to {mailbox}",
|
||||
"move_failed": "Move failed",
|
||||
"move_error": "Could not move emails to the selected folder",
|
||||
"identity_created": "Identity created successfully",
|
||||
"identity_updated": "Identity updated successfully",
|
||||
"identity_deleted": "Identity deleted",
|
||||
"identity_create_failed": "Failed to create identity: {{error}}",
|
||||
"identity_update_failed": "Failed to update identity: {{error}}",
|
||||
"identity_delete_failed": "Failed to delete identity: {{error}}",
|
||||
"identity_unauthorized": "You are not authorized to send from this email address",
|
||||
"identity_not_found": "Identity not found"
|
||||
},
|
||||
"date": {
|
||||
"today": "Today",
|
||||
@@ -264,9 +333,21 @@
|
||||
"title": "Language",
|
||||
"english": "English",
|
||||
"french": "Français",
|
||||
"japanese": "日本語",
|
||||
"spanish": "Español",
|
||||
"italian": "Italiano",
|
||||
"german": "Deutsch",
|
||||
"dutch": "Nederlands",
|
||||
"portuguese": "Português",
|
||||
"select_language": "Select language",
|
||||
"switch_to_english": "Switch to English",
|
||||
"switch_to_french": "Switch to French",
|
||||
"switch_to_japanese": "Switch to Japanese",
|
||||
"switch_to_spanish": "Switch to Spanish",
|
||||
"switch_to_italian": "Switch to Italian",
|
||||
"switch_to_german": "Switch to German",
|
||||
"switch_to_dutch": "Switch to Dutch",
|
||||
"switch_to_portuguese": "Switch to Portuguese",
|
||||
"switching": "Changing language..."
|
||||
},
|
||||
"settings": {
|
||||
@@ -283,6 +364,7 @@
|
||||
"composer": "Composer",
|
||||
"privacy": "Privacy & Security",
|
||||
"account": "Account",
|
||||
"identities": "Identities",
|
||||
"advanced": "Advanced"
|
||||
},
|
||||
"appearance": {
|
||||
@@ -468,6 +550,23 @@
|
||||
"value": "{{time}}"
|
||||
}
|
||||
},
|
||||
"identities": {
|
||||
"title": "Sending Identities",
|
||||
"description": "Manage email addresses you can send from",
|
||||
"identities_count": {
|
||||
"label": "Your Identities",
|
||||
"description": "Email addresses configured for sending",
|
||||
"count_zero": "No identities",
|
||||
"count_one": "1 identity",
|
||||
"count_other": "{{count}} identities"
|
||||
},
|
||||
"manage": "Manage Identities",
|
||||
"sub_addressing": {
|
||||
"label": "Sub-Addressing",
|
||||
"description": "Use tags like user+tag@domain.com to organize incoming mail",
|
||||
"learn_more": "Learn More"
|
||||
}
|
||||
},
|
||||
"advanced": {
|
||||
"title": "Advanced",
|
||||
"description": "Advanced options and developer settings",
|
||||
@@ -525,6 +624,8 @@
|
||||
"move_to": "Move to...",
|
||||
"archive": "Archive",
|
||||
"delete": "Delete",
|
||||
"mark_as_spam": "Report spam",
|
||||
"not_spam": "Not spam",
|
||||
"color_tag": "Color Tag",
|
||||
"remove_color": "Remove Color",
|
||||
"items_selected": "{{count}} emails selected"
|
||||
@@ -552,7 +653,8 @@
|
||||
"archive": "Archive",
|
||||
"delete": "Delete",
|
||||
"mark_unread": "Mark as unread",
|
||||
"mark_read": "Mark as read"
|
||||
"mark_read": "Mark as read",
|
||||
"toggle_spam": "Report spam / Not spam"
|
||||
},
|
||||
"global": {
|
||||
"compose": "Compose new email",
|
||||
@@ -577,5 +679,68 @@
|
||||
"delete": "Delete conversation",
|
||||
"star": "Star conversation",
|
||||
"unstar": "Unstar conversation"
|
||||
},
|
||||
"identities": {
|
||||
"modal_title": "Manage Sending Identities",
|
||||
"create_new": "Create New Identity",
|
||||
"edit_identity": "Edit Identity",
|
||||
"delete_confirm": "Delete this identity? This cannot be undone.",
|
||||
"cannot_delete": "This identity cannot be deleted",
|
||||
"primary_identity": "Primary",
|
||||
"no_identities": "No identities found",
|
||||
"display": {
|
||||
"reply_to": "Reply-To:",
|
||||
"bcc": "BCC:",
|
||||
"signature": "Signature:",
|
||||
"preview": "Preview:"
|
||||
},
|
||||
"validation_errors": {
|
||||
"invalid_emails": "Invalid emails: {emails}",
|
||||
"unknown_error": "Unknown error"
|
||||
},
|
||||
"form": {
|
||||
"name_label": "Display Name",
|
||||
"name_placeholder": "e.g., Work Email, Personal",
|
||||
"name_required": "Name is required",
|
||||
"email_label": "Email Address",
|
||||
"email_placeholder": "your.email@example.com",
|
||||
"email_required": "Email is required",
|
||||
"email_invalid": "Please enter a valid email address",
|
||||
"email_immutable": "Email address cannot be changed after creation",
|
||||
"reply_to_label": "Reply-To (optional)",
|
||||
"reply_to_placeholder": "different@email.com",
|
||||
"bcc_label": "Auto BCC (optional)",
|
||||
"bcc_placeholder": "archive@email.com",
|
||||
"text_signature_label": "Text Signature",
|
||||
"html_signature_label": "HTML Signature",
|
||||
"save": "Save Identity",
|
||||
"cancel": "Cancel",
|
||||
"creating": "Creating...",
|
||||
"updating": "Updating..."
|
||||
},
|
||||
"sub_address": {
|
||||
"button_tooltip": "Use sub-address",
|
||||
"popover_title": "Add Sub-Address Tag",
|
||||
"tag_input_placeholder": "Enter tag (e.g., shopping)",
|
||||
"preview_label": "Preview:",
|
||||
"recent_tags": "Recent Tags",
|
||||
"suggested_tags": "Suggested",
|
||||
"use_address": "Use This Address",
|
||||
"invalid_tag": "Tag must be alphanumeric and dashes only",
|
||||
"tag_too_long": "Tag must be 30 characters or less",
|
||||
"help_text": "Emails sent to user+tag@domain.com will arrive in your inbox",
|
||||
"validation": {
|
||||
"empty": "Tag cannot be empty",
|
||||
"too_long": "Tag must be {max} characters or less",
|
||||
"invalid_chars": "Tag must contain only letters, numbers, and dashes"
|
||||
}
|
||||
},
|
||||
"badge": {
|
||||
"sent_via": "via",
|
||||
"sub_address_tag": "Sent using sub-address: {tag}",
|
||||
"identity_name": "Sent using identity: {name}",
|
||||
"identity_short": "via {name}",
|
||||
"subaddress_tag": "+{tag}"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user