Skip to content

Commit bda30f5

Browse files
committed
fix: extract keys for new header dropdown + orgs pages
1 parent f43e01b commit bda30f5

4 files changed

Lines changed: 73 additions & 27 deletions

File tree

app/components/HeaderOrgsDropdown.vue

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const props = defineProps<{
33
username: string
44
}>()
55
6+
const { t } = useI18n()
67
const { listUserOrgs } = useConnector()
78
89
const isOpen = ref(false)
@@ -61,7 +62,7 @@ function handleKeydown(event: KeyboardEvent) {
6162
:to="`/~${username}/orgs`"
6263
class="link-subtle font-mono text-sm inline-flex items-center gap-1"
6364
>
64-
orgs
65+
{{ t('header.orgs') }}
6566
<span
6667
class="i-carbon-chevron-down w-3 h-3 transition-transform duration-200"
6768
:class="{ 'rotate-180': isOpen }"
@@ -78,15 +79,17 @@ function handleKeydown(event: KeyboardEvent) {
7879
<div v-if="isOpen" class="absolute right-0 top-full pt-2 w-56 z-50">
7980
<div class="bg-bg-elevated border border-border rounded-lg shadow-lg overflow-hidden">
8081
<div class="px-3 py-2 border-b border-border">
81-
<span class="font-mono text-xs text-fg-subtle">Your Organizations</span>
82+
<span class="font-mono text-xs text-fg-subtle">{{
83+
t('header.orgs_dropdown.title')
84+
}}</span>
8285
</div>
8386

8487
<div v-if="isLoading" class="px-3 py-4 text-center">
85-
<span class="text-fg-muted text-sm">Loading…</span>
88+
<span class="text-fg-muted text-sm">{{ t('header.orgs_dropdown.loading') }}</span>
8689
</div>
8790

8891
<div v-else-if="error" class="px-3 py-4 text-center">
89-
<span class="text-fg-muted text-sm">{{ error }}</span>
92+
<span class="text-fg-muted text-sm">{{ t('header.orgs_dropdown.error') }}</span>
9093
</div>
9194

9295
<ul v-else-if="orgs.length > 0" class="py-1 max-h-80 overflow-y-auto">
@@ -101,15 +104,15 @@ function handleKeydown(event: KeyboardEvent) {
101104
</ul>
102105

103106
<div v-else class="px-3 py-4 text-center">
104-
<span class="text-fg-muted text-sm">No organizations found</span>
107+
<span class="text-fg-muted text-sm">{{ t('header.orgs_dropdown.empty') }}</span>
105108
</div>
106109

107110
<div class="px-3 py-2 border-t border-border">
108111
<NuxtLink
109112
:to="`/~${username}/orgs`"
110113
class="link-subtle font-mono text-xs inline-flex items-center gap-1"
111114
>
112-
View all
115+
{{ t('header.orgs_dropdown.view_all') }}
113116
<span class="i-carbon-arrow-right w-3 h-3" aria-hidden="true" />
114117
</NuxtLink>
115118
</div>

app/components/HeaderPackagesDropdown.vue

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ const props = defineProps<{
33
username: string
44
}>()
55
6+
const { t } = useI18n()
67
const { listUserPackages } = useConnector()
78
89
const isOpen = ref(false)
@@ -61,7 +62,7 @@ function handleKeydown(event: KeyboardEvent) {
6162
:to="`/~${username}`"
6263
class="link-subtle font-mono text-sm inline-flex items-center gap-1"
6364
>
64-
packages
65+
{{ t('header.packages') }}
6566
<span
6667
class="i-carbon-chevron-down w-3 h-3 transition-transform duration-200"
6768
:class="{ 'rotate-180': isOpen }"
@@ -78,15 +79,17 @@ function handleKeydown(event: KeyboardEvent) {
7879
<div v-if="isOpen" class="absolute right-0 top-full pt-2 w-64 z-50">
7980
<div class="bg-bg-elevated border border-border rounded-lg shadow-lg overflow-hidden">
8081
<div class="px-3 py-2 border-b border-border">
81-
<span class="font-mono text-xs text-fg-subtle">Your Packages</span>
82+
<span class="font-mono text-xs text-fg-subtle">{{
83+
t('header.packages_dropdown.title')
84+
}}</span>
8285
</div>
8386

8487
<div v-if="isLoading" class="px-3 py-4 text-center">
85-
<span class="text-fg-muted text-sm">Loading…</span>
88+
<span class="text-fg-muted text-sm">{{ t('header.packages_dropdown.loading') }}</span>
8689
</div>
8790

8891
<div v-else-if="error" class="px-3 py-4 text-center">
89-
<span class="text-fg-muted text-sm">{{ error }}</span>
92+
<span class="text-fg-muted text-sm">{{ t('header.packages_dropdown.error') }}</span>
9093
</div>
9194

9295
<ul v-else-if="packages.length > 0" class="py-1 max-h-80 overflow-y-auto">
@@ -101,15 +104,15 @@ function handleKeydown(event: KeyboardEvent) {
101104
</ul>
102105

103106
<div v-else class="px-3 py-4 text-center">
104-
<span class="text-fg-muted text-sm">No packages found</span>
107+
<span class="text-fg-muted text-sm">{{ t('header.packages_dropdown.empty') }}</span>
105108
</div>
106109

107110
<div class="px-3 py-2 border-t border-border">
108111
<NuxtLink
109112
:to="`/~${username}`"
110113
class="link-subtle font-mono text-xs inline-flex items-center gap-1"
111114
>
112-
View all
115+
{{ t('header.packages_dropdown.view_all') }}
113116
<span class="i-carbon-arrow-right w-3 h-3" aria-hidden="true" />
114117
</NuxtLink>
115118
</div>

app/pages/~[username]/orgs.vue

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
<script setup lang="ts">
2+
const { t } = useI18n()
23
const route = useRoute('~username-orgs')
34
45
const username = computed(() => route.params.username)
@@ -119,7 +120,7 @@ useSeoMeta({
119120
</div>
120121
<div>
121122
<h1 class="font-mono text-2xl sm:text-3xl font-medium">@{{ username }}</h1>
122-
<p class="text-fg-muted text-sm mt-1">Organizations</p>
123+
<p class="text-fg-muted text-sm mt-1">{{ t('user.orgs_page.title') }}</p>
123124
</div>
124125
</div>
125126

@@ -130,48 +131,51 @@ useSeoMeta({
130131
class="link-subtle font-mono text-sm inline-flex items-center gap-1.5"
131132
>
132133
<span class="i-carbon-arrow-left w-4 h-4" aria-hidden="true" />
133-
Back to profile
134+
{{ t('user.orgs_page.back_to_profile') }}
134135
</NuxtLink>
135136
</nav>
136137
</header>
137138

138139
<!-- Not connected state -->
139140
<ClientOnly>
140141
<div v-if="!isConnected" class="py-12 text-center">
141-
<p class="text-fg-muted mb-4">Connect the local CLI to view your organizations.</p>
142+
<p class="text-fg-muted mb-4">{{ t('user.orgs_page.connect_required') }}</p>
142143
<p class="text-fg-subtle text-sm">
143-
Run <code class="font-mono bg-bg-subtle px-1.5 py-0.5 rounded">npx @npmx.dev/cli</code> to
144-
get started.
144+
{{ t('user.orgs_page.connect_hint_prefix') }}
145+
<code class="font-mono bg-bg-subtle px-1.5 py-0.5 rounded">npx @npmx.dev/cli</code>
146+
{{ t('user.orgs_page.connect_hint_suffix') }}
145147
</p>
146148
</div>
147149

148150
<!-- Not own profile state -->
149151
<div v-else-if="!isOwnProfile" class="py-12 text-center">
150-
<p class="text-fg-muted">You can only view your own organizations.</p>
151-
<NuxtLink :to="`/~${npmUser}/orgs`" class="btn mt-4">View your organizations</NuxtLink>
152+
<p class="text-fg-muted">{{ t('user.orgs_page.own_orgs_only') }}</p>
153+
<NuxtLink :to="`/~${npmUser}/orgs`" class="btn mt-4">{{
154+
t('user.orgs_page.view_your_orgs')
155+
}}</NuxtLink>
152156
</div>
153157

154158
<!-- Loading state -->
155-
<LoadingSpinner v-else-if="isLoading" text="Loading organizations..." />
159+
<LoadingSpinner v-else-if="isLoading" :text="t('user.orgs_page.loading')" />
156160

157161
<!-- Error state -->
158162
<div v-else-if="error" role="alert" class="py-12 text-center">
159163
<p class="text-fg-muted mb-4">{{ error }}</p>
160-
<button type="button" class="btn" @click="loadOrgs">Try again</button>
164+
<button type="button" class="btn" @click="loadOrgs">{{ t('common.try_again') }}</button>
161165
</div>
162166

163167
<!-- Empty state -->
164168
<div v-else-if="orgs.length === 0" class="py-12 text-center">
165-
<p class="text-fg-muted">No organizations found.</p>
169+
<p class="text-fg-muted">{{ t('user.orgs_page.empty') }}</p>
166170
<p class="text-fg-subtle text-sm mt-2">
167-
Organizations are detected from your scoped packages.
171+
{{ t('user.orgs_page.empty_hint') }}
168172
</p>
169173
</div>
170174

171175
<!-- Orgs list -->
172-
<section v-else aria-label="Organizations">
176+
<section v-else :aria-label="t('user.orgs_page.title')">
173177
<h2 class="text-xs text-fg-subtle uppercase tracking-wider mb-4">
174-
{{ orgs.length }} Organization{{ orgs.length === 1 ? '' : 's' }}
178+
{{ t('user.orgs_page.count', { count: orgs.length }, orgs.length) }}
175179
</h2>
176180

177181
<ul class="grid gap-4 sm:grid-cols-2 lg:grid-cols-3">
@@ -212,7 +216,13 @@ useSeoMeta({
212216
<div class="flex items-center gap-1.5">
213217
<span class="i-carbon-cube w-4 h-4" aria-hidden="true" />
214218
<span v-if="org.packageCount !== null">
215-
{{ org.packageCount }} package{{ org.packageCount === 1 ? '' : 's' }}
219+
{{
220+
t(
221+
'user.orgs_page.packages_count',
222+
{ count: org.packageCount },
223+
org.packageCount,
224+
)
225+
}}
216226
</span>
217227
<span v-else-if="org.isLoadingDetails" class="skeleton inline-block h-4 w-20" />
218228
<span v-else class="text-fg-subtle">—</span>

i18n/locales/en.json

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,20 @@
377377
"failed_to_load": "Failed to load user packages",
378378
"no_match": "No packages match \"{query}\"",
379379
"filter_placeholder": "Filter {count} packages..."
380+
},
381+
"orgs_page": {
382+
"title": "Organizations",
383+
"back_to_profile": "Back to profile",
384+
"connect_required": "Connect the local CLI to view your organizations.",
385+
"connect_hint_prefix": "Run",
386+
"connect_hint_suffix": "to get started.",
387+
"own_orgs_only": "You can only view your own organizations.",
388+
"view_your_orgs": "View your organizations",
389+
"loading": "Loading organizations...",
390+
"empty": "No organizations found.",
391+
"empty_hint": "Organizations are detected from your scoped packages.",
392+
"count": "{count} Organization | {count} Organizations",
393+
"packages_count": "{count} package | {count} packages"
380394
}
381395
},
382396
"claim": {
@@ -446,6 +460,22 @@
446460
},
447461
"header": {
448462
"home": "npmx home",
449-
"github": "GitHub"
463+
"github": "GitHub",
464+
"packages": "packages",
465+
"packages_dropdown": {
466+
"title": "Your Packages",
467+
"loading": "Loading...",
468+
"error": "Failed to load packages",
469+
"empty": "No packages found",
470+
"view_all": "View all"
471+
},
472+
"orgs": "orgs",
473+
"orgs_dropdown": {
474+
"title": "Your Organizations",
475+
"loading": "Loading...",
476+
"error": "Failed to load organizations",
477+
"empty": "No organizations found",
478+
"view_all": "View all"
479+
}
450480
}
451481
}

0 commit comments

Comments
 (0)