提交 3210f089 编写于 作者: P Peter Pan

we can use next-i18next in serverless mode now

上级 0eca8a87
import React, {FunctionComponent} from 'react';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import {NodeType, TypedNode} from '~/resource/graph';
import styled from 'styled-components';
import {WithStyled} from '~/utils/style';
......
import React, {FunctionComponent, useEffect, useState, useRef} from 'react';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import fetch from 'isomorphic-unfetch';
type ImageProps = {
......
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {useRouter} from 'next/router';
import Link from 'next/link';
import {useTranslation} from 'react-i18next';
import {useTranslation, Link} from '~/utils/i18n';
import {rem, headerColor, duration, easing, lighten, transitions} from '~/utils/style';
const navItems = ['scalars', 'samples', 'graphs', 'high-dimensional'];
......
import React, {FunctionComponent} from 'react';
import styled from 'styled-components';
import {rem} from '~/utils/style';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import Select, {SelectValueType} from '~/components/Select';
const Title = styled.div`
......
import React, {FunctionComponent, useState, useCallback} from 'react';
import styled from 'styled-components';
import {rem} from '~/utils/style';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import Button from '~/components/Button';
const StyledButton = styled(Button)`
......
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import useSWR from 'swr';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import {em, size, ellipsis, textLightColor} from '~/utils/style';
import StepSlider from '~/components/StepSlider';
import Image from '~/components/Image';
......
......@@ -7,7 +7,7 @@ import maxBy from 'lodash/maxBy';
import sortBy from 'lodash/sortBy';
import {EChartOption} from 'echarts';
import {em, size} from '~/utils/style';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import {cycleFetcher} from '~/utils/fetch';
import {transform, range, tooltip, TooltipData} from '~/utils/scalars';
import * as chart from '~/utils/chart';
......
import React, {FunctionComponent, useState, useCallback, useEffect} from 'react';
import styled from 'styled-components';
import without from 'lodash/without';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import useClickOutside from '~/hooks/useClickOutside';
import {
WithStyled,
......
import React, {FunctionComponent, useState} from 'react';
import styled from 'styled-components';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import Field from '~/components/Field';
import RangeSlider from '~/components/RangeSlider';
......
import React, {FunctionComponent, useState, useEffect} from 'react';
import styled from 'styled-components';
import {em, textLightColor} from '~/utils/style';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import RangeSlider from '~/components/RangeSlider';
const Label = styled.div`
......
......@@ -2,7 +2,7 @@ import React, {FunctionComponent, useState, useCallback, useEffect} from 'react'
import styled from 'styled-components';
import groupBy from 'lodash/groupBy';
import sortBy from 'lodash/sortBy';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
import {rem, math, ellipsis} from '~/utils/style';
import SearchInput from '~/components/SearchInput';
import Tag from '~/components/Tag';
......
import {useRef, useEffect, useCallback, MutableRefObject} from 'react';
import echarts, {ECharts} from 'echarts';
import {useTranslation} from 'react-i18next';
import {useTranslation} from '~/utils/i18n';
const useECharts = <T extends HTMLElement>(options: {
loading: boolean;
......
......@@ -15,6 +15,7 @@ const APP = {
};
module.exports = {
target: 'serverless',
assetPrefix: publicPath,
distDir: 'dist',
poweredByHeader: false,
......
......@@ -39,20 +39,15 @@
"echarts": "4.6.0",
"echarts-gl": "1.1.1",
"express": "4.17.1",
"i18next": "19.3.2",
"i18next-browser-languagedetector": "4.0.2",
"i18next-chained-backend": "2.0.1",
"i18next-localstorage-backend": "3.1.1",
"i18next-xhr-backend": "3.2.2",
"isomorphic-unfetch": "3.0.0",
"lodash": "4.17.15",
"moment": "2.24.0",
"next": "9.2.2",
"next-i18next": "4.2.0",
"nprogress": "0.2.0",
"polished": "3.4.4",
"react": "16.13.0",
"react-dom": "16.13.0",
"react-i18next": "11.3.3",
"react-input-range": "1.3.0",
"react-is": "16.13.0",
"save-svg-as-png": "1.4.17",
......
import '~/public/style/vdl-icon.css';
import '~/utils/i18n';
import React from 'react';
import Router from 'next/router';
import App from 'next/app';
import Head from 'next/head';
import NProgress from 'nprogress';
import {SWRConfig} from 'swr';
import {Router, appWithTranslation} from '~/utils/i18n';
import {fetcher} from '~/utils/fetch';
import {GlobalStyle} from '~/utils/style';
import Layout from '~/components/Layout';
......@@ -48,4 +47,4 @@ class VDLApp extends App {
}
}
export default VDLApp;
export default appWithTranslation(VDLApp);
import Document, {Head, Main, NextScript, DocumentContext} from 'next/document';
import Document, {Head, Main, NextScript, DocumentContext, DocumentProps} from 'next/document';
import {ServerStyleSheet} from '~/utils/style';
export default class VDLDocument extends Document {
interface VDLDocumentProps extends DocumentProps {
language: string;
}
export default class VDLDocument extends Document<VDLDocumentProps> {
static async getInitialProps(ctx: DocumentContext) {
// https://github.com/zeit/next.js/blob/canary/examples/with-typescript-styled-components/pages/_document.tsx
const sheet = new ServerStyleSheet();
......@@ -15,8 +19,16 @@ export default class VDLDocument extends Document {
const initialProps = await Document.getInitialProps(ctx);
// stealed from https://github.com/isaachinman/next-i18next/issues/20#issuecomment-558799264
// FIXME: https://github.com/i18next/i18next-express-middleware/blob/master/src/index.js#L23-L26
const additionalProps = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
language: (ctx.res as any)?.locals?.language ?? 'en'
};
return {
...initialProps,
...additionalProps,
styles: (
<>
{initialProps.styles}
......@@ -30,8 +42,9 @@ export default class VDLDocument extends Document {
}
render() {
const {language} = this.props;
return (
<html>
<html lang={language}>
<Head />
<body>
<Main />
......
import React from 'react';
import {useTranslation} from 'react-i18next';
import {NextPage} from 'next';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
interface ErrorProps {
statusCode?: number | null;
}
const Error: NextPage<ErrorProps> = ({statusCode}) => {
const Error: NextI18NextPage<ErrorProps> = ({statusCode}) => {
const {t} = useTranslation('errors');
return <p>{statusCode ? t('error-with-status', {statusCode}) : t('error-without-status')}</p>;
......@@ -20,6 +19,7 @@ Error.getInitialProps = ({res, err}) => {
({statusCode} = err);
}
return {
namespacesRequired: ['errors'],
statusCode
};
};
......
import React, {useState, useEffect, useMemo} from 'react';
import useSWR from 'swr';
import styled from 'styled-components';
import {NextPage} from 'next';
import RawButton from '~/components/Button';
import RawRangeSlider from '~/components/RangeSlider';
import Content from '~/components/Content';
import Title from '~/components/Title';
import Field from '~/components/Field';
import {useTranslation} from 'react-i18next';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import {rem} from '~/utils/style';
import {fetcher} from '~/utils/fetch';
import NodeInfo, {NodeInfoProps} from '~/components/GraphPage/NodeInfo';
......@@ -240,7 +239,7 @@ const useDagreD3 = (graph: Graph | undefined) => {
return {currentNode, displaySwitch, setDisplaySwitch, downloadImage, fitScreen, scale, setScale};
};
const Graphs: NextPage = () => {
const Graphs: NextI18NextPage = () => {
const {t} = useTranslation(['graphs', 'common']);
const {data: graph} = useSWR<{data: Graph}>('/graphs/graph', fetcher);
const {currentNode, downloadImage, fitScreen, scale, setScale} = useDagreD3(graph ? graph.data : undefined);
......@@ -282,4 +281,8 @@ const Graphs: NextPage = () => {
);
};
Graphs.getInitialProps = () => ({
namespacesRequired: ['graphs', 'common']
});
export default Graphs;
import React, {useState, useEffect, useMemo} from 'react';
import styled from 'styled-components';
import useSWR from 'swr';
import {NextPage} from 'next';
import {useRouter} from 'next/router';
import {rem, em} from '~/utils/style';
import {useTranslation} from 'react-i18next';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import Title from '~/components/Title';
import Content from '~/components/Content';
import SearchInput from '~/components/SearchInput';
......@@ -43,7 +42,7 @@ type Data = {
labels: string[];
};
const HighDimensional: NextPage = () => {
const HighDimensional: NextI18NextPage = () => {
const {t} = useTranslation(['high-dimensional', 'common']);
const {query} = useRouter();
......@@ -143,4 +142,8 @@ const HighDimensional: NextPage = () => {
);
};
HighDimensional.getInitialProps = () => ({
namespacesRequired: ['high-dimensional', 'common']
});
export default HighDimensional;
import {useEffect} from 'react';
import {NextPage} from 'next';
import Router from 'next/router';
import {NextI18NextPage, Router} from '~/utils/i18n';
const Index: NextPage = () => {
const Index: NextI18NextPage = () => {
useEffect(() => {
Router.replace('/scalars');
}, []);
......@@ -10,4 +9,10 @@ const Index: NextPage = () => {
return null;
};
Index.getInitialProps = () => {
return {
namespacesRequired: []
};
};
export default Index;
import React, {useState, useCallback, useMemo} from 'react';
import {useTranslation} from 'react-i18next';
import styled from 'styled-components';
import {NextPage} from 'next';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import {rem, em} from '~/utils/style';
import useTagFilter from '~/hooks/useTagFilter';
import Title from '~/components/Title';
......@@ -38,7 +37,7 @@ type Item = {
label: string;
};
const Samples: NextPage = () => {
const Samples: NextI18NextPage = () => {
const {t} = useTranslation(['samples', 'common']);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags} = useTagFilter('images');
......@@ -113,4 +112,8 @@ const Samples: NextPage = () => {
);
};
Samples.getInitialProps = () => ({
namespacesRequired: ['samples', 'common']
});
export default Samples;
import React, {useState, useCallback} from 'react';
import {useTranslation} from 'react-i18next';
import {NextPage} from 'next';
import {useTranslation, NextI18NextPage} from '~/utils/i18n';
import useTagFilter from '~/hooks/useTagFilter';
import Title from '~/components/Title';
import Content from '~/components/Content';
......@@ -21,7 +20,7 @@ const xAxisValues = ['step', 'relative', 'wall'];
type TooltiopSorting = keyof typeof sortingMethodMap;
const toolTipSortingValues = ['default', 'descending', 'ascending', 'nearest'];
const Scalars: NextPage = () => {
const Scalars: NextI18NextPage = () => {
const {t} = useTranslation(['scalars', 'common']);
const {runs, tags, selectedRuns, selectedTags, onChangeRuns, onFilterTags} = useTagFilter('scalars');
......@@ -93,4 +92,8 @@ const Scalars: NextPage = () => {
);
};
Scalars.getInitialProps = () => ({
namespacesRequired: ['scalars', 'common']
});
export default Scalars;
......@@ -2,6 +2,8 @@ import path from 'path';
import express from 'express';
import next from 'next';
import {setConfig} from 'next/config';
import nextI18NextMiddleware from 'next-i18next/middleware';
import nextI18next from '../utils/i18n';
import config from '../next.config';
const isDev = process.env.NODE_ENV !== 'production';
......@@ -21,6 +23,9 @@ const handle = app.getRequestHandler();
server.use(config.env.API_URL, mock({path: path.resolve(__dirname, '../mock')}));
}
await nextI18next.initPromise;
server.use(nextI18NextMiddleware(nextI18next));
server.get('*', (req, res) => handle(req, res));
server.listen(port);
......
import i18n, {InitOptions} from 'i18next';
import {initReactI18next} from 'react-i18next';
import Backend from 'i18next-chained-backend';
import LocalStorageBackend from 'i18next-localstorage-backend';
import XHR from 'i18next-xhr-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import {NextComponentType, NextPageContext} from 'next';
import NextI18Next from 'next-i18next';
const options: InitOptions = {
react: {
useSuspense: false
},
const isDev = process.env.NODE_ENV === 'development';
load: 'languageOnly',
fallbackLng: 'en',
defaultNS: 'common',
ns: ['common'],
interpolation: {
escapeValue: false // not needed for react as it escapes by default
const nextI18Next = new NextI18Next({
localePath: 'public/locales',
browserLanguageDetection: !isDev,
serverLanguageDetection: !isDev,
defaultLanguage: 'en',
otherLanguages: ['zh'],
localeSubpaths: {
zh: 'zh'
}
};
if (process.browser) {
i18n
// load translation using xhr -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
// learn more: https://github.com/i18next/i18next-xhr-backend
.use(Backend)
// detect user language
// learn more: https://github.com/i18next/i18next-browser-languageDetector
.use(LanguageDetector)
// pass the i18n instance to react-i18next.
.use(initReactI18next)
// init i18next
// for all options read: https://www.i18next.com/overview/configuration-options
.init({
backend: {
backends: [LocalStorageBackend, XHR],
backendOptions: [
{
defaultVersion: '1' // TODO: use build id
},
{
loadPath: `${process.env.PUBLIC_PATH}/locales/{{lng}}/{{ns}}.json`,
allowMultiLoading: false,
crossDomain: true,
overrideMimeType: true
}
]
},
});
detection: {},
// from ~/node_modules/next/types/index.d.ts
// https://gitlab.com/kachkaev/website-frontend/-/blob/master/src/i18n.ts#L64-68
export type NextI18NextPage<P = {}, IP = P> = NextComponentType<
NextPageContext,
IP & {namespacesRequired: string[]},
P & {namespacesRequired: string[]}
>;
...options
});
} else {
i18n.use(initReactI18next).init(options);
}
export default nextI18Next;
export default i18n;
export const {i18n, appWithTranslation, withTranslation, useTranslation, Router, Link, Trans} = nextI18Next;
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册