Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 10 additions & 2 deletions app/components/Package/Dependencies.vue
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,11 @@ const numberFormatter = useNumberFormatter()
:to="packageRoute(dep, getVulnerableDepInfo(dep)!.version)"
class="shrink-0"
:class="SEVERITY_TEXT_COLORS[getHighestSeverity(getVulnerableDepInfo(dep)!.counts)]"
:title="`${getVulnerableDepInfo(dep)!.counts.total} vulnerabilities`"
:title="
$t('package.dependencies.vulnerabilities_count', {
count: getVulnerableDepInfo(dep)!.counts.total,
})
"
classicon="i-lucide:shield-check"
>
<span class="sr-only">{{ $t('package.dependencies.view_vulnerabilities') }}</span>
Expand All @@ -176,7 +180,11 @@ const numberFormatter = useNumberFormatter()
({{ getOutdatedTooltip(outdatedDeps[dep], $t) }})
</span>
<span v-if="getVulnerableDepInfo(dep)" class="sr-only">
({{ getVulnerableDepInfo(dep)!.counts.total }} vulnerabilities)
({{
$t('package.dependencies.vulnerabilities_count', {
count: getVulnerableDepInfo(dep)!.counts.total,
})
}})
</span>
</span>
</li>
Expand Down
2 changes: 1 addition & 1 deletion app/components/Package/ListToolbar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ const { selectedPackages, clearSelectedPackages } = usePackageSelection()
</ButtonBase>
<button
@click="clearSelectedPackages"
aria-label="Close action bar"
:aria-label="$t('filters.clear_selected_label')"
class="flex items-center ms-2"
>
<span class="i-lucide:x text-sm" />
Expand Down
2 changes: 1 addition & 1 deletion app/components/Package/SkillsModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ function getWarningTooltip(skill: SkillListItem): string | undefined {
"
@click="selectedMethod = 'skills-cli'"
>
skills CLI
{{ $t('package.skills.skills_cli') }}
</button>
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions app/components/Package/VersionDistribution.vue
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ const chartConfig = computed<VueUiXyConfig>(() => {
tabindex="0"
class="i-lucide:info w-3.5 h-3.5 text-fg-subtle cursor-help shrink-0 rounded-sm"
role="img"
aria-label="versions info"
:aria-label="$t('package.versions.grouping_versions_about')"
/>
</TooltipApp>
</label>
Expand Down Expand Up @@ -412,7 +412,7 @@ const chartConfig = computed<VueUiXyConfig>(() => {
tabindex="0"
class="i-lucide:info w-3.5 h-3.5 text-fg-subtle cursor-help shrink-0 rounded-sm"
role="img"
aria-label="versions info"
:aria-label="$t('package.versions.grouping_usage_about')"
/>
</TooltipApp>
</label>
Expand Down
2 changes: 1 addition & 1 deletion app/components/VersionSelector.vue
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ watch(
type="button"
class="w-4 h-4 flex items-center justify-center text-fg-subtle hover:text-fg transition-colors shrink-0"
:aria-expanded="group.isExpanded"
:aria-label="group.isExpanded ? 'Collapse' : 'Expand'"
:aria-label="group.isExpanded ? $t('common.collapse') : $t('common.expand')"
@click.stop="toggleGroup(group.id)"
>
<span
Expand Down
31 changes: 17 additions & 14 deletions app/components/diff/ViewerPanel.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ function getCodeUrl(version: string): string {
@click="showOptions = !showOptions"
>
<span class="i-lucide:settings w-3.5 h-3.5" />
Options
{{ $t('compare.options') }}
<span
class="i-lucide:chevron-down w-3 h-3 transition-transform"
:class="{ 'rotate-180': showOptions }"
Expand Down Expand Up @@ -174,10 +174,13 @@ function getCodeUrl(version: string): string {
>
<div class="flex flex-col gap-2">
<!-- Merge modified lines toggle -->
<SettingsToggle label="Merge modified lines" v-model="mergeModifiedLines" />
<SettingsToggle
:label="$t('compare.merge_modified_lines')"
v-model="mergeModifiedLines"
/>

<!-- Word wrap toggle -->
<SettingsToggle label="Word wrap" v-model="wordWrap" />
<SettingsToggle :label="$t('compare.word_wrap')" v-model="wordWrap" />

<!-- Sliders -->
<div
Expand All @@ -186,14 +189,14 @@ function getCodeUrl(version: string): string {
>
<!-- Change ratio slider -->
<div class="sr-only">
<label for="change-ratio">Change ratio</label>
<label for="change-ratio">{{ $t('compare.change_ratio') }}</label>
</div>
<div
class="slider-shell w-full min-w-0"
:class="{ 'is-disabled': !mergeModifiedLines }"
>
<div class="slider-labels">
<span class="slider-label">Change ratio</span>
<span class="slider-label">{{ $t('compare.change_ratio') }}</span>
<span class="slider-value tabular-nums">{{ maxChangeRatio.toFixed(2) }}</span>
</div>
<div class="slider-track">
Expand All @@ -219,14 +222,14 @@ function getCodeUrl(version: string): string {

<!-- Diff distance slider -->
<div class="sr-only">
<label for="diff-distance">Diff distance</label>
<label for="diff-distance">{{ $t('compare.diff_distance') }}</label>
</div>
<div
class="slider-shell w-full min-w-0"
:class="{ 'is-disabled': !mergeModifiedLines }"
>
<div class="slider-labels">
<span class="slider-label">Diff distance</span>
<span class="slider-label">{{ $t('compare.diff_distance') }}</span>
<span class="slider-value tabular-nums">{{ maxDiffDistance }}</span>
</div>
<div class="slider-track">
Expand All @@ -252,14 +255,14 @@ function getCodeUrl(version: string): string {

<!-- Char edits slider -->
<div class="sr-only">
<label for="char-edits">Char edits</label>
<label for="char-edits">{{ $t('compare.char_edits') }}</label>
</div>
<div
class="slider-shell w-full min-w-0"
:class="{ 'is-disabled': !mergeModifiedLines }"
>
<div class="slider-labels">
<span class="slider-label">Char edits</span>
<span class="slider-label">{{ $t('compare.char_edits') }}</span>
<span class="slider-value tabular-nums">{{ inlineMaxCharEdits }}</span>
</div>
<div class="slider-track">
Expand Down Expand Up @@ -295,7 +298,7 @@ function getCodeUrl(version: string): string {
class="px-2 py-1 text-xs text-fg-muted hover:text-fg bg-bg-muted border border-border rounded transition-colors"
target="_blank"
>
View file
{{ $t('compare.view_file') }}
</NuxtLink>
</div>
</div>
Expand All @@ -317,22 +320,22 @@ function getCodeUrl(version: string): string {
<!-- Loading state -->
<div v-else-if="status === 'pending'" class="py-12 text-center">
<div class="i-svg-spinners-ring-resize w-6 h-6 mx-auto text-fg-muted" />
<p class="mt-2 text-sm text-fg-muted">Loading diff...</p>
<p class="mt-2 text-sm text-fg-muted">{{ $t('compare.loading_diff') }}</p>
</div>

<!-- Error state -->
<div v-else-if="status === 'error'" class="py-8 text-center">
<span class="i-lucide:triangle-alert w-8 h-8 mx-auto text-fg-subtle mb-2 block" />
<p class="text-fg-muted text-sm mb-2">
{{ loadError?.message || 'Failed to load diff' }}
{{ loadError?.message || $t('compare.loading_diff_error') }}
</p>
<div class="flex items-center justify-center gap-2">
<NuxtLink
v-if="file.type !== 'removed'"
:to="getCodeUrl(toVersion)"
class="text-xs text-fg-muted hover:text-fg underline"
>
View in code browser
{{ $t('compare.view_in_code_browser') }}
</NuxtLink>
</div>
</div>
Expand All @@ -342,7 +345,7 @@ function getCodeUrl(version: string): string {
v-else-if="diff && diff.hunks.length === 0"
class="py-8 text-center text-fg-muted text-sm"
>
No content changes detected
{{ $t('compare.no_content_changes') }}
</div>

<!-- Diff content -->
Expand Down
4 changes: 2 additions & 2 deletions app/pages/blog/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ useSeoMeta({
:authors="post.authors"
:title="post.title"
:path="post.slug"
:excerpt="post.excerpt || post.description || 'No Excerpt Available'"
:excerpt="post.excerpt || post.description"
:topics="Array.isArray(post.tags) ? post.tags : placeHolder"
:published="post.date"
:index="idx"
Expand All @@ -47,7 +47,7 @@ useSeoMeta({
</template>
</article>

<p v-else class="text-center py-20 text-fg-subtle">No posts found.</p>
<p v-else class="text-center py-20 text-fg-subtle">{{ $t('blog.no_posts') }}</p>
</article>
</main>
</template>
15 changes: 10 additions & 5 deletions app/pages/diff/[[org]]/[packageName]/v/[versionRange].vue
Original file line number Diff line number Diff line change
Expand Up @@ -135,21 +135,26 @@ useSeoMeta({
<!-- Error: invalid route -->
<div v-if="!versionRange" class="container py-20 text-center">
<p class="text-fg-muted mb-4">
Invalid comparison URL. Use format: /diff/package/v/from...to
{{ $t('compare.version_invalid_url') }}
<code class="font-mono text-sm">/diff/package/v/from...to</code>
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn't sure what the best way to handle this would be, and if we should attempt to add translations for package/from/to. Seems like if we did, we'd want additional brackets or something to separate them out from the "hard-coded" parts of the url (e.g. /diff/[packageName]/v/[from]...[to]). Not totally sure what a i18n key for that would look like.

Copy link
Copy Markdown
Member

@MatteoGabriele MatteoGabriele Mar 19, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do think we need to translate the "from" and "to" strings.
something like $t('compare.version_diff_format', { packageName }) and the string would be:

en.json:

{
  "version_invalid_format": {
    "hint": "Invalid comparison URL. Use format: {0}",
    "format": "/diff/{packageName}/v/from...to"
  },
}

then you use the i18n-t component with something like this

<i18n-t keypath="version_invalid_format.hint" tag="p" for="format">
    <code>{{ $t("version_invalid_format.format") }}</code>
</i18n-t>

I hope this is what you were looking for

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for that! I added the i18n component, and split the format details into additional keys for from and to, while leaving the rest hard-coded (with the packageName interpolated). Hopefully that reduces the potential for introducing errors to the full string in the translations.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I do find the HTML a bit harder to read, but I think it would probably reduce the number of typos when translating the example.

</p>
<NuxtLink :to="packageRoute(packageName)" class="btn">Go to package</NuxtLink>
<NuxtLink :to="packageRoute(packageName)" class="btn">{{
$t('compare.version_back_to_package')
}}</NuxtLink>
</div>

<!-- Loading state -->
<div v-else-if="compareStatus === 'pending'" class="container py-20 text-center">
<div class="i-svg-spinners-ring-resize w-8 h-8 mx-auto text-fg-muted" />
<p class="mt-4 text-fg-muted">Comparing versions...</p>
<p class="mt-4 text-fg-muted">{{ $t('compare.comparing_versions_label') }}</p>
</div>

<!-- Error state -->
<div v-else-if="compareStatus === 'error'" class="container py-20 text-center" role="alert">
<p class="text-fg-muted mb-4">Failed to compare versions</p>
<NuxtLink :to="packageRoute(packageName)" class="btn">Back to package</NuxtLink>
<p class="text-fg-muted mb-4">{{ $t('compare.version_error_message') }}</p>
<NuxtLink :to="packageRoute(packageName)" class="btn">{{
$t('compare.version_back_to_package')
}}</NuxtLink>
</div>

<!-- Comparison content -->
Expand Down
31 changes: 27 additions & 4 deletions i18n/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@
},
"draft_badge": "Draft",
"draft_banner": "This is an unpublished draft. It may be incomplete or contain inaccuracies.",
"no_posts": "No posts found.",
"atproto": {
"view_on_bluesky": "View on Bluesky",
"reply_on_bluesky": "Reply on Bluesky",
Expand Down Expand Up @@ -207,7 +208,9 @@
"radicle": "View on Radicle",
"sourcehut": "View on SourceHut",
"tangled": "View on Tangled"
}
},
"collapse": "Collapse",
"expand": "Expand"
},
"profile": {
"display_name": "Display Name",
Expand Down Expand Up @@ -286,7 +289,8 @@
"refs": "{count} ref | {count} refs",
"assets": "{count} asset | {count} assets"
},
"view_source": "View source"
"view_source": "View source",
"skills_cli": "skills CLI"
},
"links": {
"main": "main",
Expand Down Expand Up @@ -390,9 +394,11 @@
"grouping_major": "Major",
"grouping_minor": "Minor",
"grouping_versions_title": "Versions",
"grouping_versions_about": "About version grouping",
"grouping_versions_all": "All",
"grouping_versions_only_recent": "Only recent",
"grouping_usage_title": "Usage",
"grouping_usage_about": "About usage grouping",
"grouping_usage_all": "All",
"grouping_usage_most_used": "Most used",
"recent_versions_only_tooltip": "Show only versions published within the last year.",
Expand Down Expand Up @@ -423,7 +429,8 @@
"outdated_major": "{count} major version behind (latest: {latest}) | {count} major versions behind (latest: {latest})",
"outdated_minor": "{count} minor version behind (latest: {latest}) | {count} minor versions behind (latest: {latest})",
"outdated_patch": "Patch update available (latest: {latest})",
"has_replacement": "This dependency has suggested replacements"
"has_replacement": "This dependency has suggested replacements",
"vulnerabilities_count": "{count} vulnerability | {count} vulnerabilities"
},
"peer_dependencies": {
"title": "Peer Dependency ({count}) | Peer Dependencies ({count})",
Expand Down Expand Up @@ -867,6 +874,7 @@
"insecure": "With warnings"
},
"view_selected": "View selected",
"clear_selected_label": "Clear selected",
"sort": {
"label": "Sort packages",
"toggle_direction": "Toggle sort direction",
Expand Down Expand Up @@ -1179,6 +1187,10 @@
"file_size_warning": "{size} exceeds the 250KB limit for comparison",
"compare_versions": "diff",
"compare_versions_title": "Compare with latest version",
"comparing_versions_label": "Comparing versions...",
"version_back_to_package": "Back to package",
"version_error_message": "Failed to compare versions.",
"version_invalid_url": "Invalid comparison URL. Use format:",
"version_selector_title": "Compare with version",
"summary": "Summary",
"deps_count": "{count} dep | {count} deps",
Expand All @@ -1205,7 +1217,18 @@
"files_button": "Files",
"select_file_prompt": "Select a file from the sidebar to view its diff",
"close_files_panel": "Close files panel",
"filter_files_label": "Filter files by change type"
"filter_files_label": "Filter files by change type",
"change_ratio": "Change ratio",
"char_edits": "Char edits",
"diff_distance": "Diff distance",
"loading_diff": "Loading diff...",
"loading_diff_error": "Failed to load diff",
"merge_modified_lines": "Merge modified lines",
"no_content_changes": "No content changes detected",
"options": "Options",
"view_file": "View file",
"view_in_code_browser": "View in code browser",
"word_wrap": "Word wrap"
},
"pds": {
"title": "npmx.social",
Expand Down
Loading
Loading