Session: you-are-a-senior-buzzing-sundae-subagent-ab00a163 — 2026-04-17

workspace-doctolib · Claude · branch HEAD · claude-haiku-4-5-20251001 · 2026-04-17 13:49 · 1 msgs · 26 tools · 14 min read · updated 2 weeks ago

Explore the package at /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui to...

tools: Bash, Read, Glob
← workspace-doctolib Download .md .txt .json
Tool calls
Read Read: 16 calls (61.5%) 16 Bash Bash: 8 calls (30.8%) 8 Glob Glob: 2 calls (7.7%) 2
Token usage3.8M total
Input212
Cache creation206.7K
Cache read3.6M
Output4.7K
Cache hit ratio95%· healthy

Project: workspace-doctolib · Branch: HEAD · Mode: ` · **Model:**claude-haiku-4-5-20251001`

Stats: 1 user messages, 26 tool calls, tools used: Bash, Read, Glob.

Conversation

Turn 1 — User

Explore the package at /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui to understand:

  1. Does the package already have ANY i18n setup? Look for: - i18n.json at root level (what's in it?) - Any imports of i18n libraries (react-i18next, i18next, formatjs, etc.) - Any existing translation keys or t() function usage

  2. How are component props currently defined? Look at: - TypeScript interfaces/types for component props - What props already accept string labels externally vs hardcoding them

  3. What is the package's public API (index.ts exports)?

  4. What testing patterns exist for these components?

  5. Check the package.json for dependencies related to i18n

  6. Look at /Users/USER/workspace/doctolib/treatment-plan/packages for other packages that might already have i18n patterns we should follow.

Output a summary of findings covering all points above.

Turn 1 — Assistant

I'll explore this package systematically to understand its current state and i18n capabilities. Let me start by examining the directory structure and key files.

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui -type f -name "*.json" -o -name "*.ts" -o -name "*.tsx" | head -50

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/storybook-static/project.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/storybook-static/index.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/rsbuild.config.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/dist/entry.d.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-natio …(truncated, 9578 more chars)

Good! I can see there's already i18n structure in place. Let me explore the source files and key configuration files.

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/package.json

Tool results:

→ result (ok): 1 { 2 "name": "@doctolib/tpf-national-health-records-ui", 3 "version": "13.0.2", 4 "repository": { 5 "type": "git", 6 "url": "git+https://github.com/doctolib/treatment-plan.git" 7 }, 8 "keywords": [ 9 "upfront", 10 "modular frontend", 11 "smaller-scope" 12 ], 13 "author": "@doctolib/fire", 14 "license": "Doctolib", 15 "doctolib": { 16 "upfront-type": "smaller-scope" 17 }, 18 "type": "module", 19 "sideEffects": [ 20 "./src/i18n.ts" 21 ], 22
…(truncated, 3864 more chars)

Tools used:

  • Bash: ls -la /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/ | grep -E "i18n|src|index"

Tool results:

→ result (ok): .rw-r--r-- clertonra staff 207 B Tue Feb 24 15:53:39 2026 i18n.json drwxr-xr-x clertonra staff 448 B Thu Apr 16 16:25:13 2026 src

Tools used:

  • Glob: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/**/*.ts

Tool results:

→ result (ok): treatment-plan/packages/tpf-national-health-records-ui/src/tests/index.test.ts treatment-plan/packages/tpf-national-health-records-ui/src/i18n.ts treatment-plan/packages/tpf-national-health-records-ui/src/entry.ts treatment-plan/packages/tpf-national-health-records-ui/src/test-helpers/fixtures/createFixtureBuilder.ts treatment-plan/packages/tpf-national-health-records-ui/src/test-helpers/fixtures/index.ts treatment-plan/packages/tpf-national-health-records-ui/src/test-helpers/fixtures/nhrDoc …(truncated, 2858 more chars)

Now let me examine the i18n configuration files and source code:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/i18n.json

Tool results:

→ result (ok): 1 { 2 "projectIDs": ["0965d2af05c26d3439c7ebf078fb684d"], 3 "namespaces": ["tpf_national_health_records_ui"], 4 "outputPath": "packages/tpf-national-health-records-ui/src/locales", 5 "locales": ["en", "fr"] 6 } 7

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.ts

Tool results:

→ result (ok): 1 import { i18n } from '@doctolib/tpf-commons/i18n' 2
3 import { loadNamespace } from './locales/loadNamespace' 4
5 i18n.registerNamespace('tpf_national_health_records_ui', loadNamespace) 6
7 export const t = i18n.t 8 export const changeLanguage = i18n.changeLanguage 9 // To be used only for storybook 10 export const getInstance = i18n.getInstance 11

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/index.ts

Tool results:

→ result (ok): 1 export { NhrDocumentList } from './components/NhrDocumentList/NhrDocumentList' 2 export { NhrDocumentListFilterPanel } from './components/NhrDocumentListFilterPanel/NhrDocumentListFilterPanel' 3 export type { 4 ActionConfig, 5 ActionsFactory, 6 ColumnConfig, 7 FilterConfig, 8 FilterRenderContext, 9 NhrPatientInfo, 10 NhrVisibilityEntry, 11 StatusOption, 12 NhrDocumentStatusFilterProps, 13 VisibilityOption, 14 SearchDocumentsFn, 15 } from './types' 16 export { NhrEntryPoin …(truncated, 2130 more chars)

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/loadNamespace.ts

Tool results:

→ result (ok): 1 import type { Language } from '@doctolib/upfront-core/i18n' 2
3 import NationalHealthRecordsUiEn from './en/tpf_national_health_records_ui.json' 4 import NationalHealthRecordsUiFr from './fr/tpf_national_health_records_ui.json' 5
6 export const loadNamespace = (lang: Language, namespace: string) => { 7 console.log(Loading namespace: ${namespace} for language: ${lang}) 8
9 if (namespace !== 'tpf_national_health_records_ui') { 10 throw new Error(Unsupported namespace: ${namespace} …(truncated, 284 more chars)

Let me check the translation files and component prop definitions:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/en/tpf_national_health_records_ui.json

Tool results:

→ result (ok): 1 { 2 "entry_point.open": "Open NHR", 3 "filters.date_selection.custom_range.label": "Custom date range", 4 "filters.date_selection.last_access.label": "Since I last accessed this DMP", 5 "filters.date_selection.last_access.message": "Last accessed on:", 6 "translation": "Translation" 7 } 8

Tools used:

  • Glob: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/**/*.tsx

Tool results:

→ result (ok): treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPointButton/NhrEntryPointButton.stories.tsx treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPointButton/NhrEntryPointButton.tsx treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/NhrDocumentListTable/NhrDocumentListTableHead/NhrDocumentListTableHead.test.tsx treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentListModal/Nh …(truncated, 8344 more chars)

Now let me check the types and examine some component prop definitions:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts

Tool results:

→ result (ok): 1 import type { DesignSystemIconComponent } from '@doctolib/design-system-icons' 2 import type { NhrDocument } from '@doctolib/tpf-national-health-records' 3 import type { ReactNode } from 'react' 4
5 export type NhrPatientInfo = { 6 fullName: string 7 gender: 'male' | 'female' | 'other' 8 birthDate: string 9 age: number 10 } 11
12 export type ColumnConfig = { 13 key: string 14 header: string 15 sortable: boolean 16 /** Only required when sortable: true. Returns a string for lo …(truncated, 2274 more chars)

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentList.tsx (1–100)

Tool results:

→ result (ok): 1 import { getPagedData } from '#utils/nhrPaginationHelpers' 2 import { SpinnerLoader } from '@doctolib/design-system/SpinnerLoader' 3 import type { NhrDocument } from '@doctolib/tpf-national-health-records' 4 import { useMemo, useState } from 'react' 5
6 import type { ActionConfig, ColumnConfig, FilterConfig, NhrPatientInfo } from '../../types' 7 import { NhrDocumentListFilterPanel } from '../NhrDocumentListFilterPanel/NhrDocumentListFilterPanel' 8 import { NhrDocumentListHeader } from '../Nhr …(truncated, 3113 more chars)

Tools used:

  • Bash: grep -r "StatusOption\|FilterConfig\|ColumnConfig\|ActionConfig" /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts | head -20

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts:export type ColumnConfig = { /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts:/* Passed to every FilterConfig.render() — country variant casts to its own patient type / /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/types.ts:export type StatusOption = { /Users/USER/workspace/doctolib/treatment-plan/packag …(truncated, 518 more chars)

Now let me check the i18n test and look at other packages for patterns:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/i18n.test.ts

Tool results:

→ result (ok): 1 import { beforeEach, describe, expect, it } from 'vitest' 2
3 import { changeLanguage, t } from './i18n' 4
5 describe('i18n tests', () => { 6 beforeEach(async () => { 7 await changeLanguage('en') 8 }) 9
10 it('should return missing translation', () => { 11 const unknownKey = 'unknown.key' 12 expect(t(unknownKey)).toBe(unknownKey) 13 }) 14
15 it('should return the entry point open label', () => { 16 expect(t('tpf_national_health_records_ui.entry_point.open')).toBe( …(truncated, 625 more chars)

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/treatment-plan/packages -maxdepth 2 -name "i18n.json" -o -name "i18n.ts" | head -20

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-ti-components/i18n.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-nhr-fr/i18n.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/i18n.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-therapy-prescriptions/i18n.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-muster-forms/i18n.json /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-prescription- …(truncated, 1215 more chars)

Let me check another package to see the i18n patterns and look at one more component example:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-commons/i18n.json

Tool results:

→ result (ok): 1 { 2 "projectIDs": ["0965d2af05c26d3439c7ebf078fb684d"], 3 "namespaces": ["tpf_commons"], 4 "outputPath": "packages/tpf-commons/src/locales", 5 "locales": ["en", "de", "fr", "it"] 6 } 7

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPointButton/NhrEntryPointButton.tsx

Tool results:

→ result (ok): 1 import { Badge } from '@doctolib/design-system/Badge' 2 import { IconButton } from '@doctolib/design-system/IconButton/v2' 3
4 import { t } from '../../i18n' 5
6 const NEW_DOCUMENTS_COUNT_LIMIT = 99 7
8 const formatNewDocumentsCount = (newDocumentsCount: number) => 9 newDocumentsCount > NEW_DOCUMENTS_COUNT_LIMIT ? '99+' : newDocumentsCount 10
11 export type NhrEntryPointButtonProps = { 12 newDocumentsCount?: number 13 onClick: () => void 14 } 15
16 export const NhrEntryPointButton = …(truncated, 532 more chars)

Tools used:

  • Bash: grep -r "export type.*Props" /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components --include="*.tsx" | head -5

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentList.tsx:export type NhrDocumentListProps = { /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentVisibilityFilter/NhrDocumentVisibilityFilter.tsx:export type NhrDocumentVisibilityFilterProps = { /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/N …(truncated, 450 more chars)

Perfect! Now let me check a factory function to understand how labels are currently handled:

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentStatusFilterConfig.ts

Tool results:

→ result (ERROR): File does not exist. Note: your current working directory is /Users/USER/workspace/doctolib. Did you mean createNhrDocumentStatusFilterConfig.tsx?

Tools used:

  • Bash: head -50 /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrStatusColumn.ts

Tool results:

→ result (ERROR): Exit code 1 head: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/columns/createNhrStatusColumn.ts: No such file or directory

Let me find the actual files:

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories -type f -name "*.ts" -o -name "*.tsx" | head -10

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDateSelectionFilterConfig.tsx /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentStatusFilterConfig.test.tsx /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentCategoryFilterConfig.tsx /Users/USER/workspace/d …(truncated, 1084 more chars)

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/locales/en/tpf_national_health_records_ui.json

Tool results:

→ result (ok): File unchanged since last read. The content from the earlier Read tool_result in this conversation is still current — refer to that instead of re-reading.

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/business/factories/filters/createNhrDocumentStatusFilterConfig.tsx

Tool results:

→ result (ok): 1 import { NhrDocumentStatusFilter } from '../../../components/NhrDocumentList/NhrDocumentStatusFilter/NhrDocumentStatusFilter' 2 import type { FilterConfig, StatusOption } from '../../../types' 3
4 export const createNhrDocumentStatusFilterConfig = (statuses: StatusOption[], label: string): FilterConfig => ({ 5 key: 'documentStatus', 6 render: (filters, onChange) => ( 7 <NhrDocumentStatusFilter 8 label={label} 9 statuses={statuses} 10 value={statuses.filter((s) => fil …(truncated, 158 more chars)

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrDocumentList/NhrDocumentStatusFilter/NhrDocumentStatusFilter.tsx

Tool results:

→ result (ok): 1 import { Checkbox } from '@doctolib/design-system/Checkbox/v2' 2 import { Heading } from '@doctolib/design-system/Heading' 3
4 import type { NhrDocumentStatusFilterProps } from '../../../types' 5
6 export const NhrDocumentStatusFilter = ({ label, statuses, value, onChange }: NhrDocumentStatusFilterProps) => ( 7 <> 8 <Heading level='h5'>{label}</Heading> 9 <div className='flex flex-col'> 10 {statuses.map((status) => ( 11 <Checkbox 12 key={status.filterKey} 13 …(truncated, 327 more chars)

Perfect! Now let me check the storybook setup to understand how translations work there:

Tools used:

  • Bash: find /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/.storybook -type f 2>/dev/null | head -10

Tool results:

→ result (ok): /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/.storybook/main.ts /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/.storybook/preview.tsx /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/.storybook/preview.css /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/.storybook/public/mockServiceWorker.js /Users/USER/workspace/doctolib/treatment-plan/packag …(truncated, 61 more chars)

Tools used:

  • Read: /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/src/components/NhrEntryPoint/NhrEntryPoint.stories.tsx (1–80)

Tool results:

→ result (ok): 1 import type { NhrDocument } from '@doctolib/tpf-national-health-records' 2 import type { Meta, StoryObj } from '@storybook/react' 3
4 import type { FilterConfig, NhrPatientInfo } from '../../types' 5 import { NhrEntryPoint } from './NhrEntryPoint' 6 import { nhrDocumentListColumns } from './nhrDocumentListColumns' 7
8 const samplePatient: NhrPatientInfo = { 9 fullName: 'Camille Devailly', 10 gender: 'female', 11 birthDate: '1990-06-15', 12 age: 34, 13 } 14
15 const sampleDocuments: …(truncated, 2096 more chars)

Excellent! Now I have all the information I need. Let me create a comprehensive summary report.

Summary of Findings

1. I18N Setup Status: ALREADY ESTABLISHED

The package already has comprehensive i18n infrastructure in place:

  • i18n.json exists at /Users/USER/workspace/doctolib/treatment-plan/packages/tpf-national-health-records-ui/i18n.json with:
  • Phrase project ID: 0965d2af05c26d3439c7ebf078fb684d
  • Namespace: tpf_national_health_records_ui
  • Locales: en, fr
  • Output path: packages/tpf-national-health-records-ui/src/locales

  • i18n.ts at /src/i18n.ts:

  • Imports i18n from @doctolib/tpf-commons/i18n (centralized i18n management)
  • Registers namespace via i18n.registerNamespace()
  • Exports t() function and changeLanguage() for use throughout the package

  • Translation files:

  • /src/locales/en/tpf_national_health_records_ui.json (English source)
  • /src/locales/fr/tpf_national_health_records_ui.json (French)
  • Both pulled from Phrase (managed externally, not hand-edited)

  • loadNamespace.ts at /src/locales/loadNamespace.ts:

  • Static imports with language-based switch statement (Vite-friendly)
  • Supports both en and fr locales
  • Fallback to English for unsupported languages

  • Tests at /src/i18n.test.ts:

  • Tests verify translation key loading for both languages
  • Pattern matches documentation guidelines

2. Component Props Definition: MIXED APPROACH

Component props are defined with:

Hardcoded strings (most components): - Labels passed as props to child components - Parent components responsible for providing text - Example: NhrDocumentStatusFilter accepts label prop as string - Factory functions like createNhrDocumentStatusFilterConfig() accept label parameter

Type-safe prop interfaces: - All components have TypeScript interfaces - Example types exported: - ColumnConfig - table columns with header: string - FilterConfig - filter definitions with render function - ActionConfig - action buttons with tooltip: string - StatusOption - status filters with label: string - VisibilityOption - visibility filters with label: string - NhrDocumentStatusFilterProps - component props including label: string

Where strings are currently used: - NhrEntryPointButton: Uses t('tpf_national_health_records_ui.entry_point.open') for tooltip - Component signatures accept string props that are then rendered


3. Public API (index.ts exports)

The package exports a comprehensive public API:

Main Components: - NhrDocumentList - NhrDocumentListFilterPanel - NhrEntryPoint - NhrDocumentVisibilityFilter

Factory Functions (for creating configurations): - createNhrStatusColumn() - createNhrSharedByColumn() - createNhrProcedureDateColumn() - createNhrDocumentCategoryColumn() - createNhrDocumentCategoryFilterConfig() - createNhrDateSelectionFilterConfig() - createNhrShareDateColumn() - createNhrDocumentNameColumn() - createNhrVisibilityColumn() - createNhrDocumentStatusFilterConfig() - createNhrDocumentVisibilityFilterConfig() - createViewDocumentAction() - createMoreActionsAction()

Type Exports: - ActionConfig, ActionsFactory, ColumnConfig, FilterConfig, FilterRenderContext - NhrPatientInfo, NhrVisibilityEntry, StatusOption, NhrDocumentStatusFilterProps, VisibilityOption - SearchDocumentsFn - DateMode


4. Testing Patterns

Test structure: - Vitest (frontend test runner) - React Testing Library for component testing - Colocated test files: *.test.tsx alongside component files - Storybook stories: *.stories.tsx for visual documentation and interaction testing

i18n testing: - src/i18n.test.ts verifies namespace loading and translation keys - Tests use changeLanguage() to switch locales - Pattern: t('tpf_national_health_records_ui.section.key')

Component test patterns: - Use setup() from @doctolib/test-helpers (pre-configured userEvent) - MSW mocking available via @storybook/experimental-addon-test for Storybook tests - CSS Modules for component styling with type generation


5. Package.json Dependencies

i18n-related dependencies: - i18next-browser-languagedetector ^8.2.1 (in dependencies) - @doctolib/tpf-commons 3.0.1 (provides centralized i18n service)

Dev dependencies for i18n testing: - storybook-react-i18next ^3.3.1 (Storybook i18n addon)

No direct i18n library like react-i18next or i18next - uses Doctolib's centralized solution via @doctolib/tpf-commons/i18n


6. Other Packages I18N Patterns (Reference)

Explored i18n configurations from sibling packages. All follow the same pattern:

  • tpf-commons: Centralized i18n service (project ID: same as NHR)
  • tpf-therapy-prescriptions: German-only (["en", "de"])
  • tpf-diga-fulfillments: German-only (["en", "de"])
  • tpf-french-teleservices: French-specific features
  • tpf-muster-forms, tpf-rich-texts, tpf-hand-letters: All use same Phrase-managed approach

Key pattern: Phrase is the source of truth. Translation files are auto-pulled via GitHub Actions workflows (i18n-sync.yml, i18n-create-auto-pr.yml). Developers add labels to Phrase, then PR is labeled i18n to pull translations.


7. Current Translation Keys in Package

From /src/locales/en/tpf_national_health_records_ui.json:

{
  "entry_point.open": "Open NHR",
  "filters.date_selection.custom_range.label": "Custom date range",
  "filters.date_selection.last_access.label": "Since I last accessed this DMP",
  "filters.date_selection.last_access.message": "Last accessed on:",
  "translation": "Translation"
}

Minimal set - only 5 keys. Most UI labels are currently passed as props.


Key Files:

  • i18n configuration: /packages/tpf-national-health-records-ui/i18n.json
  • i18n exports: /packages/tpf-national-health-records-ui/src/i18n.ts
  • i18n loader: /packages/tpf-national-health-records-ui/src/locales/loadNamespace.ts
  • Translation files: /packages/tpf-national-health-records-ui/src/locales/{en,fr}/tpf_national_health_records_ui.json
  • Types: /packages/tpf-national-health-records-ui/src/types.ts
  • Package config: /packages/tpf-national-health-records-ui/package.json
  • Index/API: /packages/tpf-national-health-records-ui/src/index.ts

Keyboard shortcuts

⌘K / Ctrl+KOpen command palette
/Focus search
g hGo to home
g pGo to projects
g sGo to sessions
j / kNext / prev row (tables)
?Show this help
EscClose dialogs

Structured queries

Mix key:value filters with free text in the palette:

type:sessionOnly session pages
project:llm-wikiFilter by project name (substring)
model:claudeFilter by model name (substring)
date:>2026-03-01Sessions after a date
date:<2026-04-01Sessions before a date
tags:rustPages mentioning a tag/topic
sort:dateSort results by date (newest first)

Example: type:session project:llm-wiki date:>2026-04 sort:date