Skip to content

Commit 374b7ea

Browse files
committed
docs(mosaic): document how localization keys are named and placed
1 parent fa5bd1b commit 374b7ea

3 files changed

Lines changed: 30 additions & 4 deletions

File tree

‎.changeset/mosaic-localization-key-tree.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@
22
'@clerk/mosaic': minor
33
---
44

5-
Reorganize localization keys under the component they belong to. Section and dialog strings now nest under their component instead of sitting at the top level, for example `userProfileMfa.label` is now `userProfile.mfa.label`, `membersTableTab.title` is now `organizationProfile.members.list.title`, and `apiKeysTable.search` is now `apiKeys.search`. Email and phone strings moved from `userProfileContact.email` and `userProfileContact.phone` to `userProfile.email` and `userProfile.phone`. Update any `localization` overrides that use the old keys; TypeScript flags each one.
5+
Reorganize localization keys under the component they belong to. Section and dialog strings now nest under their component instead of sitting at the top level, for example `userProfileMfa.label` is now `userProfile.mfa.label`, `membersTableTab.title` is now `organizationProfile.members.list.title`, and `apiKeysTable.search` is now `apiKeys.search`. Email and phone strings moved from `userProfileContact.email` and `userProfileContact.phone` to `userProfile.email` and `userProfile.phone`. Reverification keys now use plain names, for example `reverification.alternativeMethods.blockButton__password` is now `reverification.methods.password` and `reverification.formButtonPrimary` is now `reverification.continue`; keys no reverification screen rendered were removed. Update any `localization` overrides that use the old keys; TypeScript flags each one.

‎packages/mosaic/ARCHITECTURE.md‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,19 @@ so a consumer's overrides type-check against the real keys, as a dot path
245245
Renaming or moving a key breaks every override that names it; treat it like renaming
246246
a prop.
247247

248+
The key tree follows what the user sees, so a key can be found from the screen:
249+
250+
- A root is a public component (`userProfile`) or a shared block (`form`, `errors`).
251+
There is no `common` root. The same English in two components is two keys,
252+
because a translation may need to differ by context.
253+
- Below the root, keys nest by section, then by the dialog or step inside it:
254+
`userProfile.email.addDialog`, `userProfile.email.removeDialog`.
255+
- Copy that several views render through one shared component belongs to that
256+
component (`userProfile.contact` for the row both email and phone use).
257+
- Every segment is camelCase. A map keyed by data ids (`errors`, `roles`,
258+
`userProfile.mfa.methods`) keeps the ids as its keys;
259+
`src/localization/__tests__/registry.test.ts` lists those maps and checks the rest.
260+
248261
### Composition
249262

250263
Two shapes, chosen by whether the slice fetches its own data.

‎packages/mosaic/docs/views.md‎

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,26 @@ Every string a view renders comes from the feature's `*.messages.ts`, shaped the
4848
way `@clerk/i18n` takes a base definition. A plural message is its forms; a
4949
parameterized one is its template.
5050

51-
Register the file as a namespace in `src/localization/registry.ts`, then read it
52-
with `useMessages` in the view or controller that renders it:
51+
To add copy for a new section, step or dialog:
52+
53+
1. Put the strings in the `*.messages.ts` next to the view that renders them. Name
54+
each key for what the string is (`label`, `resend`, `confirm`), not where it
55+
sits in the markup.
56+
2. Mount the object in `src/localization/registry.ts` under the public component
57+
the user sees it in: a section of `UserProfile` goes at `userProfile.<section>`,
58+
and a dialog inside it at `userProfile.<section>.addDialog` or `.removeDialog`.
59+
Copy two views share goes under the component that renders it, never under a
60+
new `common` root.
61+
3. Read it with `useMessages` and the root, in the view or controller that
62+
renders it:
5363

5464
```tsx
55-
const m = useMessages('userButton');
65+
const m = useMessages('userProfile').mfa;
5666
```
5767

68+
The rules behind these steps are in [ARCHITECTURE.md](../ARCHITECTURE.md), and
69+
`src/localization/__tests__/registry.test.ts` fails on a key that is not camelCase.
70+
5871
Never import a `*.messages.ts` directly. A direct import skips the customer's
5972
locale and overrides, so the copy can't be localized.
6073

0 commit comments

Comments
 (0)