You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* feat(i18n): add internationalization support with English translations
- Implemented i18n context and provider for translation management.
- Added English translations for various components and sections.
- Updated components to utilize the translation function for dynamic text.
- Modified layout files to support locale-based rendering.
- Removed hardcoded strings in favor of translation keys for better localization.
* feat: add more text to i18n and explain how to make a new language
* feat(i18n): add support for non-standard locales and update documentation
Copy file name to clipboardExpand all lines: README.md
+99Lines changed: 99 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,6 +28,105 @@ bun run dev
28
28
29
29
Note: I added [remark-mermaid](https://github.com/temando/remark-mermaid) into utils and slightly modified it so that it is always simple mode and always returns a `pre` + `<div class="mermaid"></div>`. This allows mermaid code blocks to be included.
30
30
31
+
# Adding a New Language
32
+
33
+
UI strings live in `src/i18n/locales/` and are served via a pure Preact context — no external i18n library required. Adding a new locale takes 3 steps:
34
+
35
+
## 1. Create the locale file
36
+
37
+
Copy `src/i18n/locales/en.ts` to a new file, e.g. `src/i18n/locales/es.ts`. Translate all string values. The key structure must stay identical.
In `src/i18n/context.tsx`, import the new locale and add it to the `locales` map:
53
+
54
+
```ts
55
+
importenfrom"~/i18n/locales/en";
56
+
importesfrom"~/i18n/locales/es"; // add
57
+
58
+
const locales:Record<string, Translation> = { en, es }; // add es
59
+
```
60
+
61
+
## 3. Add it to Astro and create the page
62
+
63
+
In `astro.config.mjs`, add the locale code to the `locales` array:
64
+
65
+
```js
66
+
i18n: {
67
+
locales: ["en", "es"], // add "es"
68
+
defaultLocale:"en",
69
+
routing: { prefixDefaultLocale:false },
70
+
},
71
+
```
72
+
73
+
Then create `src/pages/es/index.astro` (mirroring `src/pages/index.astro`). Astro will set `Astro.currentLocale` to `"es"` for that page, which flows through the layout's `locale` prop into `I18nProvider` — all components then resolve strings from the new locale automatically.
74
+
75
+
> **Note on islands**: All home-page sections are grouped inside `<HomeSections locale={...} client:visible />`, which wraps them in a single `I18nProvider`. Each Astro `client:*` island is an isolated Preact tree, so any new island components that use `useTranslation()` must also receive `locale` and render inside an `I18nProvider`.
76
+
77
+
## Non-standard / fun locales
78
+
79
+
For locales that aren't real BCP 47 language codes (e.g. a "backward" locale that reverses all strings for testing), use Astro's locale **object syntax** to decouple the URL path from the `lang` attribute:
80
+
81
+
```js
82
+
// astro.config.mjs
83
+
i18n: {
84
+
locales: [
85
+
"en",
86
+
{ path:"backward", codes: ["en-x-backward"] },
87
+
],
88
+
defaultLocale:"en",
89
+
routing: { prefixDefaultLocale:false },
90
+
},
91
+
```
92
+
93
+
-**`path`** — the URL segment (`/backward/`)
94
+
-**`codes`** — what goes in `<html lang="...">`. Using `en-x-backward` is a valid BCP 47 private-use extension: screen readers treat it as English while still accurately describing the variant.
95
+
96
+
Because `Astro.currentLocale` resolves to the first entry in `codes` (`"en-x-backward"`), you must pass `locale` explicitly in the page rather than relying on `Astro.currentLocale`:
The current approach (one folder per locale, e.g. `src/pages/es/index.astro`) works but doesn't scale — each new locale requires duplicating every page file.
115
+
116
+
The better long-term solution is to use a dynamic `[locale]` route with `getStaticPaths` so a single file generates all locale variants:
0 commit comments