The problem
The app is English-only, hardcoded. Every string is written inline in the component that shows it — roughly 308 <Text> elements, 33 placeholder/label/title props and 38 toasts across 117 files. There is no i18n library, no locale files, and app.json declares no localizations.
A large part of the crew is Brazilian and does not read English comfortably. They are the people most likely to be onboarded by a friend rather than by choice, which makes English the first wall they hit — right at signup, where the copy explains keys, lite accounts and a blockchain.
Priority: pt-BR first, then Spanish, then whatever the crew asks for.
What makes this app harder than a normal i18n pass
The copy has a voice, and the voice is the point. about.tsx and the onboarding coach (#68) are deliberately raw and a bit sweary. Run through machine translation they come out as a bank's terms of service — technically correct, and they lose exactly the thing that makes someone feel this app is theirs. These strings need a skater translating, not a model.
Some strings never reach the bundle. API errors are surfaced straight to the user (r.error in app/email-login.tsx, plus the toasts in lib/posting.ts), and they arrive in English from the server. Translating the app leaves those in English unless the API returns codes instead of sentences — which is a skatehive-api change, not a mobile one. Worth deciding early whether they stay English or the backend gets error codes.
Time strings are hand-built. formatTimeAbbreviated in components/Feed/PostCard.tsx concatenates 2h, 3d, 5mo. Those are not translations, they are a format — Intl.RelativeTimeFormat handles this correctly per locale and is already available in Hermes.
Shape
expo-localization for the device locale, plus a light runtime (i18n-js is enough — no need for a compiler-based library at this size).
- Strings move to
locales/en.json / locales/pt-BR.json, keyed by screen.
- A language picker in Settings, because the device locale is often wrong for people who bought a phone secondhand or keep it in English on purpose. Device locale as the default, not as the verdict.
app.json gets the localizations so the App Store listing and the permission prompts follow.
Not this
A big-bang PR translating all 117 files at once, which is unreviewable and blocks on the whole translation being ready. Screen by screen, starting with the ones a new user sees first: login, onboarding, profile, about.tsx.
Suggested label: enhancement
The problem
The app is English-only, hardcoded. Every string is written inline in the component that shows it — roughly 308
<Text>elements, 33placeholder/label/titleprops and 38 toasts across 117 files. There is no i18n library, no locale files, andapp.jsondeclares no localizations.A large part of the crew is Brazilian and does not read English comfortably. They are the people most likely to be onboarded by a friend rather than by choice, which makes English the first wall they hit — right at signup, where the copy explains keys, lite accounts and a blockchain.
Priority: pt-BR first, then Spanish, then whatever the crew asks for.
What makes this app harder than a normal i18n pass
The copy has a voice, and the voice is the point.
about.tsxand the onboarding coach (#68) are deliberately raw and a bit sweary. Run through machine translation they come out as a bank's terms of service — technically correct, and they lose exactly the thing that makes someone feel this app is theirs. These strings need a skater translating, not a model.Some strings never reach the bundle. API errors are surfaced straight to the user (
r.errorinapp/email-login.tsx, plus the toasts inlib/posting.ts), and they arrive in English from the server. Translating the app leaves those in English unless the API returns codes instead of sentences — which is askatehive-apichange, not a mobile one. Worth deciding early whether they stay English or the backend gets error codes.Time strings are hand-built.
formatTimeAbbreviatedincomponents/Feed/PostCard.tsxconcatenates2h,3d,5mo. Those are not translations, they are a format —Intl.RelativeTimeFormathandles this correctly per locale and is already available in Hermes.Shape
expo-localizationfor the device locale, plus a light runtime (i18n-jsis enough — no need for a compiler-based library at this size).locales/en.json/locales/pt-BR.json, keyed by screen.app.jsongets the localizations so the App Store listing and the permission prompts follow.Not this
A big-bang PR translating all 117 files at once, which is unreviewable and blocks on the whole translation being ready. Screen by screen, starting with the ones a new user sees first: login, onboarding, profile,
about.tsx.Suggested label:
enhancement