I just implemented localization/internationalization on another Astro site. Some notes.
Config
export default defineConfig({
//...
i18n: {
defaultLocale: "en",
locales: ["en", "fr", "ja"],
},
});
File Architecture
A [locale] directory at the root of everything. / redirects to /en.
UI Strings
I implemented a <T/> component:
---
import { getString } from "../content";
const { k, fallback } = Astro.props;
const locale = Astro.currentLocale;
const { t } = getString(k, { fallback, locale });
---
<span data-key={k}>{t || fallback || k}</span>
And a getString() function:
import en from "./locales/en.yml";
import fr from "./locales/fr.yml";
import ja from "./locales/ja.yml";
const locales = { en, fr, ja } as Record<string, typeof en>;
export const getString = (
k: string,
options: {
fallback?: string;
locale?: string;
} = {},
) => {
const { count, fallback = k, locale = "en" } = options;
const strings = locales[locale] ?? en;
const s = strings.find((s) => s.key === k) ?? en.find((s) => s.key === k);
let t = s?.t || fallback;
return { t };
};
Usage: <T k="tagline" />
YAML content
Another use case is having translated content inside YAML files, JSON API data, etc. I added a second component for that:
---
// content is an object containing {en, ja, fr, etc.} fields
const { content } = Astro.props;
const locale = Astro.currentLocale;
---
<span>{content[locale]}</span>
Usage: <T2 content={description_i18n} />
Pages
Finally, a third use case is .mdx, .md, etc. pages that have their own file. Here's a third component:
---
const { file } = Astro.props;
const locale = Astro.currentLocale;
const { default: File } = await import(`../mdx/${locale}/${file}.mdx`);
---
<div><File /></div>
Usage: <T3 file="About" />
I just implemented localization/internationalization on another Astro site. Some notes.
Config
File Architecture
A
[locale]directory at the root of everything./redirects to/en.UI Strings
I implemented a
<T/>component:And a
getString()function:Usage:
<T k="tagline" />YAML content
Another use case is having translated content inside YAML files, JSON API data, etc. I added a second component for that:
Usage:
<T2 content={description_i18n} />Pages
Finally, a third use case is
.mdx,.md, etc. pages that have their own file. Here's a third component:Usage:
<T3 file="About" />