ops: prepare for internationalization without shipping translations (… - #97
Open
Josetic224 wants to merge 5 commits into
Open
ops: prepare for internationalization without shipping translations (…#97Josetic224 wants to merge 5 commits into
Josetic224 wants to merge 5 commits into
Conversation
Contributor
|
@Josetic224, ci pipeline failed |
Author
|
I'll work on it now |
Contributor
|
@Josetic224, ci failed |
Contributor
|
Also having some conflicts |
… from expected-pages
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #80
What this does
Preparation for i18n — no translations are shipped, English is the only active locale. The goal is to make adding a second locale a well-scoped task rather than a cross-codebase retrofit.
Changes
Message catalogue (
lib/i18n/messages/en.ts)Every user-facing string is extracted into a single file with stable, namespaced keys. Keys are a contract — they can be added freely but renaming requires a deprecation period so translation tooling does not break.
Locale infrastructure (
lib/i18n/index.ts)getMessages()for Server Components and API routesuseMessages()for Client ComponentsresolveLocale()— returns"en"now, reads from request headers/middleware when a second locale lands. No call sites change.LOCALE_META— maps locale →{ dir, label }for<html lang dir>and RTL supportIntl formatters (
lib/i18n/formatters.ts)Replaces every hardcoded locale format call. No locale tag is ever hardcoded at a call site.
formatNumber(n)n.toLocaleString(),new Intl.NumberFormat("en-US")formatCompact(n)new Intl.NumberFormat("en-US", { notation: "compact" })formatTime(date)new Date().toLocaleTimeString()formatDate(date)formatCurrency(n, currency)interpolate(template, values)The currency formatter is included specifically because
1,000.50vs1.000,50is a correctness problem in a billing product, not just a cosmetic one.HTML shell (
app/layout.tsx)<html lang={locale} dir={dir}>— both attributes derived fromLOCALE_META. RTL locales work by adding one entry to the map.Layout hardening
Audited all layouts against 30–40% longer strings (German, Finnish worst-case):
repeat(3, 1fr)→repeat(3, minmax(0, 1fr))— prevents label overflow in narrow columnscharts.module.css):white-space: nowrapscoped to value cells only; row-header cells (which carry translated labels) now wrapglobals.css):brandgetsflex-shrink: 0;linksgetsmin-width: 0so the link list wraps before overflowingAll pages and components updated
All JSX strings replaced with catalogue lookups. No user-visible string change in English.
How to add a new locale later
lib/i18n/messages/<locale>.tswith the same shape asen.tsLocaleunion andLOCALE_METAinlib/i18n/index.tsresolveLocale()to read from middleware/request headersThat is the complete addition path. No call sites in components or pages change.
Acceptance criteria from #80
IntlTesting
npm run buildpasses with zero TypeScript errors and all 14 pages generated statically.EOF
)"