Skip to content

Commit 405cf9f

Browse files
committed
Add i18n and 10n with lingui and babel
1 parent 18bdb89 commit 405cf9f

File tree

16 files changed

+9511
-5501
lines changed

16 files changed

+9511
-5501
lines changed

.babelrc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"presets": [
3+
"next/babel"
4+
],
5+
"plugins": ["@lingui/babel-plugin-lingui-macro"]
6+
}

lingui.config.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
const nextConfig = require('./next.config')
2+
3+
console.log('nextConfig', nextConfig)
4+
5+
/** @type {import('@lingui/conf').LinguiConfig} */
6+
module.exports = {
7+
locales: nextConfig.i18n.locales,
8+
pseudoLocale: 'pseudo',
9+
sourceLocale: nextConfig.i18n.defaultLocale,
10+
fallbackLocales: {
11+
default: 'en',
12+
},
13+
catalogs: [
14+
{
15+
path: 'src/locales/{locale}/messages',
16+
// path: 'src/locales/{locale}',
17+
include: ['src/'],
18+
},
19+
],
20+
}

next.config.mjs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,10 @@ export default withMDX({
1818
images: {
1919
domains: ["raw.githubusercontent.com", "numpy.org", "dask.org", "chainer.org", ],
2020
},
21+
i18n: {
22+
// These are all the locales you want to support in
23+
// your application
24+
locales: ["en", "es", "pt"],
25+
defaultLocale: "en",
26+
},
2127
})

package.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
"private": true,
55
"scripts": {
66
"build-cards": "node build-cards.js",
7+
"extract": "lingui extract",
8+
"compile": "lingui compile",
79
"dev": "next dev",
8-
"build": "next build",
10+
"build": "yarn extract && next build",
911
"start": "next start",
1012
"lint": "next lint"
1113
},
@@ -24,6 +26,8 @@
2426
"@emotion/styled": "^11.13.0",
2527
"@fontsource-variable/inter": "^5.2.5",
2628
"@giscus/react": "^3.0.0",
29+
"@lingui/core": "^5.0.0-next.2",
30+
"@lingui/react": "^5.0.0-next.2",
2731
"@mdx-js/loader": "^3.0.1",
2832
"@mdx-js/react": "^3.0.1",
2933
"@next/mdx": "^14.2.14",
@@ -46,6 +50,9 @@
4650
"swr": "^2.2.5"
4751
},
4852
"devDependencies": {
53+
"@lingui/babel-plugin-lingui-macro": "^5.0.0-next.2",
54+
"@lingui/cli": "^5.0.0-next.2",
55+
"@lingui/loader": "^5.0.0-next.2",
4956
"@types/react": "^18.3.11",
5057
"eslint": "^9.12.0",
5158
"eslint-config-next": "14.2.14",

src/components/layout.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { Header } from '@/components/header'
44
import { Link } from '@/components/mdx'
55
import { Box, Flex } from '@chakra-ui/react'
66
import Head from 'next/head'
7+
import { Trans, useLingui } from '@lingui/react/macro'
8+
import { useRouter } from 'next/router'
79

810
export const Layout = ({
911
title,
@@ -13,7 +15,15 @@ export const Layout = ({
1315
url = 'https://xarray.dev',
1416
enableBanner = false,
1517
}) => {
16-
const bannerTitle = 'Check out the new blog post on DataTree!'
18+
/**
19+
* This macro hook is needed to get `t` which
20+
* is bound to i18n from React.Context
21+
*/
22+
const { t } = useLingui()
23+
const router = useRouter()
24+
const { pathname, asPath, query } = router
25+
26+
const bannerTitle = t`Check out the new blog post on DataTree!`
1727
const bannerDescription = ''
1828
const bannerChildren = (
1929
<Link href='/blog/datatree'>

src/i18n.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { i18n, Messages } from '@lingui/core'
2+
import { useRouter } from 'next/router'
3+
import { useEffect } from 'react'
4+
5+
/**
6+
* Load messages for requested locale and activate it.
7+
* This function isn't part of the LinguiJS library because there are
8+
* many ways how to load messages — from REST API, from file, from cache, etc.
9+
*/
10+
export async function loadCatalog(locale: string) {
11+
const catalog = await import(`@lingui/loader!./locales/${locale}/messages.po`)
12+
return catalog.messages
13+
}
14+
15+
export function useLinguiInit(messages: Messages) {
16+
const router = useRouter()
17+
const locale = router.locale || router.defaultLocale!
18+
const isClient = typeof window !== 'undefined'
19+
20+
if (!isClient && locale !== i18n.locale) {
21+
// there is single instance of i18n on the server
22+
// note: on the server, we could have an instance of i18n per supported locale
23+
// to avoid calling loadAndActivate for (worst case) each request, but right now that's what we do
24+
i18n.loadAndActivate({ locale, messages })
25+
}
26+
if (isClient && !i18n.locale) {
27+
// first client render
28+
i18n.loadAndActivate({ locale, messages })
29+
}
30+
31+
useEffect(() => {
32+
const localeDidChange = locale !== i18n.locale
33+
if (localeDidChange) {
34+
i18n.loadAndActivate({ locale, messages })
35+
}
36+
}, [locale])
37+
38+
return i18n
39+
}

src/locales/en/messages.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/en/messages.po

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
msgid ""
2+
msgstr ""
3+
"POT-Creation-Date: 2025-05-01 08:03-0500\n"
4+
"MIME-Version: 1.0\n"
5+
"Content-Type: text/plain; charset=utf-8\n"
6+
"Content-Transfer-Encoding: 8bit\n"
7+
"X-Generator: @lingui/cli\n"
8+
"Language: en\n"
9+
"Project-Id-Version: \n"
10+
"Report-Msgid-Bugs-To: \n"
11+
"PO-Revision-Date: \n"
12+
"Last-Translator: \n"
13+
"Language-Team: \n"
14+
"Plural-Forms: \n"
15+
16+
#: src/components/layout.js:26
17+
msgid "Check out the new blog post on DataTree!"
18+
msgstr "Check out the new blog post on DataTree!"

src/locales/es/messages.js

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/locales/es/messages.mo

420 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)