From 535e036fa1e8b55fc17a5f21d9aca9e408c6af1f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 19:52:05 +0000 Subject: [PATCH 1/4] Initial plan From e066cf35e7d8106211e48fa4e24238beb590f5de Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 27 Aug 2026 20:03:15 +0000 Subject: [PATCH 2/4] feat: add i18n support with svelte-i18n (Spanish/English) Co-authored-by: foxkdev <22413328+foxkdev@users.noreply.github.com> --- .gitignore | 1 + package.json | 3 +- src/lib/components/AppNavbar.svelte | 21 ++-- src/lib/components/AppSidebar.svelte | 97 ++++++++--------- src/lib/components/Footer.svelte | 9 +- src/lib/i18n/index.ts | 30 ++++++ src/lib/i18n/locales/en.json | 147 +++++++++++++++++++++++++ src/lib/i18n/locales/es.json | 147 +++++++++++++++++++++++++ src/routes/+layout.svelte | 3 + src/routes/profile/+page.svelte | 156 +++++++++++++++++---------- 10 files changed, 492 insertions(+), 122 deletions(-) create mode 100644 src/lib/i18n/index.ts create mode 100644 src/lib/i18n/locales/en.json create mode 100644 src/lib/i18n/locales/es.json diff --git a/.gitignore b/.gitignore index eb52943..bae85c5 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ node_modules build .vite bun.lockb +package-lock.json .DS_Store coverage data/ diff --git a/package.json b/package.json index b2159cb..8c0b5dd 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "@google-cloud/storage": "^8.0.1", "@lucide/svelte": "^1.34.0", "chart.js": "^4.5.1", - "nodemailer": "^9.0.6" + "nodemailer": "^9.0.6", + "svelte-i18n": "^4.0.1" } } diff --git a/src/lib/components/AppNavbar.svelte b/src/lib/components/AppNavbar.svelte index 69eda61..e6e6ac0 100644 --- a/src/lib/components/AppNavbar.svelte +++ b/src/lib/components/AppNavbar.svelte @@ -1,6 +1,7 @@ - Profile - GitOps + {$_('profile.title')} - GitOps
@@ -98,11 +111,11 @@

- Account + {$_('profile.account')}

-

Profile

+

{$_('profile.title')}

- Manage your identity, password and API access from one place. + {$_('profile.subtitle')}

@@ -111,15 +124,15 @@ on:click={toggleDarkMode} class="inline-flex shrink-0 items-center gap-2 rounded-md border border-white/15 bg-white/10 px-4 py-2.5 text-sm font-semibold text-white transition-colors hover:bg-white/15" aria-pressed={themeReady ? darkMode : undefined} - aria-label={darkMode ? 'Disable dark mode' : 'Enable dark mode'} - title={darkMode ? 'Disable dark mode' : 'Enable dark mode'} + aria-label={darkMode ? $_('profile.disableDarkMode') : $_('profile.enableDarkMode')} + title={darkMode ? $_('profile.disableDarkMode') : $_('profile.enableDarkMode')} > {#if darkMode} - Light mode + {$_('profile.lightMode')} {:else} - Dark mode + {$_('profile.darkMode')} {/if}
@@ -128,30 +141,30 @@
-

Username

+

{$_('profile.username')}

{data.user.username}

-

Email

-

{data.user.email || 'Not set'}

+

{$_('profile.email')}

+

{data.user.email || $_('profile.notSet')}

-

Role

+

{$_('profile.role')}

{data.user.role.name}

-

GCP

+

{$_('profile.gcp')}

{#if data.gcpConnected} - Connected + {$_('profile.connected')} {:else} - Not connected + {$_('profile.notConnected')} {/if}

@@ -170,12 +183,12 @@
-

Account information

+

{$_('profile.accountInformation')}

- + - Username + {$_('profile.username')} {data.user.username}
- Role + {$_('profile.role')} {data.user.role.name}
@@ -205,7 +218,7 @@ class="btn-primary inline-flex items-center gap-2 rounded-md px-4 py-2.5 text-sm font-medium" > - Save changes + {$_('profile.saveChanges')}
@@ -213,13 +226,13 @@
-

Password

+

{$_('profile.password')}

{$_('profile.currentPassword')} {$_('profile.newPassword')} {$_('profile.confirmPassword')} - Update password + {$_('profile.updatePassword')}
+
+
+ +
+

{$_('profile.language')}

+

{$_('profile.languageDescription')}

+
+
+ +
+ +
+
+
-

API Keys

-

Create and revoke keys for future API access.

+

{$_('profile.apiKeys')}

+

{$_('profile.apiKeysDescription')}

@@ -279,7 +317,7 @@ class="btn-primary inline-flex shrink-0 items-center gap-2 rounded-md px-4 py-2.5 text-sm font-medium" > - Create + {$_('profile.create')}
@@ -289,7 +327,7 @@ >
-

Copy this token now. It will not be shown again.

+

{$_('profile.copyNow')}

{form.createdKey} @@ -299,15 +337,15 @@ type="button" on:click={copyCreatedKey} class="btn-ghost inline-flex shrink-0 items-center gap-2 rounded-md border border-amber-200 bg-white px-3 py-2 text-xs font-medium text-amber-900 hover:bg-amber-100" - title="Copy API key" - aria-label="Copy API key" + title={$_('profile.copy')} + aria-label={$_('profile.copy')} > {#if copiedCreatedKey} - Copied + {$_('profile.copied')} {:else} - Copy + {$_('profile.copy')} {/if}
@@ -319,7 +357,7 @@
- No API keys created yet. + {$_('profile.noApiKeys')}
{:else} {#each data.apiKeys as key} @@ -329,7 +367,7 @@

{key.name}

- Prefix: {key.keyPrefix} · Created {key.createdAt} · Expires {formatDateTime( + {$_('profile.prefix')}: {key.keyPrefix} · {$_('profile.created')} {key.createdAt} · {$_('profile.expires')} {formatDateTime( key.expiresAt, )}

@@ -338,9 +376,9 @@ ? 'text-rose-700' : 'text-emerald-700'}" > - Status: {getKeyState(key)} + {$_('profile.status')}: {getKeyState(key)} {#if key.revokedAt} - · Revoked {formatDateTime(key.revokedAt)} + · {$_('profile.revoked')} {formatDateTime(key.revokedAt)} {/if}

@@ -354,7 +392,7 @@ class="btn-secondary inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium" > - Regenerate + {$_('profile.regenerate')} @@ -365,14 +403,14 @@ class="btn-danger inline-flex items-center gap-2 rounded-md px-3 py-2 text-sm font-medium" > - Revoke + {$_('profile.revoke')} {:else}
- Actions unavailable for revoked keys. + {$_('profile.revokedActionsUnavailable')}
{/if}
@@ -388,27 +426,27 @@ type="button" class="fixed inset-0 z-40 bg-slate-900/50" on:click={closeCreateApiKeyModal} - aria-label="Close create api key modal" + aria-label={$_('common.close')} >