Skip to content

Commit

Permalink
✨ feat(i18n): Add i18next and lobe-i18n internationalization configur…
Browse files Browse the repository at this point in the history
…ation files and update dependencies

This commit introduces new configuration files for internationalization,
deletes one file, modifies existing files, and adds new files. The changes
also involve importing dependencies and updating app and document pages.
Additional libraries and modules are used in a React application. The Header
component is modified, the index page is updated for server-side translations,
and the tsconfig.json file is modified.

Description:
- Added configuration files for internationalization
- Deleted one file
- Modified existing files
- Added new files
- Imported dependencies
- Updated app and document pages
- Used additional libraries and modules in a React application
- Modified the Header component
- Updated the index page for server-side translations
- Modified the tsconfig.json file.
  • Loading branch information
canisminor1990 committed Jul 15, 2023
1 parent 4e522a6 commit 53cd87c
Show file tree
Hide file tree
Showing 19 changed files with 181 additions and 14 deletions.
12 changes: 12 additions & 0 deletions .i18nrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
const { description } = require('./package.json');

module.exports = {
reference: description,
entry: 'public/locales/zh_CN',
entryLocale: 'zh_CN',
output: 'public/locales',
outputLocales: ['zh_HK', 'en_US', 'ja_JP', 'ko_KR'],
splitToken: 2500,
temperature: 0,
modelName: 'gpt-3.5-turbo',
};
3 changes: 0 additions & 3 deletions commitlint.config.js

This file was deleted.

13 changes: 13 additions & 0 deletions next-i18next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const i18n = require('./.i18nrc');

/** @type {import('next-i18next').UserConfig} */
module.exports = {
debug: process.env.NODE_ENV === 'development',
i18n: {
defaultLocale: i18n.entryLocale,
locales: [i18n.entryLocale, i18n.outputLocales],
},
localePath:
typeof window === 'undefined' ? require('node:path').resolve('./', i18n.output) : '/locales',
reloadOnPrerender: process.env.NODE_ENV === 'development',
};
22 changes: 22 additions & 0 deletions next-utils.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const pc = require('picocolors');

const nextUtilsConfig = () => {
const trueEnv = ['true', '1', 'yes'];
const esmExternals = trueEnv.includes(process.env?.NEXTJS_ESM_EXTERNALS ?? 'false');
const tsconfigPath = process.env.NEXTJS_TSCONFIG_PATH
? process.env.NEXTJS_TSCONFIG_PATH
: './tsconfig.json';

// eslint-disable-next-line no-console
console.warn(
`${pc.green('warn -')} experimental.esmExternals is ${esmExternals ? 'enabled' : 'disabled'}`,
);
return {
esmExternals,
tsconfigPath,
};
};

module.exports = {
loadCustomBuildParams: nextUtilsConfig,
};
13 changes: 12 additions & 1 deletion next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
// @ts-check
import i18nConfig from './next-i18next.config.js';
import utilsConfig from './next-utils.config.js';

const API_END_PORT_URL = process.env.API_END_PORT_URL || '';

const { esmExternals = false, tsconfigPath } = utilsConfig.loadCustomBuildParams();

/** @type {import('next').NextConfig} */
const nextConfig = {
experimental: {
esmExternals, // https://nextjs.org/blog/next-11-1#es-modules-support
},
i18n: i18nConfig.i18n,
reactStrictMode: true,
pageExtensions: ['page.tsx', 'api.ts'],
transpilePackages: ['@lobehub/ui', 'antd-style'],
typescript: {
tsconfigPath,
},
webpack(config) {
config.experiments = {
asyncWebAssembly: true,
Expand Down
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"scripts": {
"build": "next build",
"dev": "next dev -p 3010",
"i18n": "lobe-i18n",
"lint": "eslint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
"lint:md": "remark . --quiet --frail --output",
"lint:style": "stylelint \"{src,tests}/**/*.{js,jsx,ts,tsx}\" --fix",
Expand All @@ -34,6 +35,7 @@
"test": "vitest --passWithNoTests",
"test:coverage": "vitest run --coverage --passWithNoTests",
"test:update": "vitest -u",
"toc": "i18next-resources-for-ts toc -i ./public/locales/zh_CN -o ./src/types/resources.ts",
"type-check": "tsc --noEmit"
},
"lint-staged": {
Expand Down Expand Up @@ -75,6 +77,7 @@
"lucide-react": "latest",
"nanoid": "^4",
"next": "13.4.7",
"next-i18next": "^14",
"polished": "^4",
"react": "^18",
"react-dom": "^18",
Expand All @@ -88,6 +91,7 @@
},
"devDependencies": {
"@commitlint/cli": "^17",
"@lobehub/i18n-cli": "latest",
"@lobehub/lint": "latest",
"@next/eslint-plugin-next": "^13",
"@testing-library/jest-dom": "^5",
Expand All @@ -104,10 +108,12 @@
"commitlint": "^17",
"eslint": "^8",
"husky": "^8",
"i18next-resources-for-ts": "^1",
"jsdom": "^22",
"lint-staged": "^13",
"next-pwa": "^5",
"node-fetch": "^3",
"picocolors": "^1",
"postcss-styled-syntax": "^0.4",
"prettier": "^2",
"remark": "^14",
Expand Down
4 changes: 4 additions & 0 deletions public/locales/en_US/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setting": "Setting",
"share": "Share"
}
4 changes: 4 additions & 0 deletions public/locales/ja_JP/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setting": "設定",
"share": "共有する"
}
4 changes: 4 additions & 0 deletions public/locales/ko_KR/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setting": "설정",
"share": "공유"
}
4 changes: 4 additions & 0 deletions public/locales/zh_CN/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setting": "设置",
"share": "分享"
}
4 changes: 4 additions & 0 deletions public/locales/zh_HK/common.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"setting": "設置",
"share": "分享"
}
18 changes: 18 additions & 0 deletions src/i18n/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import type { Namespace } from 'i18next';
import type { SSRConfig, UserConfig } from 'next-i18next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

import nextI18nextConfig from '@/../next-i18next.config';

type ArrayElementOrSelf<T> = T extends Array<infer U> ? U[] : T[];

export const getServerTranslations = async (
locale: string,
namespacesRequired?: ArrayElementOrSelf<Namespace> | undefined,
configOverride?: UserConfig,
extraLocales?: string[] | false,
): Promise<SSRConfig> => {
const config = configOverride ?? nextI18nextConfig;
// @ts-ignore
return serverSideTranslations(locale, namespacesRequired, config, extraLocales);
};
14 changes: 9 additions & 5 deletions src/pages/_app.page.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import { Analytics } from '@vercel/analytics/react';
import { appWithTranslation } from 'next-i18next';
import type { AppProps } from 'next/app';
import { Suspense } from 'react';

import Layout from '@/layout';

function MyApp({ Component, pageProps }: AppProps) {
return (
<Layout>
<Component {...pageProps} />
<Analytics />
</Layout>
<Suspense fallback="loading">
<Layout>
<Component {...pageProps} />
<Analytics />
</Layout>
</Suspense>
);
}

export default MyApp;
export default appWithTranslation(MyApp);
34 changes: 32 additions & 2 deletions src/pages/_document.page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { StyleProvider, extractStaticStyle } from 'antd-style';
import Document, { DocumentContext, Head, Html, Main, NextScript } from 'next/document';

import i18nextConfig from '../../next-i18next.config.js';

class MyDocument extends Document {
static async getInitialProps(ctx: DocumentContext) {
const page = await ctx.renderPage({
Expand Down Expand Up @@ -28,9 +30,37 @@ class MyDocument extends Document {
}

render() {
const currentLocale = this.props.__NEXT_DATA__.locale ?? i18nextConfig.i18n.defaultLocale;
return (
<Html lang="en">
<Head></Head>
<Html lang={currentLocale}>
<Head>
<link
href="https://npm.elemecdn.com/@lobehub/assets-favicons/assets/apple-touch-icon.png"
rel="apple-touch-icon"
sizes="180x180"
/>
<link
href="https://npm.elemecdn.com/@lobehub/assets-favicons/assets/favicon-32x32.png"
rel="icon"
sizes="32x32"
type="image/png"
/>
<link
href="https://npm.elemecdn.com/@lobehub/assets-favicons/assets/favicon-16x16.png"
rel="icon"
sizes="16x16"
type="image/png"
/>
<link
color="#000000"
href="https://npm.elemecdn.com/@lobehub/assets-favicons/assets/safari-pinned-tab.svg"
rel="mask-icon"
/>
<meta content="LobeHub" name="apple-mobile-web-app-title" />
<meta content="LobeHub" name="application-name" />
<meta content="#000000" name="msapplication-TileColor" />
<meta content="#000000" name="theme-color" />
</Head>
<body>
<Main />
<NextScript />
Expand Down
4 changes: 3 additions & 1 deletion src/pages/chat/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ActionIcon, Avatar } from '@lobehub/ui';
import { createStyles, useTheme } from 'antd-style';
import { ArchiveIcon, MoreVerticalIcon, Share2Icon } from 'lucide-react';
import { useTranslation } from 'next-i18next';
import { memo } from 'react';
import { Flexbox } from 'react-layout-kit';
import { shallow } from 'zustand/shallow';
Expand All @@ -19,6 +20,7 @@ const useStyles = createStyles(({ css, token }) => ({
}));
const Header = memo(() => {
const theme = useTheme();
const { t } = useTranslation('common');
const meta = useChatStore((s) => {
const chat = sessionSelectors.currentSession(s);
return chat?.meta;
Expand Down Expand Up @@ -62,7 +64,7 @@ const Header = memo(() => {
onClick={() => {
// genShareUrl();
}}
title={'分享'}
title={t('share')}
/>
<ActionIcon icon={ArchiveIcon} title={'归档'} />
<ActionIcon icon={MoreVerticalIcon} onClick={toggleConfig} />
Expand Down
18 changes: 17 additions & 1 deletion src/pages/index.page.tsx
Original file line number Diff line number Diff line change
@@ -1 +1,17 @@
export { default } from './chat/index.page';
import type { GetStaticProps, InferGetStaticPropsType } from 'next';
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';

import Chat from './chat/index.page';

// eslint-disable-next-line @typescript-eslint/no-unused-vars
const Index = (_props: InferGetStaticPropsType<typeof getStaticProps>) => {
return <Chat />;
};

export const getStaticProps: GetStaticProps = async ({ locale }) => ({
props: {
...(await serverSideTranslations(locale ?? 'zh_CN', ['common'])),
},
});

export default Index;
8 changes: 8 additions & 0 deletions src/types/i18next.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import resources from '@/types/resources';

declare module 'i18next' {
interface CustomTypeOptions {
defaultNS: 'common';
resources: typeof resources;
}
}
7 changes: 7 additions & 0 deletions src/types/resources.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import common from '@/../public/locales/zh_CN/common.json';

const resources = {
common,
} as const;

export default resources;
3 changes: 2 additions & 1 deletion tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ESNext",
"lib": ["dom", "dom.iterable", "esnext"],
Expand All @@ -21,5 +22,5 @@
}
},
"exclude": ["node_modules"],
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"]
"include": ["next-env.d.ts", "**/*.ts", "**/*.d.ts", "**/*.tsx"]
}

0 comments on commit 53cd87c

Please sign in to comment.