From 36172160ac8bd7b0b96a4efd1a7d442e4c584c02 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 12:08:38 +0000 Subject: [PATCH 1/4] Initial plan From 5a025576c42107ac01caa3d8fcf9ffe5b35223f8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 14 Mar 2026 12:30:27 +0000 Subject: [PATCH 2/4] feat(ui): internationalize profile, subscription, integrations templates and user menu JS - Add 155 new translation keys to en.json (common, nav, integrations, profile, subscription sections) - Add window.__i18n script block to base.html for user menu strings - Replace all hardcoded English strings in common.js with window.__i18n lookups using safe fallback pattern - Internationalize profile.html (page title, headings, labels, hints, placeholders, theme options) - Internationalize subscription.html (page title, plan cards, usage stats, plan actions, badges) - Internationalize integrations_dashboard.html (header, quota bars, modal, all form fields, action buttons, webhook section, delete modal) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- frontend/static/js/common.js | 36 +-- frontend/templates/base.html | 17 ++ .../templates/integrations_dashboard.html | 241 +++++++++--------- frontend/templates/profile.html | 67 +++-- frontend/templates/subscription.html | 79 +++--- frontend/translations/en.json | 157 ++++++++++++ 6 files changed, 380 insertions(+), 217 deletions(-) diff --git a/frontend/static/js/common.js b/frontend/static/js/common.js index b09beb42..78df364a 100644 --- a/frontend/static/js/common.js +++ b/frontend/static/js/common.js @@ -165,11 +165,11 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { 'flex items-center gap-2 px-2 py-1 rounded-md text-gray-700 hover:text-gray-900 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-blue-500'; btn.setAttribute('aria-haspopup', 'true'); btn.setAttribute('aria-expanded', 'false'); - btn.setAttribute('aria-label', `Account menu for ${displayName}`); + btn.setAttribute('aria-label', `${(window.__i18n.accountMenuFor || 'Account menu for {name}').replace('{name}', displayName)}`); const avatar = document.createElement('img'); avatar.src = data.picture; - avatar.alt = 'Avatar'; + avatar.alt = window.__i18n.avatar || 'Avatar'; avatar.className = 'w-8 h-8 rounded-full'; const nameSpan = document.createElement('span'); @@ -189,7 +189,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { menu.className = 'absolute right-0 mt-2 w-52 bg-white rounded-md shadow-lg ring-1 ring-black ring-opacity-5 z-50 hidden'; menu.setAttribute('role', 'menu'); - menu.setAttribute('aria-label', 'Account menu'); + menu.setAttribute('aria-label', window.__i18n.accountMenu || 'Account menu'); // User info header const header = document.createElement('div'); @@ -207,16 +207,16 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { const linksDiv = document.createElement('div'); linksDiv.className = 'py-1'; linksDiv.appendChild( - _makeMenuLink('/profile', 'fas fa-user-circle text-blue-400', 'Profile Settings', 'text-gray-700') + _makeMenuLink('/profile', 'fas fa-user-circle text-blue-400', window.__i18n.profileSettings || 'Profile Settings', 'text-gray-700') ); linksDiv.appendChild( - _makeMenuLink('/subscription', 'fas fa-layer-group text-indigo-400', 'My Subscription', 'text-gray-700') + _makeMenuLink('/subscription', 'fas fa-layer-group text-indigo-400', window.__i18n.mySubscription || 'My Subscription', 'text-gray-700') ); linksDiv.appendChild( - _makeMenuLink('/api-tokens', 'fas fa-key text-yellow-500', 'API Tokens', 'text-gray-700') + _makeMenuLink('/api-tokens', 'fas fa-key text-yellow-500', window.__i18n.apiTokens || 'API Tokens', 'text-gray-700') ); linksDiv.appendChild( - _makeMenuLink('/shared-links', 'fas fa-share-alt text-blue-400', 'Shared Links', 'text-gray-700') + _makeMenuLink('/shared-links', 'fas fa-share-alt text-blue-400', window.__i18n.sharedLinks || 'Shared Links', 'text-gray-700') ); // Divider + Sign Out @@ -225,7 +225,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { const signOutDiv = document.createElement('div'); signOutDiv.className = 'py-1'; signOutDiv.appendChild( - _makeMenuLink('/logout', 'fas fa-sign-out-alt text-red-400', 'Sign Out', 'text-red-600') + _makeMenuLink('/logout', 'fas fa-sign-out-alt text-red-400', window.__i18n.signOut || 'Sign Out', 'text-red-600') ); menu.appendChild(header); @@ -259,7 +259,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { userRow.className = 'flex items-center gap-3 px-3 py-3'; const mAvatar = document.createElement('img'); mAvatar.src = data.picture; - mAvatar.alt = 'Avatar'; + mAvatar.alt = window.__i18n.avatar || 'Avatar'; mAvatar.className = 'w-8 h-8 rounded-full flex-shrink-0'; const mUserInfo = document.createElement('div'); mUserInfo.className = 'min-w-0'; @@ -284,7 +284,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { profileIcon.className = 'fas fa-user-circle mr-2 text-blue-400'; profileIcon.setAttribute('aria-hidden', 'true'); profileLink.appendChild(profileIcon); - profileLink.appendChild(document.createTextNode('Profile Settings')); + profileLink.appendChild(document.createTextNode(window.__i18n.profileSettings || 'Profile Settings')); mobileAuthSection.appendChild(profileLink); // Subscription link @@ -296,7 +296,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { subIcon.className = 'fas fa-layer-group mr-2 text-indigo-400'; subIcon.setAttribute('aria-hidden', 'true'); subLink.appendChild(subIcon); - subLink.appendChild(document.createTextNode('My Subscription')); + subLink.appendChild(document.createTextNode(window.__i18n.mySubscription || 'My Subscription')); mobileAuthSection.appendChild(subLink); // API Tokens link @@ -308,7 +308,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { tokensIcon.className = 'fas fa-key mr-2 text-yellow-500'; tokensIcon.setAttribute('aria-hidden', 'true'); tokensLink.appendChild(tokensIcon); - tokensLink.appendChild(document.createTextNode('API Tokens')); + tokensLink.appendChild(document.createTextNode(window.__i18n.apiTokens || 'API Tokens')); mobileAuthSection.appendChild(tokensLink); // Shared Links link @@ -320,7 +320,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { sharedLinksIcon.className = 'fas fa-share-alt mr-2 text-blue-400'; sharedLinksIcon.setAttribute('aria-hidden', 'true'); sharedLinksLink.appendChild(sharedLinksIcon); - sharedLinksLink.appendChild(document.createTextNode('Shared Links')); + sharedLinksLink.appendChild(document.createTextNode(window.__i18n.sharedLinks || 'Shared Links')); mobileAuthSection.appendChild(sharedLinksLink); // Logout link @@ -332,7 +332,7 @@ function _makeMenuLink(href, iconClass, label, extraClasses = '') { logoutIcon.className = 'fas fa-sign-out-alt mr-2'; logoutIcon.setAttribute('aria-hidden', 'true'); logoutLink.appendChild(logoutIcon); - logoutLink.appendChild(document.createTextNode('Sign Out')); + logoutLink.appendChild(document.createTextNode(window.__i18n.signOut || 'Sign Out')); mobileAuthSection.appendChild(logoutLink); } } else { @@ -367,7 +367,7 @@ function _renderLoggedOutAuth(authSection, mobileAuthSection) { loginLink.href = '/login'; loginLink.className = 'px-3 py-1.5 rounded-md text-sm font-medium text-gray-700 hover:text-gray-900 hover:bg-gray-100 border border-gray-300'; - loginLink.textContent = 'Log In'; + loginLink.textContent = window.__i18n.logIn || 'Log In'; row.appendChild(loginLink); if (multiUser) { @@ -375,7 +375,7 @@ function _renderLoggedOutAuth(authSection, mobileAuthSection) { startLink.href = startHref; startLink.className = 'px-3 py-1.5 rounded-md text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500'; - startLink.textContent = allowSignup ? 'Sign Up' : 'Get Started'; + startLink.textContent = allowSignup ? (window.__i18n.signUp || 'Sign Up') : (window.__i18n.getStarted || 'Get Started'); row.appendChild(startLink); } @@ -393,7 +393,7 @@ function _renderLoggedOutAuth(authSection, mobileAuthSection) { loginIcon.className = 'fas fa-sign-in-alt mr-2'; loginIcon.setAttribute('aria-hidden', 'true'); loginLink.appendChild(loginIcon); - loginLink.appendChild(document.createTextNode('Log In')); + loginLink.appendChild(document.createTextNode(window.__i18n.logIn || 'Log In')); mobileAuthSection.appendChild(loginLink); if (multiUser) { @@ -405,7 +405,7 @@ function _renderLoggedOutAuth(authSection, mobileAuthSection) { startIcon.className = 'fas fa-arrow-right mr-2'; startIcon.setAttribute('aria-hidden', 'true'); startLink.appendChild(startIcon); - startLink.appendChild(document.createTextNode(allowSignup ? 'Sign Up' : 'Get Started')); + startLink.appendChild(document.createTextNode(allowSignup ? (window.__i18n.signUp || 'Sign Up') : (window.__i18n.getStarted || 'Get Started'))); mobileAuthSection.appendChild(startLink); } } diff --git a/frontend/templates/base.html b/frontend/templates/base.html index 9230423b..f38263ef 100644 --- a/frontend/templates/base.html +++ b/frontend/templates/base.html @@ -548,6 +548,23 @@ })(); + + + diff --git a/frontend/templates/integrations_dashboard.html b/frontend/templates/integrations_dashboard.html index a710b98c..0fecd6d0 100644 --- a/frontend/templates/integrations_dashboard.html +++ b/frontend/templates/integrations_dashboard.html @@ -1,5 +1,5 @@ {% extends "base.html" %} -{% block title %}Integrations – DocuElevate{% endblock %} +{% block title %}{{ _("integrations.page_title") }} – DocuElevate{% endblock %} {% block content %}
- Manage your ingestion sources and storage destinations in one place. + {{ _("integrations.subtitle") }}
- Mailbox Sources: + {{ _("integrations.sources_quota_label") }} / - / unlimited + {{ _("integrations.quota_unlimited") }} - (not available) + {{ _("integrations.quota_not_available") }}
- Plan: + {{ _("integrations.plan_label") }}
- Storage Destinations: + {{ _("integrations.destinations_quota_label") }} / - / unlimited + {{ _("integrations.quota_unlimited") }}
- Plan: + {{ _("integrations.plan_label") }}
Loading integrations…
+{{ _("integrations.loading") }}
- Add your first integration to connect ingestion sources (like IMAP) and storage destinations (like S3, Dropbox, or Google Drive). + {{ _("integrations.no_integrations_body") }}