Skip to content

Notes about i18n with Astro #128

Description

@SachaG

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" />

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions