diff --git a/.storybook/handlers.ts b/.storybook/handlers.ts index c8e485285a..fa5544eced 100644 --- a/.storybook/handlers.ts +++ b/.storybook/handlers.ts @@ -91,68 +91,3 @@ export const pdsUsersHandler = http.get('/api/atproto/pds-users', () => { }, ]) }) - -export const i18nStatusHandler = http.get('/lunaria/status.json', () => { - return HttpResponse.json({ - generatedAt: '2026-01-22T10:07:07.000Z', - sourceLocale: { - lang: 'en', - label: 'English', - totalKeys: 500, - }, - locales: [ - { - lang: 'en-GB', - label: 'English (UK)', - dir: 'ltr', - totalKeys: 500, - completedKeys: 423, - percentComplete: 84, - missingKeys: [ - 'settings.background_themes.label', - 'settings.enable_graph_pulse_loop', - 'settings.enable_graph_pulse_loop_description', - 'settings.data_source.algolia_description', - 'settings.data_source.npm_description', - 'i18n.contribute_hint', - 'i18n.copy_keys', - ], - githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/en-GB.json', - githubHistoryUrl: - 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/en-GB.json', - }, - { - lang: 'fr-FR', - label: 'Français', - dir: 'ltr', - totalKeys: 500, - completedKeys: 423, - percentComplete: 84, - missingKeys: [ - 'settings.background_themes.label', - 'settings.enable_graph_pulse_loop', - 'settings.enable_graph_pulse_loop_description', - 'settings.data_source.algolia_description', - 'settings.data_source.npm_description', - 'i18n.contribute_hint', - 'i18n.copy_keys', - ], - githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/fr-FR.json', - githubHistoryUrl: - 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/fr-FR.json', - }, - { - lang: 'de-DE', - label: 'Deutsch', - dir: 'ltr', - totalKeys: 500, - completedKeys: 500, - percentComplete: 100, - missingKeys: [], - githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/de-DE.json', - githubHistoryUrl: - 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/de-DE.json', - }, - ], - }) -}) diff --git a/.storybook/handlers/lunaria-status.ts b/.storybook/handlers/lunaria-status.ts new file mode 100644 index 0000000000..878adf3070 --- /dev/null +++ b/.storybook/handlers/lunaria-status.ts @@ -0,0 +1,357 @@ +import { http, HttpResponse } from 'msw' + +export const i18nStatusHandler = http.get('/lunaria/status.json', () => { + return HttpResponse.json({ + generatedAt: '2026-01-22T10:07:07.000Z', + sourceLocale: { + lang: 'en', + label: 'English', + totalKeys: 100, + }, + locales: [ + { + lang: 'ar-EG', + label: 'العربية', + dir: 'rtl', + totalKeys: 100, + completedKeys: 79, + percentComplete: 79, + missingKeys: [ + 'settings.background_themes.label', + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + 'package.version', + 'package.downloads', + 'package.dependencies', + 'search.placeholder', + 'search.results', + 'nav.docs', + 'nav.blog', + 'error.not_found', + 'error.server_error', + 'common.loading', + 'common.error', + 'common.close', + 'common.save', + 'common.cancel', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/ar-EG.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/ar-EG.json', + }, + { + lang: 'en-GB', + label: 'English (UK)', + dir: 'ltr', + totalKeys: 100, + completedKeys: 93, + percentComplete: 93, + missingKeys: [ + 'settings.background_themes.label', + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/en-GB.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/en-GB.json', + }, + { + lang: 'fr-FR', + label: 'Français', + dir: 'ltr', + totalKeys: 100, + completedKeys: 90, + percentComplete: 90, + missingKeys: [ + 'settings.background_themes.label', + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + 'package.version', + 'package.downloads', + 'package.dependencies', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/fr-FR.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/fr-FR.json', + }, + { + lang: 'es-ES', + label: 'Español (España)', + dir: 'ltr', + totalKeys: 100, + completedKeys: 60, + percentComplete: 60, + missingKeys: [ + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + 'package.version', + 'package.downloads', + 'package.dependencies', + 'search.placeholder', + 'search.results', + 'nav.docs', + 'nav.blog', + 'error.not_found', + 'error.server_error', + 'common.loading', + 'common.error', + 'common.close', + 'common.save', + 'common.cancel', + 'settings.theme', + 'settings.language', + 'settings.accessibility', + 'settings.notifications', + 'settings.privacy', + 'package.license', + 'package.homepage', + 'package.repository', + 'package.keywords', + 'package.maintainers', + 'package.publish_date', + 'package.last_updated', + 'search.no_results', + 'search.filters', + 'nav.settings', + 'nav.profile', + 'nav.sign_in', + 'nav.sign_out', + 'error.unauthorized', + 'error.forbidden', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/es-ES.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/es-ES.json', + }, + { + lang: 'pt-PT', + label: 'Português (Portugal)', + dir: 'ltr', + totalKeys: 100, + completedKeys: 25, + percentComplete: 25, + missingKeys: [ + 'settings.background_themes.label', + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + 'package.version', + 'package.downloads', + 'package.dependencies', + 'package.license', + 'search.placeholder', + 'search.results', + 'nav.docs', + 'nav.blog', + 'error.not_found', + 'error.server_error', + 'common.loading', + 'common.error', + 'common.close', + 'common.save', + 'common.cancel', + 'settings.theme', + 'settings.language', + 'settings.accessibility', + 'settings.notifications', + 'settings.privacy', + 'package.scripts', + 'package.homepage', + 'package.repository', + 'package.keywords', + 'package.maintainers', + 'package.publish_date', + 'package.last_updated', + 'search.no_results', + 'search.filters', + 'nav.settings', + 'nav.profile', + 'nav.sign_in', + 'nav.sign_out', + 'error.unauthorized', + 'error.forbidden', + 'blog.read_more', + 'blog.published', + 'blog.author', + 'blog.tags', + 'blog.share', + 'package.size', + 'package.types', + 'package.exports', + 'package.funding', + 'package.deprecated', + 'package.unpublished', + 'search.sort_by', + 'search.sort_popularity', + 'search.sort_quality', + 'search.sort_maintenance', + 'search.sort_date', + 'search.advanced', + 'search.clear', + 'settings.account', + 'settings.appearance', + 'settings.keyboard_shortcuts', + 'settings.reset', + 'error.rate_limited', + 'error.network', + 'common.retry', + 'common.copy', + 'common.copied', + 'common.share', + 'common.back', + 'common.next', + 'common.previous', + 'common.view_on_github', + 'common.confirm', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/pt-PT.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/pt-PT.json', + }, + { + lang: 'nl-NL', + label: 'Nederlands', + dir: 'ltr', + totalKeys: 100, + completedKeys: 0, + percentComplete: 0, + missingKeys: [ + 'settings.background_themes.label', + 'settings.enable_graph_pulse_loop', + 'settings.enable_graph_pulse_loop_description', + 'settings.data_source.algolia_description', + 'settings.data_source.npm_description', + 'i18n.contribute_hint', + 'i18n.copy_keys', + 'package.version', + 'package.downloads', + 'package.dependencies', + 'package.license', + 'search.placeholder', + 'search.results', + 'nav.docs', + 'nav.blog', + 'error.not_found', + 'error.server_error', + 'common.loading', + 'common.error', + 'common.close', + 'common.save', + 'common.cancel', + 'settings.theme', + 'settings.language', + 'settings.accessibility', + 'settings.notifications', + 'settings.privacy', + 'package.homepage', + 'package.repository', + 'package.keywords', + 'package.maintainers', + 'package.publish_date', + 'package.last_updated', + 'search.no_results', + 'search.filters', + 'nav.settings', + 'nav.profile', + 'nav.sign_in', + 'nav.sign_out', + 'error.unauthorized', + 'error.forbidden', + 'blog.read_more', + 'blog.published', + 'blog.author', + 'blog.tags', + 'blog.share', + 'package.size', + 'package.types', + 'package.exports', + 'package.funding', + 'package.deprecated', + 'package.unpublished', + 'search.sort_by', + 'search.sort_popularity', + 'search.sort_quality', + 'search.sort_maintenance', + 'search.sort_date', + 'search.advanced', + 'search.clear', + 'settings.account', + 'settings.appearance', + 'settings.keyboard_shortcuts', + 'settings.reset', + 'error.rate_limited', + 'error.network', + 'common.retry', + 'common.copy', + 'common.copied', + 'common.share', + 'common.back', + 'common.next', + 'common.previous', + 'common.view_on_github', + 'common.confirm', + 'common.dismiss', + 'common.open', + 'common.download', + 'common.filter', + 'common.sort', + 'common.edit', + 'common.delete', + 'common.expand', + 'common.collapse', + 'nav.home', + 'nav.about', + 'nav.compare', + 'nav.search', + 'package.changelog', + 'package.provenance', + 'package.peer_dependencies', + 'package.optional_dependencies', + 'package.dev_dependencies', + 'package.bundle_size', + 'package.esm', + 'blog.next_post', + 'blog.previous_post', + 'search.type_filter', + 'search.scope_filter', + 'settings.export_data', + 'settings.delete_account', + ], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/nl-NL.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/nl-NL.json', + }, + { + lang: 'de-DE', + label: 'Deutsch', + dir: 'ltr', + totalKeys: 100, + completedKeys: 100, + percentComplete: 100, + missingKeys: [], + githubEditUrl: 'https://github.com/npmx-dev/npmx.dev/edit/main/i18n/locales/de-DE.json', + githubHistoryUrl: + 'https://github.com/npmx-dev/npmx.dev/commits/main/i18n/locales/de-DE.json', + }, + ], + }) +}) diff --git a/app/pages/settings.stories.ts b/app/pages/settings.stories.ts index 1deaecbc19..8d5571d20e 100644 --- a/app/pages/settings.stories.ts +++ b/app/pages/settings.stories.ts @@ -2,7 +2,7 @@ import Settings from './settings.vue' import type { Meta, StoryObj } from '@storybook-vue/nuxt' import { userEvent, expect } from 'storybook/test' import { pageDecorator } from '../../.storybook/decorators' -import { i18nStatusHandler } from '../../.storybook/handlers' +import { i18nStatusHandler } from '../../.storybook/handlers/lunaria-status' const meta = { component: Settings, diff --git a/app/pages/translation-status.stories.ts b/app/pages/translation-status.stories.ts new file mode 100644 index 0000000000..9c13223cb3 --- /dev/null +++ b/app/pages/translation-status.stories.ts @@ -0,0 +1,30 @@ +import TranslationStatus from './translation-status.vue' +import type { Meta, StoryObj } from '@storybook-vue/nuxt' +import { pageDecorator } from '../../.storybook/decorators' +import { i18nStatusHandler } from '../../.storybook/handlers/lunaria-status' + +const meta = { + component: TranslationStatus, + parameters: { + layout: 'fullscreen', + msw: { + handlers: [i18nStatusHandler], + }, + }, + decorators: [pageDecorator], +} satisfies Meta + +export default meta +type Story = StoryObj + +/** `/lunaria/status.json` is intercepted by MSW. Showing a variety of completion level translation statuses for a subset of locales. */ +export const Default: Story = {} + +/** No API response — the fetch never succeeds so `fetchStatus` stays as `'pending'`. Shows skeleton blocks in the locale list and skeleton inlines in body text. */ +export const WithoutTranslationData: Story = { + parameters: { + msw: { + handlers: [], + }, + }, +}