Skip to main content

Locale data

Static site data for each locale is grouped into two general categories: the "global" data and the "page" data. Global data refers to site-wide content—things like navigation menus, footers, and so on—while page data refers to page-specific content—things like a homepage header, or a biography for an "about" page.

All static locale data lives within the /src/locales/ directory, and is grouped into these two categories. You can treat the globals directory as a reserved directory name, as all global (site-wide) data is compiled from within it. All other directories here, however, are page-level data directories which should match each page's filename as it exists in the /src/pages/ directory.

Within both /src/locales/globals/ and /src/locales/<page-name>/, should live YAML files containing the actual locale data. Each YAML file's name should be the locale string as specified in the locale config, with a .yml extension, except for the index.yml file, which is a special case for each directory (more on that below).

Here is an example file tree, containing global data as well as data for two pages—all containing content for three locales:

.
└── src/
└── locales/
├── globals/
│ ├── en.yml
│ ├── es.yml
│ ├── fr.yml
│ └── index.yml
├── home/
│ ├── en.yml
│ ├── es.yml
│ ├── fr.yml
│ └── index.yml
└── features/
├── en.yml
├── es.yml
└── fr.yml

Locale data compilation

Under the hood, all of these files get compiled into two objects—globals and page—and are then passed to each page as props. This process is done via Next JS' getStaticProps convention. The useLocale hook is a convenient way to work with this data from any functional React component in your project.

globals example

An example globals YAML file for the "en" locale:

meta:
title: My Cool Web App
description: The site-wide meta description.
og_alt: Description of the og image.

nav:
label: Main site navigation
items:
- id: home
label: Home
- id: features
label: Product Features
- id: contact
label: Get in touch

footer: © Company Name.

As mentioned, that data gets compiled into a page-level prop called globals, for the current page and locale. Here's an example that uses that data (via useLocale) from within an imaginary <Navigation /> component:

import { useLocale } from "@local/hooks"

const Navigation = () => {
const { globals } = useLocale()

return (
<nav aria-labelledby="nav-label">
<span id="nav-label" className="visually-hidden">{globals.nav.label}</span>
<ul>
{globals.nav.items.map(item => (
<li key={item.id}>{item.label}</li>
)}
</ul>
</nav>
)
}

export default Navigation

page example

An example "Product Features" page YAML file for the "en" locale:

meta:
title: Product Features
description: Our product is pretty cool. It does cool things.

features:
- id: 897213
image: path-to-some-image.jpg
image_alt: Description of image goes here.
description: Laborum sint ut mollit proident quis do proident ex laboris sint nisi.
- id: 216357
image: path-to-some-other-image.jpg
image_alt: Description of image goes here.
description: Consequat ea fugiat irure do magna fugiat ex minim aute proident ullamco.
- id: 187236
image: path-to-yet-another-image.jpg
image_alt: Description of image goes here.
description: Magna in laborum aliquip exercitation est est est.

This data gets compiled into a page-level prop called page, for the current page and locale. Here's an example that uses that data (via useLocale) from within an imaginary <FeatureList> component:

import { useLocale } from "@local/hooks";

const FeatureList = ({}) => {
const { page } = useLocale();

return (
<ul>
{page.features.map((feature) => (
<li key={feature.id}>
<img src={feature.image} alt={featue.image_alt} />
<span>{feature.description}</span>
</li>
))}
</ul>
);
};

export default FeatureList;

index.yml example

Each directory within /src/locales/ can contain an index.yml. If inside global/ its data will be available as part of the globals scope mentioned above, otherwise it will be part of the page scope.

If inside a page locale directory, the data will be available for all locales, but those can still overwrite that data.

Let's say you have a list of downlodable PDFs that you want to display on the footer of your site. These PDFs are in english for all locales except for fr. You can define the list in the index.yml file and then overwrite it for the fr locale instead of having to define it for each locale.

downloads:
- path-to-pdf-1.pdf
- path-to-pdf-2.pdf
- path-to-pdf-3.pdf
downloads:
- fr/path-to-pdf-1.pdf
- fr/path-to-pdf-2.pdf
- fr/path-to-pdf-3.pdf

The data is then merged and is available in the globals scope.

import { useLocale } from "@local/hooks";

const Footer = ({}) => {
const { globals: { downloads } } = useLocale();

return (
<ul>
{downloads.map((path, i) => (
<li key={i}>
<a href={path} download><Icon id="download" /></a>
</li>
))}
</ul>
);
};

export default Footer;