OpenSignup has no message catalogs or translator, so none of its text can be translated
メンテナーはふだん 1 日以内に返信
まだ誰も着手していません。
評価
- 難易度
- 4/5
- 見積もり時間
- 3〜5日
- 初心者へのやさしさ
- 38/100
- issue の種類
- 機能追加
- 明瞭さ
- 明確に書かれている
- 活発さ
- 活発
- 技術スタック
- eslint, next.js, node.js, playwright, typescript
調査の方向性
Start with next.config.mjs, eslint.config.mjs, budgets.json, and the worker test at src/email/templates/worker-render.test.ts; inspect the existing package, test, and lint setup before adding the translator plumbing. The issue lists the required catalog and i18n entry points, plus checks to run: lint, typecheck, knip, tests, build, and budgets. Done means translation works in server, test, and worker contexts, client imports are rejected by lint, and first-load JavaScript budgets pass.
索引モデルが issue の本文から書いたものです。
説明
Needs your OK: this adds next-intl and the translation plumbing the rest of #619 builds on. Nothing anyone sees changes. Swap pipeline:proposed for pipeline:ready to have it built.
What happens
Every string a person sees is typed inline, in English, in components, emails and helpers. There's no catalog to translate and no function to look a message up. Text is rendered in three places with different limits:
- Server components, the bulk of the app.
'use client'bundles, whose sizebudgets.jsoncaps.- The pg-boss worker (
pnpm worker, plain Node undertsx, no Next runtime), which renders the reminder and time-changed emails.
Fix, in outline
- Packages. Add
next-intlanduse-intlat the same exact version. pnpm's isolatednode_moduleswon't resolveuse-intl/coreas a transitive dependency, and knip flags unlisted imports. Wrapnext.config.mjswithcreateNextIntlPlugin, keepingoutput: 'standalone',serverExternalPackagesandheaders()as they are. - Catalog.
src/messages/en.json, undersrc/because the runner image copies onlysrc/and the worker runs from it (a rootmessages/folder would crash the first reminder job in production). Top-level namespaces by audience:participant,email,organizer,auth,site,common. Types come from next-intl'sAppConfigaugmentation overen.json, so a missing key or a wrong argument fails typecheck. src/i18n/config.ts, pure (nonext/*, noenv.ts):CATALOG_LOCALES(justenfor now) andSHIPPED = { participant: ['en'], organizer: ['en'], site: ['en'] }, the languages complete and reviewed for each audience.src/i18n/translator.ts:getTranslator(locale, namespace, { onError }), synchronous, built onuse-intl/core'screateTranslatorover the catalogs imported as modules. English is merged under the requested language per namespace, so a gap shows English, not a key path likeparticipant.signUp. No logging import, because Playwright specs import app copy modules. It returns the same function typeuseTranslationsdoes, so a helper written against it also works in a client component.src/i18n/server.ts: passes anonErrorthat logs one pino line per missing key. The worker will import it, so nothing fromnext/*goes in it.src/i18n/request.ts: the request config the plugin requires. For now it returnsenandtimeZone: 'UTC'.- A lint rule keyed on the
'use client'directive, in a small local ESLint plugin ineslint.config.mjs: a client file may not import the translator,server.tsor a catalog, since each carries every language. Client files live outside any fixed directory list, so read the file's leading directive rather than matching paths. - Tests: an English test translator whose
onErrorthrows, so a missing key fails a test. - knip: entries for the request config and the catalogs, with a comment saying why.
Watch for
- Don't use next-intl's server hooks (
getTranslations, oruseTranslationsin server components). 18 jsdom test files render server components synchronously withrender(), and async components would break them. Server code takes a translator fromgetTranslator. server-onlycan't guard the translator: it throws undertsxand vitest. The lint rule andpnpm budgets(a client chunk with every catalog in it blows the 108 KB*budget) are the guards.- Move no copy yet beyond what the tests need. Extraction comes in later steps of #619.
- Pieces with no caller yet wait for the step that first uses them (
resolveLocale,defaultFor, language names, the client provider wrapper), or knip fails.
Choices this makes
- next-intl, over Lingui, Paraglide, react-intl and i18next. Default: next-intl. Measured client runtimes (esbuild, minified, gzip, React excluded): use-intl 11.6 KB, or 2.8 KB with its
precompileoption (a later step); Lingui 3.4 KB, but its macros need an SWC plugin tied to Next's exactswc_coreand can't run undertsx; Paraglide 2 is built for Vite and fetches plugins from a CDN at build time; react-intl 14.9 KB; i18next 17.2 KB. - ICU MessageFormat in JSON. Default: yes. Translation tools such as Weblate read it.
- One synchronous translator for server code, emails, the worker and tests, with next-intl's React provider only around client components that need text. Default: yes.
Done when
getTranslator('en', …)works in a server component, in a unit test, and under the worker toolchain (thesrc/email/templates/worker-render.test.tspattern).- A client file that imports the translator fails lint.
- No page's first-load JS changes (
pnpm build && pnpm budgets). pnpm lint && pnpm typecheck && pnpm knip && pnpm testpass.
Planned with the owner in https://claude.ai/code/session_01EFKmj716ZY3b3SwR8TV8Y2 and checked against the code on main at 35288fa. The full plan is private to the owner's account: https://claude.ai/artifact/VgQH6U2s2EVx3LX991fJi8 (a Claude session on that account can open it with the Artifact tool's read action). This is step 0.1 there.
- 主要言語
- TypeScript
- スター
- 19
- フォーク
- 4
- 平均マージ
- 21時間 3分
- マージ済み PR(30日)
- 176
環境構築
- Dockerfile または Docker Compose ファイルあり
- プルリクエストのテンプレートなし
- コントリビューションガイドを読む
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
richshaw/OpenSignup のほかの issue
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
richshaw/OpenSignup#654 ·
メンテナーはふだん 1 日以内に返信
-
The help pages never say "pause", so organizers looking for it miss Close or reopen a signup対応中かも @richshaw が 1 日前に担当しました。 オープンenhancement pipeline:building pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
richshaw/OpenSignup#653 · 担当者 1 名 ·
メンテナーはふだん 1 日以内に返信
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
richshaw/OpenSignup#652 ·
メンテナーはふだん 1 日以内に返信
-
SMTP timeout notes in smtp.ts and the changelog describe nodemailer 10.0, not 10.1対応中かも @agammann が 2 日前に担当しました。 オープンenhancement good first issue pipeline:ready
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
richshaw/OpenSignup#645 ·
メンテナーはふだん 1 日以内に返信
-
enhancement pipeline:proposed pipeline:ux
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
richshaw/OpenSignup#589 ·
メンテナーはふだん 1 日以内に返信
richshaw/OpenSignup の issue をすべて見る
似ている issue
-
comp/desktop desktop/shell os/windows P3 tool/file type/bug
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
NousResearch/hermes-agent#145928 ·
メンテナーはふだん 1 日以内に返信
-
compiler-dom: stringifyStatic renders :disabled="0" as a present attribute対応中かも @DaZuiZui が今日担当しました。 オープン
難易度 2/5 1〜3時間 初心者へのやさしさ 76/100
メンテナーはふだん 1 日以内に返信
-
難易度 1/5 1時間未満 初心者へのやさしさ 74/100
-
integration:coding-agents
難易度 1/5 1時間未満 初心者へのやさしさ 83/100
vectorize-io/hindsight#6151 ·
メンテナーはふだん 1 日以内に返信
-
DogFooding
難易度 1/5 1時間未満 初心者へのやさしさ 88/100
OpenAEV-Platform/openaev#8768 ·
メンテナーはふだん 1 日以内に返信