Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion apps/site/app/[locale]/[...path]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@
* dynamic params, which will lead on static export errors and other sort of issues.
*/

import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
import { notFound } from 'next/navigation';

import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import { ENABLE_STATIC_EXPORT_LOCALE } from '#site/next.constants.mjs';
import { dynamicRouter } from '#site/next.dynamic.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';
import { availableLocaleCodes, defaultLocale } from '#site/next.locales.mjs';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion apps/site/app/[locale]/blog/[...path]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { defaultLocale } from '@node-core/website-i18n';
import { notFound } from 'next/navigation';

import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import { BLOG_DYNAMIC_ROUTES } from '#site/next.dynamic.constants.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';
import { defaultLocale } from '#site/next.locales.mjs';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { defaultLocale } from '@node-core/website-i18n';
import { notFound, redirect } from 'next/navigation';

import provideReleaseData from '#site/next-data/providers/releaseData';
import provideReleaseVersions from '#site/next-data/providers/releaseVersions';
import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';
import { defaultLocale } from '#site/next.locales.mjs';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion apps/site/app/[locale]/feed/[feed]/route.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { defaultLocale } from '@node-core/website-i18n';
import { NextResponse } from 'next/server';

import { siteConfig } from '#site/next.json.mjs';
import { defaultLocale } from '#site/next.locales.mjs';
import { getFeeds } from '#site/util/feeds';

type DynamicStaticPaths = { locale: string; feed: string };
Expand Down
5 changes: 3 additions & 2 deletions apps/site/app/[locale]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { availableLocales, defaultLocale } from '@node-core/website-i18n';
import { Analytics } from '@vercel/analytics/react';
import { SpeedInsights } from '@vercel/speed-insights/next';
import classNames from 'classnames';
Expand All @@ -6,7 +7,6 @@ import { NextIntlClientProvider } from 'next-intl';
import BaseLayout from '#site/layouts/Base';
import { VERCEL_ENV } from '#site/next.constants.mjs';
import { IBM_PLEX_MONO, OPEN_SANS } from '#site/next.fonts';
import { availableLocalesMap, defaultLocale } from '#site/next.locales.mjs';
import { ThemeProvider } from '#site/providers/themeProvider';

import type { FC, PropsWithChildren } from 'react';
Expand All @@ -22,7 +22,8 @@ type RootLayoutProps = PropsWithChildren<{
const RootLayout: FC<RootLayoutProps> = async ({ children, params }) => {
const { locale } = await params;

const { langDir, hrefLang } = availableLocalesMap[locale] || defaultLocale;
const { langDir, hrefLang } =
availableLocales.find(l => l.code === locale) || defaultLocale;

return (
<html
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import HexagonGrid from '@node-core/ui-components/Icons/HexagonGrid';
import JsWhiteIcon from '@node-core/ui-components/Icons/Logos/JsWhite';
import { defaultLocale } from '@node-core/website-i18n';
import { ImageResponse } from 'next/og';

import { DEFAULT_CATEGORY_OG_TYPE } from '#site/next.constants.mjs';
import { defaultLocale } from '#site/next.locales.mjs';

// TODO: use CSS variables instead of absolute values
const CATEGORY_TO_THEME_COLOUR_MAP = {
Expand Down
3 changes: 1 addition & 2 deletions apps/site/app/[locale]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { defaultLocale, availableLocaleCodes } from '@node-core/website-i18n';
import { notFound } from 'next/navigation';

import { ENABLE_STATIC_EXPORT } from '#site/next.constants.mjs';
import { ENABLE_STATIC_EXPORT_LOCALE } from '#site/next.constants.mjs';
import * as basePage from '#site/next.dynamic.page.mjs';
import { availableLocaleCodes } from '#site/next.locales.mjs';
import { defaultLocale } from '#site/next.locales.mjs';

import type { DynamicParams } from '#site/types';
import type { FC } from 'react';
Expand Down
3 changes: 2 additions & 1 deletion apps/site/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';

import { BASE_PATH } from '#site/next.constants.mjs';
import { BASE_URL } from '#site/next.constants.mjs';
import { EXTERNAL_LINKS_SITEMAP } from '#site/next.constants.mjs';
import { BLOG_DYNAMIC_ROUTES } from '#site/next.dynamic.constants.mjs';
import { dynamicRouter } from '#site/next.dynamic.mjs';
import { availableLocaleCodes, defaultLocale } from '#site/next.locales.mjs';

import type { MetadataRoute } from 'next';

Expand Down
2 changes: 1 addition & 1 deletion apps/site/components/withDownloadSection.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { defaultLocale } from '@node-core/website-i18n';
import { getLocale } from 'next-intl/server';

import { getClientContext } from '#site/client-context';
import WithNodeRelease from '#site/components/withNodeRelease';
import provideDownloadSnippets from '#site/next-data/providers/downloadSnippets';
import { defaultLocale } from '#site/next.locales.mjs';
import {
ReleaseProvider,
ReleasesProvider,
Expand Down
2 changes: 1 addition & 1 deletion apps/site/components/withMetaBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import MetaBar from '@node-core/ui-components/Containers/MetaBar';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';
import { defaultLocale } from '@node-core/website-i18n';
import { useFormatter, useLocale, useTranslations } from 'next-intl';

import Link from '#site/components/Link';
Expand All @@ -10,7 +11,6 @@ import { useClientContext } from '#site/hooks/react-client';
import useMediaQuery from '#site/hooks/react-client/useMediaQuery';
import { DEFAULT_DATE_FORMAT } from '#site/next.calendar.constants.mjs';
import { TRANSLATION_URL } from '#site/next.constants.mjs';
import { defaultLocale } from '#site/next.locales.mjs';
import { getGitHubBlobUrl } from '#site/util/github';

import type { FC } from 'react';
Expand Down
2 changes: 1 addition & 1 deletion apps/site/components/withNavBar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import NavBar from '@node-core/ui-components/Containers/NavBar';
// TODO(@AvivKeller): I don't like that we are importing styles from another module
import styles from '@node-core/ui-components/Containers/NavBar/index.module.css';
import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub';
import { availableLocales } from '@node-core/website-i18n';
import dynamic from 'next/dynamic';
import { useLocale, useTranslations } from 'next-intl';
import { useTheme } from 'next-themes';
Expand All @@ -16,7 +17,6 @@ import WithBanner from '#site/components/withBanner';
import WithNodejsLogo from '#site/components/withNodejsLogo';
import { useSiteNavigation } from '#site/hooks';
import { useRouter, usePathname } from '#site/navigation.mjs';
import { availableLocales } from '#site/next.locales.mjs';

import type { SimpleLocaleConfig } from '@node-core/ui-components/types';
import type { FC } from 'react';
Expand Down
8 changes: 4 additions & 4 deletions apps/site/i18n.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { importLocale } from '@node-core/website-i18n';
import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
import defaultMessages from '@node-core/website-i18n/locales/en.json';
import { getRequestConfig } from 'next-intl/server';

import { availableLocaleCodes, defaultLocale } from '#site/next.locales.mjs';

import { deepMerge } from './util/objects';

// Loads the Application Locales/Translations Dynamically
Expand All @@ -15,7 +13,9 @@ const loadLocaleDictionary = async (locale: string) => {
if (availableLocaleCodes.includes(locale)) {
// Other languages don't really require HMR as they
// will never be development languages so we can load them dynamically
const messages = await importLocale(locale);
const { default: messages } = await import(
`@node-core/website-i18n/locales/${locale}.json`
);

// Use default messages as fallback
return deepMerge(defaultMessages, messages);
Expand Down
3 changes: 1 addition & 2 deletions apps/site/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
import createMiddleware from 'next-intl/middleware';

import { availableLocaleCodes, defaultLocale } from '#site/next.locales.mjs';

export default createMiddleware({
// A list of all locales that are supported
locales: availableLocaleCodes,
Expand Down
3 changes: 1 addition & 2 deletions apps/site/navigation.mjs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
'use strict';

import { availableLocaleCodes } from '@node-core/website-i18n';
import { createNavigation } from 'next-intl/navigation';

import { availableLocaleCodes } from './next.locales.mjs';

export const { Link, redirect, usePathname, useRouter } = createNavigation({
locales: availableLocaleCodes,
});
2 changes: 1 addition & 1 deletion apps/site/next-data/generators/downloadSnippets.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { readFile, glob } from 'node:fs/promises';
import { basename, extname, join } from 'node:path';

import { availableLocaleCodes } from '../../next.locales.mjs';
import { availableLocaleCodes } from '@node-core/website-i18n';

/**
* This method is used to generate the Node.js Website Download Snippets
Expand Down
2 changes: 1 addition & 1 deletion apps/site/next.dynamic.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import { readFile } from 'node:fs/promises';
import { join, normalize, sep } from 'node:path';

import { availableLocaleCodes, defaultLocale } from '@node-core/website-i18n';
import matter from 'gray-matter';
import { cache } from 'react';
import { VFile } from 'vfile';
Expand All @@ -17,7 +18,6 @@ import { IS_DEV_ENV } from './next.constants.mjs';
import { PAGE_METADATA } from './next.dynamic.constants.mjs';
import { getMarkdownFiles } from './next.helpers.mjs';
import { siteConfig } from './next.json.mjs';
import { availableLocaleCodes, defaultLocale } from './next.locales.mjs';

// This is the combination of the Application Base URL and Base PATH
const baseUrlAndPath = `${BASE_URL}${BASE_PATH}`;
Expand Down
7 changes: 5 additions & 2 deletions apps/site/next.dynamic.page.mjs
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { join } from 'node:path';

import {
allLocaleCodes,
defaultLocale,
availableLocaleCodes,
} from '@node-core/website-i18n';
import { notFound, redirect } from 'next/navigation';
import { setRequestLocale } from 'next-intl/server';

import { setClientContext } from '#site/client-context';
import WithLayout from '#site/components/withLayout';
import { PAGE_VIEWPORT } from '#site/next.dynamic.constants.mjs';
import { dynamicRouter } from '#site/next.dynamic.mjs';
import { allLocaleCodes, availableLocaleCodes } from '#site/next.locales.mjs';
import { defaultLocale } from '#site/next.locales.mjs';
import { MatterProvider } from '#site/providers/matterProvider';

/**
Expand Down
36 changes: 0 additions & 36 deletions apps/site/next.locales.mjs

This file was deleted.

3 changes: 2 additions & 1 deletion apps/site/next.rewrites.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use strict';

import { availableLocaleCodes } from '@node-core/website-i18n';

import { siteRedirects } from './next.json.mjs';
import { availableLocaleCodes } from './next.locales.mjs';

// This allows us to prefix redirects with all available locale codes so that redirects are not bound to a single locale
// This also transforms the locale itself as a matching group that can be used for rewrites
Expand Down
14 changes: 9 additions & 5 deletions apps/site/tests/e2e/general-behavior.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
import { importLocale } from '@node-core/website-i18n';
import englishLocale from '@node-core/website-i18n/locales/en.json' with { type: 'json' };
import { test, expect, type Page } from '@playwright/test';

import type { Locale } from '@node-core/website-i18n/types';

const englishLocale = await importLocale('en');

// TODO(@avivkeller): It would be ideal for all the Test IDs to not exist in the
// ui-components package, and instead be passed as props.
const locators = {
Expand Down Expand Up @@ -43,8 +41,14 @@ const openLanguageMenu = async (page: Page) => {

const verifyTranslation = async (page: Page, locale: Locale | string) => {
// Load locale data if string code provided (e.g., 'es', 'fr')
const localeData =
typeof locale === 'string' ? await importLocale(locale) : locale;
const localeData: Locale =
typeof locale === 'string'
? (
await import(`@node-core/website-i18n/locales/${locale}.json`, {
with: { type: 'json' },
})
).default
: locale;

// Get navigation links and expected translations
const links = await page
Expand Down
9 changes: 0 additions & 9 deletions docs/technologies.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ This document provides an overview of the technologies used in the Node.js websi
- [`redirects.json`](#redirectsjson)
- [Configuration Files](#configuration-files)
- [`site.json`](#sitejson)
- [`next.locales.mjs`](#nextlocalesmjs)
- [Development Environment](#development-environment)
- [VSCode Configuration](#vscode-configuration)
- [Build and Deployment](#build-and-deployment)
Expand Down Expand Up @@ -267,14 +266,6 @@ Website metadata configuration:
- Build-time metadata
- Uses JSON format for easy collaboration

### `next.locales.mjs`

Locale configuration and management:

- Supported locale definitions
- Locale-specific settings
- Page availability per locale

## Development Environment

### VSCode Configuration
Expand Down
30 changes: 6 additions & 24 deletions packages/i18n/src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,40 +2,22 @@

import localeConfig from './config.json' with { type: 'json' };

/**
* Imports a locale when exists from the locales directory
*
* @param {string} locale The locale code to import
* @returns {Promise<import('./types').Locale>} The imported locale
*/
export const importLocale = async locale => {
return import(`./locales/${locale}.json`, { with: { type: 'json' } }).then(
f => f.default
);
};

/**
* A set of available and enabled locales for the website
* This is used for allowing us to redirect the user to any
* of the available locales that we have enabled on the website
*
* @returns {Array<import('./types').LocaleConfig>}
* @type {Array<import('./types').LocaleConfig>}
*/
export const getAvailableLocales = () =>
localeConfig.filter(locale => locale.enabled);
export const availableLocales = localeConfig.filter(locale => locale.enabled);

// This gives an easy way of accessing all available locale codes
export const getAvailableLocaleCodes = () =>
getAvailableLocales().map(locale => locale.code);
export const availableLocaleCodes = availableLocales.map(locale => locale.code);

// This provides the default locale information for the Next.js Application
// This is marked by the unique `locale.default` property on the `en` locale
export const getDefaultLocale = () =>
getAvailableLocales().find(locale => locale.default);

// Creates a Map of available locales for easy access
export const getAvailableLocalesMap = () =>
Object.fromEntries(localeConfig.map(locale => [locale.code, locale]));
/** @type {import('./types').LocaleConfig} */
export const defaultLocale = availableLocales.find(locale => locale.default);

// Creates all supported locales
export const getAllLocaleCodes = () => localeConfig.map(locale => locale.code);
export const allLocaleCodes = localeConfig.map(locale => locale.code);
Loading