[READ-ONLY] a fast, modern browser for the npm registry
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

refactor(i18n): externalize and organize hardcoded strings (#282)

Co-authored-by: Daniel Roe <daniel@roe.dev>

authored by

TAKAHASHI Shuuji
Daniel Roe
and committed by
GitHub
e53da338 4f71ec08

+33 -18
+1 -1
app/app.vue
··· 50 50 51 51 <template> 52 52 <div class="min-h-screen flex flex-col bg-bg text-fg"> 53 - <a href="#main-content" class="skip-link font-mono">Skip to main content</a> 53 + <a href="#main-content" class="skip-link font-mono">{{ $t('common.skip_link') }}</a> 54 54 55 55 <AppHeader :show-logo="!isHomepage" /> 56 56
+2 -2
app/components/AccentColorPicker.vue
··· 5 5 </script> 6 6 7 7 <template> 8 - <div role="listbox" aria-label="Accent colors" class="flex items-center gap-4"> 8 + <div role="listbox" :aria-label="$t('settings.accent_colors')" class="flex items-center gap-4"> 9 9 <button 10 10 v-for="color in accentColors" 11 11 :key="color.id" ··· 19 19 /> 20 20 <button 21 21 type="button" 22 - aria-label="Clear accent color" 22 + :aria-label="$t('settings.clear_accent')" 23 23 class="size-6 rounded-full transition-transform duration-150 motion-safe:hover:scale-110 focus-ring flex items-center justify-center bg-accent-fallback" 24 24 @click="setAccentColor(null)" 25 25 >
+1 -1
app/components/AppFooter.vue
··· 1 1 <template> 2 - <footer class="border-t border-border mt-auto" aria-label="Site footer"> 2 + <footer class="border-t border-border mt-auto" :aria-label="$t('footer.site_footer')"> 3 3 <div class="container py-3 sm:py-8 flex flex-col gap-2 sm:gap-4 text-fg-subtle text-sm"> 4 4 <div class="flex flex-col sm:flex-row items-center justify-between gap-2 sm:gap-4"> 5 5 <p class="font-mono m-0 hidden sm:block">{{ $t('tagline') }}</p>
+2 -2
app/components/AppHeader.vue
··· 45 45 46 46 <template> 47 47 <header 48 - aria-label="Site header" 48 + :aria-label="$t('header.site_header')" 49 49 class="sticky top-0 z-50 bg-bg/80 backdrop-blur-md border-b border-border" 50 50 > 51 - <nav aria-label="Main navigation" class="container h-14 flex items-center"> 51 + <nav :aria-label="$t('nav.main_navigation')" class="container h-14 flex items-center"> 52 52 <!-- Left: Logo --> 53 53 <div class="flex-shrink-0"> 54 54 <NuxtLink
+2 -2
app/components/ChartModal.vue
··· 29 29 <button 30 30 type="button" 31 31 class="absolute inset-0 bg-black/60 cursor-default" 32 - aria-label="Close modal" 32 + :aria-label="$t('common.close_modal')" 33 33 @click="open = false" 34 34 /> 35 35 ··· 47 47 <button 48 48 type="button" 49 49 class="text-fg-subtle hover:text-fg transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-fg/50 rounded" 50 - aria-label="Close" 50 + :aria-label="$t('common.close')" 51 51 @click="open = false" 52 52 > 53 53 <span class="i-carbon-close block w-5 h-5" aria-hidden="true" />
+1 -1
app/components/PackageDependencies.vue
··· 118 118 :title="`${getVulnerableDepInfo(dep)!.counts.total} vulnerabilities`" 119 119 > 120 120 <span class="i-carbon-security w-3 h-3 block" aria-hidden="true" /> 121 - <span class="sr-only">View vulnerabilities</span> 121 + <span class="sr-only">{{ $t('package.dependencies.view_vulnerabilities') }}</span> 122 122 </NuxtLink> 123 123 <NuxtLink 124 124 :to="{ name: 'package', params: { package: [...dep.split('/'), 'v', version] } }"
+4 -2
app/pages/[...package].vue
··· 521 521 <!-- Internal navigation: Docs + Code (hidden on mobile, shown in external links instead) --> 522 522 <nav 523 523 v-if="displayVersion" 524 - aria-label="Package navigation" 524 + :aria-label="$t('package.navigation')" 525 525 class="hidden sm:flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md shrink-0 ml-auto self-center" 526 526 > 527 527 <NuxtLink ··· 831 831 <!-- Binary-only packages: Show only execute command (no install) --> 832 832 <section v-if="isBinaryOnly" aria-labelledby="run-heading" class="area-install scroll-mt-20"> 833 833 <div class="flex flex-wrap items-center justify-between mb-3"> 834 - <h2 id="run-heading" class="text-xs text-fg-subtle uppercase tracking-wider">Run</h2> 834 + <h2 id="run-heading" class="text-xs text-fg-subtle uppercase tracking-wider"> 835 + {{ $t('package.run.title') }} 836 + </h2> 835 837 <!-- Package manager tabs --> 836 838 <div 837 839 class="flex items-center gap-1 p-0.5 bg-bg-subtle border border-border-subtle rounded-md"
+1 -1
app/pages/code/[...path].vue
··· 295 295 296 296 <!-- Breadcrumb navigation --> 297 297 <nav 298 - aria-label="File path" 298 + :aria-label="$t('code.file_path')" 299 299 class="flex items-center gap-1 font-mono text-sm overflow-x-auto" 300 300 > 301 301 <NuxtLink
+2 -2
app/pages/docs/[...path].vue
··· 156 156 157 157 <div v-else-if="showEmptyState" class="p-6 sm:p-8 lg:p-12"> 158 158 <div class="max-w-xl rounded-lg border border-border bg-bg-muted p-6"> 159 - <h2 class="font-mono text-lg mb-2">Docs not available</h2> 159 + <h2 class="font-mono text-lg mb-2">{{ $t('package.docs.not_available') }}</h2> 160 160 <p class="text-fg-subtle text-sm"> 161 - {{ docsData?.message ?? 'We could not generate docs for this version.' }} 161 + {{ docsData?.message ?? $t('package.docs.not_available_detail') }} 162 162 </p> 163 163 <div class="flex gap-4 mt-4"> 164 164 <NuxtLink
+2 -2
app/pages/search.vue
··· 703 703 <!-- Sticky search header - positioned below AppHeader (h-14 = 56px) --> 704 704 <header class="sticky top-14 z-40 bg-bg/95 backdrop-blur-sm border-b border-border"> 705 705 <div class="container-sm py-4"> 706 - <h1 class="font-mono text-xl sm:text-2xl font-medium mb-4">search</h1> 706 + <h1 class="font-mono text-xl sm:text-2xl font-medium mb-4">{{ $t('nav.search') }}</h1> 707 707 708 708 <search> 709 709 <form role="search" method="GET" action="/search" class="relative" @submit.prevent> ··· 755 755 756 756 <!-- Results area with container padding --> 757 757 <div class="container-sm pt-20 pb-6"> 758 - <section v-if="query" aria-label="Search results" @keydown="handleResultsKeydown"> 758 + <section v-if="query" :aria-label="$t('search.results')" @keydown="handleResultsKeydown"> 759 759 <!-- Initial loading (only after user interaction, not during view transition) --> 760 760 <LoadingSpinner v-if="showSearching" :text="$t('search.searching')" /> 761 761
+15 -2
i18n/locales/en.json
··· 9 9 "non_affiliation_disclaimer": "not affiliated with npm, Inc.", 10 10 "trademark_disclaimer": "npm is a registered trademark of npm, Inc. This site is not affiliated with npm, Inc.", 11 11 "footer": { 12 + "site_footer": "Site footer", 12 13 "about": "about", 13 14 "docs": "docs", 14 15 "source": "source", ··· 24 25 "found_packages": "Found {count} packages", 25 26 "updating": "(updating...)", 26 27 "no_results": "No packages found for \"{query}\"", 28 + "results": "Search results", 27 29 "not_taken": "{name} is not taken", 28 30 "claim_prompt": "Claim this package name on npm", 29 31 "claim_button": "Claim \"{name}\"", ··· 38 40 } 39 41 }, 40 42 "nav": { 43 + "main_navigation": "Main navigation", 41 44 "popular_packages": "Popular packages", 42 45 "search": "search", 43 46 "settings": "settings", ··· 52 55 "theme_system": "System", 53 56 "language": "Language", 54 57 "help_translate": "Help translate npmx", 55 - "accent_colors": "Accent colors" 58 + "accent_colors": "Accent colors", 59 + "clear_accent": "Clear accent color" 56 60 }, 57 61 "common": { 58 62 "loading": "Loading...", ··· 64 68 "retry": "Retry", 65 69 "copy": "copy", 66 70 "copied": "copied!", 71 + "skip_link": "Skip to main content", 72 + "close_modal": "Close modal", 67 73 "show_more": "show more", 68 74 "warnings": "Warnings:", 69 75 "go_back_home": "Go back home", ··· 84 90 "not_latest": "(not latest)", 85 91 "verified_provenance": "Verified provenance", 86 92 "view_permalink": "View permalink for this version", 93 + "navigation": "Package navigation", 87 94 "deprecation": { 88 95 "package": "This package has been deprecated.", 89 96 "version": "This version has been deprecated.", ··· 105 112 "code": "code", 106 113 "docs": "docs", 107 114 "fund": "fund" 115 + }, 116 + "docs": { 117 + "not_available": "Docs not available", 118 + "not_available_detail": "We could not generate docs for this version." 108 119 }, 109 120 "get_started": { 110 121 "title": "Get started", ··· 151 162 "title": "Dependencies ({count})", 152 163 "list_label": "Package dependencies", 153 164 "show_all": "show all {count} deps", 154 - "optional": "optional" 165 + "optional": "optional", 166 + "view_vulnerabilities": "View vulnerabilities" 155 167 }, 156 168 "peer_dependencies": { 157 169 "title": "Peer Dependencies ({count})", ··· 563 575 } 564 576 }, 565 577 "header": { 578 + "site_header": "Site header", 566 579 "home": "npmx home", 567 580 "github": "GitHub", 568 581 "packages": "packages",