Skip to content

Commit 9f63fac

Browse files
feat: add i18n for the index page
1 parent bf55ec9 commit 9f63fac

8 files changed

Lines changed: 863 additions & 130 deletions

File tree

app/components/AppFooter.vue

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,35 +85,35 @@ onMounted(() => {
8585
>
8686
<div class="container py-2 sm:py-6 flex flex-col gap-1 sm:gap-3 text-fg-subtle text-sm">
8787
<div class="flex flex-row items-center justify-between gap-2 sm:gap-4">
88-
<p class="font-mono m-0 hidden sm:block">a better browser for the npm registry</p>
88+
<p class="font-mono m-0 hidden sm:block">{{ $t('tagline') }}</p>
8989
<!-- On mobile, show disclaimer here instead of tagline -->
90-
<p class="text-xs text-fg-muted m-0 sm:hidden">not affiliated with npm, Inc.</p>
90+
<p class="text-xs text-fg-muted m-0 sm:hidden">{{ $t('non_affiliation_disclaimer') }}</p>
9191
<div class="flex items-center gap-4 sm:gap-6">
9292
<a
9393
href="https://repo.npmx.dev"
9494
rel="noopener noreferrer"
9595
class="link-subtle font-mono text-xs min-h-11 min-w- flex items-center"
9696
>
97-
source
97+
{{ $t('footer.source') }}
9898
</a>
9999
<a
100100
href="https://social.npmx.dev"
101101
rel="noopener noreferrer"
102102
class="link-subtle font-mono text-xs min-h-11 min-w-11 flex items-center"
103103
>
104-
social
104+
{{ $t('footer.social') }}
105105
</a>
106106
<a
107107
href="https://chat.npmx.dev"
108108
rel="noopener noreferrer"
109109
class="link-subtle font-mono text-xs min-h-11 min-w-11 flex items-center"
110110
>
111-
chat
111+
{{ $t('footer.chat') }}
112112
</a>
113113
</div>
114114
</div>
115115
<p class="text-xs text-fg-muted text-center sm:text-left m-0 hidden sm:block">
116-
npm is a registered trademark of npm, Inc. This site is not affiliated with npm, Inc.
116+
{{ $t('trademark_disclaimer') }}
117117
</p>
118118
</div>
119119
</footer>

app/components/AppHeader.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ withDefaults(
3232
class="link-subtle font-mono text-sm inline-flex items-center gap-2"
3333
aria-keyshortcuts="/"
3434
>
35-
search
35+
{{ $t('nav.search') }}
3636
<kbd
3737
class="hidden sm:inline-flex items-center justify-center w-5 h-5 text-xs bg-bg-muted border border-border rounded"
3838
aria-hidden="true"

app/components/SettingsMenu.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ onKeyStroke(',', e => {
4646
class="link-subtle font-mono text-sm inline-flex items-center justify-center gap-2 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 rounded"
4747
:aria-expanded="isOpen"
4848
aria-haspopup="menu"
49-
aria-label="Settings"
49+
:aria-label="$t('nav.settings')"
5050
aria-keyshortcuts=","
5151
@click="toggle"
5252
>
5353
<span class="i-carbon-settings w-4 h-4 sm:hidden" aria-hidden="true" />
54-
<span class="hidden sm:inline">settings</span>
54+
<span class="hidden sm:inline">{{ $t('nav.settings') }}</span>
5555
<kbd
5656
class="hidden sm:inline-flex items-center justify-center w-5 h-5 text-xs bg-bg-muted border border-border rounded"
5757
aria-hidden="true"
@@ -76,7 +76,7 @@ onKeyStroke(',', e => {
7676
class="absolute right-0 top-full mt-2 w-64 bg-bg-elevated border border-border rounded-lg shadow-lg z-50 overflow-hidden"
7777
>
7878
<div class="px-3 py-2 border-b border-border">
79-
<h2 class="text-xs text-fg-subtle uppercase tracking-wider">Settings</h2>
79+
<h2 class="text-xs text-fg-subtle uppercase tracking-wider">{{ $t('nav.settings') }}</h2>
8080
</div>
8181

8282
<div class="p-2 space-y-1">
@@ -88,7 +88,7 @@ onKeyStroke(',', e => {
8888
:aria-checked="settings.relativeDates"
8989
@click="settings.relativeDates = !settings.relativeDates"
9090
>
91-
<span class="text-sm text-fg select-none">Relative dates</span>
91+
<span class="text-sm text-fg select-none">{{ $t('settings.relative_dates') }}</span>
9292
<span
9393
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none"
9494
:class="settings.relativeDates ? 'bg-fg' : 'bg-bg-subtle'"
@@ -111,7 +111,7 @@ onKeyStroke(',', e => {
111111
:aria-checked="settings.includeTypesInInstall"
112112
@click="settings.includeTypesInInstall = !settings.includeTypesInInstall"
113113
>
114-
<span class="text-sm text-fg select-none">Include @types in install</span>
114+
<span class="text-sm text-fg select-none">{{ $t('settings.include_types') }}</span>
115115
<span
116116
class="relative inline-flex h-5 w-9 shrink-0 items-center rounded-full border-2 border-transparent transition-[background-color] duration-200 ease-in-out motion-reduce:transition-none"
117117
:class="settings.includeTypesInInstall ? 'bg-fg' : 'bg-bg-subtle'"

app/pages/index.vue

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ function handleSearch() {
1010
})
1111
}
1212
13+
const { t } = useI18n()
1314
useSeoMeta({
14-
title: 'npmx - Package Browser for the npm Registry',
15-
description:
16-
'A better browser for the npm registry. Search, browse, and explore packages with a modern interface.',
15+
title: t('seo.home.title'),
16+
description: t('seo.home.description'),
1717
})
1818
1919
defineOgImageComponent('Default')
@@ -34,7 +34,7 @@ defineOgImageComponent('Default')
3434
class="text-fg-muted text-lg sm:text-xl max-w-md mb-12 animate-slide-up animate-fill-both"
3535
style="animation-delay: 0.1s"
3636
>
37-
a better browser for the npm registry
37+
{{ $t('tagline') }}
3838
</p>
3939

4040
<!-- Search form with micro-interactions -->
@@ -43,7 +43,9 @@ defineOgImageComponent('Default')
4343
style="animation-delay: 0.2s"
4444
>
4545
<form role="search" class="relative" @submit.prevent="handleSearch">
46-
<label for="home-search" class="sr-only">Search npm packages</label>
46+
<label for="home-search" class="sr-only">
47+
{{ $t('search.label') }}
48+
</label>
4749

4850
<!-- Search input with glow effect on focus -->
4951
<div class="relative group" :class="{ 'is-focused': isSearchFocused }">
@@ -64,7 +66,7 @@ defineOgImageComponent('Default')
6466
v-model="searchQuery"
6567
type="search"
6668
name="q"
67-
placeholder="search packages..."
69+
:placeholder="$t('search.placeholder')"
6870
autocomplete="off"
6971
class="w-full bg-bg-subtle border border-border rounded-lg pl-8 pr-24 py-4 font-mono text-base text-fg placeholder:text-fg-subtle transition-all duration-300 focus:(border-border-hover outline-none)"
7072
@input="handleSearch"
@@ -76,7 +78,7 @@ defineOgImageComponent('Default')
7678
type="submit"
7779
class="absolute right-2 px-4 py-2 font-mono text-sm text-bg bg-fg rounded-md transition-all duration-200 hover:bg-fg/90 active:scale-95"
7880
>
79-
search
81+
{{ $t('search.button') }}
8082
</button>
8183
</div>
8284
</div>
@@ -86,7 +88,7 @@ defineOgImageComponent('Default')
8688

8789
<!-- Popular packages -->
8890
<nav
89-
aria-label="Popular packages"
91+
:aria-label="$t('nav.popular_packages')"
9092
class="pb-20 text-center animate-fade-in animate-fill-both"
9193
style="animation-delay: 0.3s"
9294
>

i18n/locales/en.json

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
{
2+
"seo": {
3+
"home": {
4+
"title": "npmx - Package Browser for the npm Registry",
5+
"description": "A better browser for the npm registry. Search, browse, and explore packages with a modern interface."
6+
}
7+
},
8+
"tagline": "a better browser for the npm registry",
9+
"non_affiliation_disclaimer": "not affiliated with npm, Inc.",
10+
"trademark_disclaimer": "npm is a registered trademark of npm, Inc. This site is not affiliated with npm, Inc.",
11+
"footer": {
12+
"source": "source",
13+
"social": "social",
14+
"chat": "chat"
15+
},
16+
"search": {
17+
"label": "Search npm packages",
18+
"placeholder": "search packages...",
19+
"button": "search"
20+
},
21+
"nav": {
22+
"popular_packages": "Popular packages",
23+
"search": "search",
24+
"settings": "settings"
25+
},
26+
"settings": {
27+
"relative_dates": "Relative dates",
28+
"include_types": "Include {'@'}types in install"
29+
}
30+
}

nuxt.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ export default defineNuxtConfig({
1616
'@nuxt/test-utils',
1717
'@vite-pwa/nuxt',
1818
'@vueuse/nuxt',
19+
'@nuxtjs/i18n',
1920
],
2021

2122
devtools: { enabled: true },
@@ -131,4 +132,10 @@ export default defineNuxtConfig({
131132
],
132133
},
133134
},
135+
136+
i18n: {
137+
defaultLocale: 'en',
138+
strategy: 'no_prefix',
139+
locales: [{ code: 'en', name: 'English', file: 'en.json' }],
140+
},
134141
})

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
"@nuxt/fonts": "^0.13.0",
3333
"@nuxt/scripts": "^0.13.2",
3434
"@nuxtjs/html-validator": "^2.1.0",
35+
"@nuxtjs/i18n": "10.2.1",
3536
"@shikijs/langs": "^3.21.0",
3637
"@shikijs/themes": "^3.21.0",
3738
"@vueuse/core": "^14.1.0",

0 commit comments

Comments
 (0)