-
- {t('modules.dashDot.card.graphs.storage.label')}
-
+
{t('card.graphs.storage.label')}
{((100 * totalUsed) / (totalSize || 1)).toFixed(1)}%{'\n'}
{bytePrettyPrint(totalUsed)} / {bytePrettyPrint(totalSize)}
@@ -204,15 +204,12 @@ export function DashdotComponent() {
)}
{networkEnabled && (
-
- {t('modules.dashDot.card.graphs.network.label')}
-
+
{t('card.graphs.network.label')}
- {bpsPrettyPrint(info?.network?.speedUp)}{' '}
- {t('modules.dashDot.card.graphs.network.metrics.upload')}
+ {bpsPrettyPrint(info?.network?.speedUp)} {t('card.graphs.network.metrics.upload')}
{'\n'}
{bpsPrettyPrint(info?.network?.speedDown)}
- {t('modules.dashDot.card.graphs.network.metrics.download')}
+ {t('card.graphs.network.metrics.download')}
)}
diff --git a/src/modules/docker/ContainerActionBar.tsx b/src/modules/docker/ContainerActionBar.tsx
index 0ae7e2ed1..a12731d9d 100644
--- a/src/modules/docker/ContainerActionBar.tsx
+++ b/src/modules/docker/ContainerActionBar.tsx
@@ -11,9 +11,10 @@ import {
} from '@tabler/icons';
import axios from 'axios';
import Dockerode from 'dockerode';
+import { useState } from 'react';
+import { useTranslation } from 'next-i18next';
import { tryMatchService } from '../../tools/addToHomarr';
import { AddAppShelfItemForm } from '../../components/AppShelf/AddAppShelfItem';
-import { useState } from 'react';
function sendDockerCommand(
action: string,
@@ -21,6 +22,8 @@ function sendDockerCommand(
containerName: string,
reload: () => void
) {
+ const { t } = useTranslation('modules/docker-module');
+
showNotification({
id: containerId,
loading: true,
@@ -34,8 +37,8 @@ function sendDockerCommand(
.then((res) => {
updateNotification({
id: containerId,
- title: `Container ${containerName} ${action}ed`,
- message: `Your container was successfully ${action}ed`,
+ title: t('messages.successfullyExecuted.message', { containerName, action }),
+ message: t('messages.successfullyExecuted.message', { action }),
icon:
,
autoClose: 2000,
});
@@ -44,7 +47,7 @@ function sendDockerCommand(
updateNotification({
id: containerId,
color: 'red',
- title: 'There was an error',
+ title: t('errors.unknownError.title'),
message: err.response.data.reason,
autoClose: 2000,
});
@@ -61,6 +64,8 @@ export interface ContainerActionBarProps {
export default function ContainerActionBar({ selected, reload }: ContainerActionBarProps) {
const [opened, setOpened] = useState
(false);
+ const { t } = useTranslation('modules/docker-module');
+
return (
setOpened(false)}
- title="Add service"
+ title={t('actionBar.addService.title')}
>
}
@@ -104,7 +109,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
color="red"
radius="md"
>
- Stop
+ {t('actionBar.stop.title')}
}
@@ -119,10 +124,10 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
color="green"
radius="md"
>
- Start
+ {t('actionBar.start.title')}
} onClick={() => reload()} variant="light" radius="md">
- Refresh data
+ {t('actionBar.refreshData.title')}
}
@@ -133,7 +138,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
if (selected.length !== 1) {
showNotification({
autoClose: 5000,
- title: Please only add one service at a time!,
+ title: {t('errors.oneServiceAtATime')},
color: 'red',
message: undefined,
});
@@ -142,7 +147,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
}
}}
>
- Add to Homarr
+ {t('actionBar.addToHomarr.title')}
}
@@ -157,7 +162,7 @@ export default function ContainerActionBar({ selected, reload }: ContainerAction
)
}
>
- Remove
+ {t('actionBar.remove.title')}
);
diff --git a/src/modules/docker/ContainerState.tsx b/src/modules/docker/ContainerState.tsx
index d5c6b5077..459dcb70f 100644
--- a/src/modules/docker/ContainerState.tsx
+++ b/src/modules/docker/ContainerState.tsx
@@ -1,4 +1,5 @@
import { Badge, BadgeVariant, MantineSize } from '@mantine/core';
+import { useTranslation } from 'next-i18next';
import Dockerode from 'dockerode';
export interface ContainerStateProps {
@@ -7,6 +8,9 @@ export interface ContainerStateProps {
export default function ContainerState(props: ContainerStateProps) {
const { state } = props;
+
+ const { t } = useTranslation('modules/docker-module');
+
const options: {
size: MantineSize;
radius: MantineSize;
@@ -20,28 +24,28 @@ export default function ContainerState(props: ContainerStateProps) {
case 'running': {
return (
- Running
+ {t('table.states.running')}
);
}
case 'created': {
return (
- Created
+ {t('table.states.created')}
);
}
case 'exited': {
return (
- Stopped
+ {t('table.states.stopped')}
);
}
default: {
return (
- Unknown
+ {t('table.states.unknown')}
);
}
diff --git a/src/modules/docker/DockerModule.tsx b/src/modules/docker/DockerModule.tsx
index 91920c93a..7ef03daaa 100644
--- a/src/modules/docker/DockerModule.tsx
+++ b/src/modules/docker/DockerModule.tsx
@@ -1,10 +1,10 @@
-import { ActionIcon, Drawer, Group, LoadingOverlay, Text, Tooltip } from '@mantine/core';
+import { ActionIcon, Drawer, Text, Tooltip } from '@mantine/core';
import axios from 'axios';
import { useEffect, useState } from 'react';
import Docker from 'dockerode';
import { IconBrandDocker, IconX } from '@tabler/icons';
import { showNotification } from '@mantine/notifications';
-import { t } from 'i18next';
+import { useTranslation } from 'next-i18next';
import ContainerActionBar from './ContainerActionBar';
import DockerTable from './DockerTable';
@@ -25,6 +25,8 @@ export default function DockerMenuButton(props: any) {
const { config } = useConfig();
const moduleEnabled = config.modules?.[DockerModule.title]?.enabled ?? false;
+ const { t } = useTranslation('modules/docker-module');
+
useEffect(() => {
reload();
}, [config.modules]);
@@ -44,10 +46,10 @@ export default function DockerMenuButton(props: any) {
// Send an Error notification
showNotification({
autoClose: 1500,
- title: {t('layout.header.docker.errors.integrationFailed.title')},
+ title: {t('errors.integrationFailed.title')},
color: 'red',
icon: ,
- message: t('layout.header.docker.errors.integrationFailed.message'),
+ message: t('errors.integrationFailed.message'),
})
);
}, 300);
@@ -69,7 +71,7 @@ export default function DockerMenuButton(props: any) {
>
-
+
{
setContainers(containers);
}, [containers]);
@@ -83,7 +85,7 @@ export default function DockerTable({
))}
{element.Ports.length > 3 && (
- {t('modules.docker.table.body.portCollapse', { ports: element.Ports.length - 3 })}
+ {t('table.body.portCollapse', { ports: element.Ports.length - 3 })}
)}
@@ -98,7 +100,7 @@ export default function DockerTable({
return (
}
value={search}
@@ -115,10 +117,10 @@ export default function DockerTable({
transitionDuration={0}
/>
- {t('modules.docker.table.header.name')} |
- {t('modules.docker.table.header.image')} |
- {t('modules.docker.table.header.ports')} |
- {t('modules.docker.table.header.state')} |
+ {t('table.header.name')} |
+ {t('table.header.image')} |
+ {t('table.header.ports')} |
+ {t('table.header.state')} |
{rows}
diff --git a/src/modules/downloads/DownloadsModule.tsx b/src/modules/downloads/DownloadsModule.tsx
index a8bdad466..f4f9a8575 100644
--- a/src/modules/downloads/DownloadsModule.tsx
+++ b/src/modules/downloads/DownloadsModule.tsx
@@ -20,7 +20,7 @@ import { useConfig } from '../../tools/state';
import { AddItemShelfButton } from '../../components/AppShelf/AddAppShelfItem';
import { useSetSafeInterval } from '../../tools/hooks/useSetSafeInterval';
import { humanFileSize } from '../../tools/humanFileSize';
-import { t } from 'i18next';
+import { useTranslation } from 'next-i18next';
export const DownloadsModule: IModule = {
title: 'Torrent',
@@ -50,6 +50,9 @@ export default function DownloadComponent() {
const [torrents, setTorrents] = useState([]);
const setSafeInterval = useSetSafeInterval();
const [isLoading, setIsLoading] = useState(true);
+
+ const { t } = useTranslation('modules/downloads-module');
+
useEffect(() => {
setIsLoading(true);
if (downloadServices.length === 0) return;
@@ -106,12 +109,12 @@ export default function DownloadComponent() {
const DEVICE_WIDTH = 576;
const ths = (
- | {t('modules.downloads.card.table.header.name')} |
- {t('modules.downloads.card.table.header.size')} |
- {width > 576 ? {t('modules.downloads.card.table.header.download')} | : ''}
- {width > 576 ? {t('modules.downloads.card.table.header.upload')} | : ''}
- {t('modules.downloads.card.table.header.estimatedTimeOfArrival')} |
- {t('modules.downloads.card.table.header.progress')} |
+ {t('card.table.header.name')} |
+ {t('card.table.header.size')} |
+ {width > 576 ? {t('card.table.header.download')} | : ''}
+ {width > 576 ? {t('card.table.header.upload')} | : ''}
+ {t('card.table.header.estimatedTimeOfArrival')} |
+ {t('card.table.header.progress')} |
);
// Convert Seconds to readable format.
@@ -196,7 +199,7 @@ export default function DownloadComponent() {
) : (
- {t('modules.downloads.card.table.body.nothingFound')}
+ {t('card.table.body.nothingFound')}
)}
diff --git a/src/modules/overseerr/RequestModal.tsx b/src/modules/overseerr/RequestModal.tsx
index ffa06c5a6..e632290f8 100644
--- a/src/modules/overseerr/RequestModal.tsx
+++ b/src/modules/overseerr/RequestModal.tsx
@@ -3,7 +3,7 @@ import { showNotification, updateNotification } from '@mantine/notifications';
import { IconAlertCircle, IconCheck, IconDownload } from '@tabler/icons';
import axios from 'axios';
import Consola from 'consola';
-import { t } from 'i18next';
+import { useTranslation } from 'next-i18next';
import { useState } from 'react';
import { useColorTheme } from '../../tools/color';
@@ -28,6 +28,7 @@ const useStyles = createStyles((theme) => ({
export function RequestModal({ base, opened, setOpened }: RequestModalProps) {
const [result, setResult] = useState();
const { secondaryColor } = useColorTheme();
+
function getResults(base: Result) {
axios.get(`/api/modules/overseerr/${base.id}?type=${base.mediaType}`).then((res) => {
setResult(res.data);
@@ -56,6 +57,8 @@ export function MovieRequestModal({
setOpened: (opened: boolean) => void;
}) {
const { secondaryColor } = useColorTheme();
+ const { t } = useTranslation('modules/overseerr-module');
+
return (
setOpened(false)}
@@ -68,23 +71,23 @@ export function MovieRequestModal({
title={
- {t('modules.overseerr.popup.item.buttons.askFor', { title: result.title })}
+ {t('popup.item.buttons.askFor', { title: result.title })}
}
>
}
- title={t('modules.overseerr.popup.item.alerts.automaticApproval.title')}
+ title={t('popup.item.alerts.automaticApproval.title')}
color={secondaryColor}
radius="md"
variant="filled"
>
- {t('modules.overseerr.popup.item.alerts.automaticApproval.text')}
+ {t('popup.item.alerts.automaticApproval.text')}
@@ -111,6 +114,7 @@ export function TvRequestModal({
}) {
const [selection, setSelection] = useState(result.seasons);
const { classes, cx } = useStyles();
+ const { t } = useTranslation('modules/overseerr-module');
const toggleRow = (container: TvShowResultSeason) =>
setSelection((current: TvShowResultSeason[]) =>
@@ -149,7 +153,7 @@ export function TvRequestModal({
title={
- {t('modules.overseerr.popup.item.buttons.askFor', {
+ {t('popup.item.buttons.askFor', {
title: result.name ?? result.originalName ?? 'a TV show',
})}
@@ -158,15 +162,15 @@ export function TvRequestModal({
}
- title={t('modules.overseerr.popup.item.alerts.automaticApproval.title')}
+ title={t('popup.item.alerts.automaticApproval.title')}
color={secondaryColor}
radius="md"
variant="filled"
>
- {t('modules.overseerr.popup.item.alerts.automaticApproval.text')}
+ {t('popup.item.alerts.automaticApproval.text')}
- {t('modules.overseerr.popup.seasonSelector.caption')}
+ {t('popup.seasonSelector.caption')}
|
@@ -177,15 +181,15 @@ export function TvRequestModal({
transitionDuration={0}
/>
|
- {t('modules.overseerr.popup.seasonSelector.table.header.season')} |
- {t('modules.overseerr.popup.seasonSelector.table.header.numberOfEpisodes')} |
+ {t('popup.seasonSelector.table.header.season')} |
+ {t('popup.seasonSelector.table.header.numberOfEpisodes')} |
{rows}
diff --git a/src/modules/ping/PingModule.tsx b/src/modules/ping/PingModule.tsx
index f8ab442fe..fd7468124 100644
--- a/src/modules/ping/PingModule.tsx
+++ b/src/modules/ping/PingModule.tsx
@@ -5,7 +5,7 @@ import { useEffect, useState } from 'react';
import { IconPlug as Plug } from '@tabler/icons';
import { useConfig } from '../../tools/state';
import { IModule } from '../ModuleTypes';
-import { t } from 'i18next';
+import { useTranslation } from 'next-i18next';
export const PingModule: IModule = {
title: 'Ping Services',
@@ -23,6 +23,8 @@ export default function PingComponent(props: any) {
const [response, setResponse] = useState(500);
const exists = config.modules?.[PingModule.title]?.enabled ?? false;
+ const { t } = useTranslation('modules/ping-module');
+
function statusCheck(response: AxiosResponse) {
const { status }: { status: string[] } = props;
//Default Status
@@ -69,10 +71,10 @@ export default function PingComponent(props: any) {
radius="lg"
label={
isOnline === 'loading'
- ? t('modules.ping.states.loading')
+ ? t('states.loading')
: isOnline === 'online'
- ? t('modules.ping.states.online', { response })
- : t('modules.ping.states.offline', { response })
+ ? t('states.online', { response })
+ : t('states.offline', { response })
}
>
{
if (OverseerrService === undefined && isOverseerrEnabled) {
@@ -177,7 +177,7 @@ export default function SearchBar(props: any) {
radius="md"
size="md"
styles={{ rightSection: { pointerEvents: 'none' } }}
- placeholder={t('layout.header.search.input.placeholder')}
+ placeholder={t('input.placeholder')}
{...props}
{...form.getInputProps('query')}
/>
diff --git a/src/modules/weather/WeatherModule.tsx b/src/modules/weather/WeatherModule.tsx
index 4d3ce8ff7..930b17405 100644
--- a/src/modules/weather/WeatherModule.tsx
+++ b/src/modules/weather/WeatherModule.tsx
@@ -13,10 +13,10 @@ import {
IconSnowflake as Snowflake,
IconSun as Sun,
} from '@tabler/icons';
+import { useTranslation } from 'next-i18next';
import { useConfig } from '../../tools/state';
import { IModule } from '../ModuleTypes';
import { WeatherResponse } from './WeatherInterface';
-import { t } from 'i18next';
export const WeatherModule: IModule = {
title: 'Weather',
@@ -49,85 +49,87 @@ export const WeatherModule: IModule = {
// 95 *Thunderstorm: Slight or moderate
// 96, 99 *Thunderstorm with slight and heavy hail
export function WeatherIcon(props: any) {
+ const { t } = useTranslation('modules/weather-module');
+
const { code } = props;
let data: { icon: any; name: string };
switch (code) {
case 0: {
- data = { icon: Sun, name: t('modules.weather.card.weatherDescriptions.clear') };
+ data = { icon: Sun, name: t('card.weatherDescriptions.clear') };
break;
}
case 1:
case 2:
case 3: {
- data = { icon: Cloud, name: t('modules.weather.card.weatherDescriptions.mainlyClear') };
+ data = { icon: Cloud, name: t('card.weatherDescriptions.mainlyClear') };
break;
}
case 45:
case 48: {
- data = { icon: CloudFog, name: t('modules.weather.card.weatherDescriptions.fog') };
+ data = { icon: CloudFog, name: t('card.weatherDescriptions.fog') };
break;
}
case 51:
case 53:
case 55: {
- data = { icon: Cloud, name: t('modules.weather.card.weatherDescriptions.drizzle') };
+ data = { icon: Cloud, name: t('card.weatherDescriptions.drizzle') };
break;
}
case 56:
case 57: {
data = {
icon: Snowflake,
- name: t('modules.weather.card.weatherDescriptions.freezingDrizzle'),
+ name: t('card.weatherDescriptions.freezingDrizzle'),
};
break;
}
case 61:
case 63:
case 65: {
- data = { icon: CloudRain, name: t('modules.weather.card.weatherDescriptions.rain') };
+ data = { icon: CloudRain, name: t('card.weatherDescriptions.rain') };
break;
}
case 66:
case 67: {
- data = { icon: CloudRain, name: t('modules.weather.card.weatherDescriptions.freezingRain') };
+ data = { icon: CloudRain, name: t('card.weatherDescriptions.freezingRain') };
break;
}
case 71:
case 73:
case 75: {
- data = { icon: CloudSnow, name: t('modules.weather.card.weatherDescriptions.snowFall') };
+ data = { icon: CloudSnow, name: t('card.weatherDescriptions.snowFall') };
break;
}
case 77: {
- data = { icon: CloudSnow, name: t('modules.weather.card.weatherDescriptions.snowGrains') };
+ data = { icon: CloudSnow, name: t('card.weatherDescriptions.snowGrains') };
break;
}
case 80:
case 81:
case 82: {
- data = { icon: CloudRain, name: t('modules.weather.card.weatherDescriptions.rainShowers') };
+ data = { icon: CloudRain, name: t('card.weatherDescriptions.rainShowers') };
break;
}
case 85:
case 86: {
- data = { icon: CloudSnow, name: t('modules.weather.card.weatherDescriptions.snowShowers') };
+ data = { icon: CloudSnow, name: t('card.weatherDescriptions.snowShowers') };
break;
}
case 95: {
- data = { icon: CloudStorm, name: t('modules.weather.card.weatherDescriptions.thunderstorm') };
+ data = { icon: CloudStorm, name: t('card.weatherDescriptions.thunderstorm') };
break;
}
case 96:
case 99: {
data = {
icon: CloudStorm,
- name: t('modules.weather.card.weatherDescriptions.thunderstormWithHail'),
+ name: t('card.weatherDescriptions.thunderstormWithHail'),
};
break;
}
default: {
- data = { icon: QuestionMark, name: t('modules.weather.card.weatherDescriptions.unknown') };
+ data = { icon: QuestionMark, name: t('card.weatherDescriptions.unknown') };
}
}
return (
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index 2a0188c8f..f5912a598 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -4,17 +4,16 @@ import { AppProps } from 'next/app';
import { getCookie, setCookie } from 'cookies-next';
import Head from 'next/head';
import { MantineProvider, ColorScheme, ColorSchemeProvider, MantineTheme } from '@mantine/core';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
import { NotificationsProvider } from '@mantine/notifications';
import { useHotkeys } from '@mantine/hooks';
import { ModalsProvider } from '@mantine/modals';
+import { appWithTranslation } from 'next-i18next';
import { ConfigProvider } from '../tools/state';
import { theme } from '../tools/theme';
import { ColorTheme } from '../tools/color';
-import { I18nextProvider } from 'react-i18next';
-import { loadI18n } from '../translations/i18n';
-import { TranslationProvider } from '../providers/translation.provider';
-export default function App(this: any, props: AppProps & { colorScheme: ColorScheme }) {
+function App(this: any, props: AppProps & { colorScheme: ColorScheme }) {
const { Component, pageProps } = props;
const [colorScheme, setColorScheme] = useState(props.colorScheme);
@@ -72,9 +71,7 @@ export default function App(this: any, props: AppProps & { colorScheme: ColorSch
-
-
-
+
@@ -88,3 +85,5 @@ export default function App(this: any, props: AppProps & { colorScheme: ColorSch
App.getInitialProps = ({ ctx }: { ctx: GetServerSidePropsContext }) => ({
colorScheme: getCookie('color-scheme', ctx) || 'light',
});
+
+export default appWithTranslation(App);
diff --git a/src/pages/index.tsx b/src/pages/index.tsx
index 3191f6baf..8bd43e2f8 100644
--- a/src/pages/index.tsx
+++ b/src/pages/index.tsx
@@ -1,6 +1,8 @@
import { getCookie, setCookie } from 'cookies-next';
import { GetServerSidePropsContext } from 'next';
import { useEffect } from 'react';
+import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
+
import AppShelf from '../components/AppShelf/AppShelf';
import LoadConfigComponent from '../components/Config/LoadConfig';
import { Config } from '../tools/types';
@@ -13,6 +15,7 @@ import Layout from '../components/layout/Layout';
export async function getServerSideProps({
req,
res,
+ locale,
}: GetServerSidePropsContext): Promise<{ props: { config: Config } }> {
let cookie = getCookie('config-name', { req, res });
if (!cookie) {
@@ -24,7 +27,31 @@ export async function getServerSideProps({
});
cookie = 'default';
}
- return getConfig(cookie as string);
+
+ const translations = await serverSideTranslations(locale as string, [
+ 'common',
+ 'layout/app-shelf',
+ 'layout/add-service-app-shelf',
+ 'settings/common',
+ 'settings/general/theme-selector',
+ 'settings/general/config-changer',
+ 'settings/general/internationalization',
+ 'settings/general/module-enabler',
+ 'settings/general/search-engine',
+ 'settings/general/widget-positions',
+ 'settings/customization/color-selector',
+ 'settings/customization/page-appearance',
+ 'settings/customization/shade-selector',
+ 'modules/search-module',
+ 'modules/downloads-module',
+ 'modules/weather-module',
+ 'modules/ping-module',
+ 'modules/docker-module',
+ 'modules/dashdot-module',
+ 'modules/overseerr-module',
+ 'modules/common-media-cards-module',
+ ]);
+ return getConfig(cookie as string, translations);
}
export default function HomePage(props: any) {
diff --git a/src/providers/translation.provider.tsx b/src/providers/translation.provider.tsx
deleted file mode 100644
index 922c91115..000000000
--- a/src/providers/translation.provider.tsx
+++ /dev/null
@@ -1,16 +0,0 @@
-import { ReactNode, Suspense } from 'react';
-
-import { I18nextProvider } from 'react-i18next';
-import { loadI18n } from '../translations/i18n';
-
-interface TranslationProviderProps {
- children: ReactNode;
-}
-
-export const TranslationProvider = ({ children }: TranslationProviderProps) => {
- return (
-
- {children}
-
- );
-};
diff --git a/src/tools/getConfig.ts b/src/tools/getConfig.ts
index b2a5559fa..d2a4a9c08 100644
--- a/src/tools/getConfig.ts
+++ b/src/tools/getConfig.ts
@@ -1,7 +1,7 @@
import path from 'path';
import fs from 'fs';
-export function getConfig(name: string) {
+export function getConfig(name: string, props: any = undefined) {
// Check if the config file exists
const configPath = path.join(process.cwd(), 'data/configs', `${name}.json`);
if (!fs.existsSync(configPath)) {
@@ -30,6 +30,7 @@ export function getConfig(name: string) {
props: {
configName: name,
config: JSON.parse(config),
+ ...props,
},
};
}
diff --git a/src/translations/i18n.ts b/src/translations/i18n.ts
deleted file mode 100644
index ce3ad3996..000000000
--- a/src/translations/i18n.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import i18n from 'i18next';
-
-import Backend from 'i18next-http-backend';
-import LanguageDetector from 'i18next-browser-languagedetector';
-
-export const loadI18n = () => {
- i18n
- .use(LanguageDetector)
- .use(Backend)
- .init({
- fallbackLng: ['de-de', 'en-us'],
- supportedLngs: ['en-us', 'de-de'],
- lowerCaseLng: true,
- keySeparator: '.',
- backend: {
- loadPath: constructLoadPath,
- },
- debug: true,
- });
- return i18n;
-};
-
-export const convertCodeToName = (code: string) => {
- switch (code) {
- case 'en-us':
- return 'English (US)';
- case 'de-de':
- return 'German';
- default:
- return `Unknown (${code})`;
- }
-};
-
-const constructLoadPath = () => {
- return '/locales/{{lng}}.json';
-};
diff --git a/yarn.lock b/yarn.lock
index 0491e5fdc..e841d41c3 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -364,7 +364,7 @@ __metadata:
languageName: node
linkType: hard
-"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.5, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
+"@babel/runtime@npm:^7.10.2, @babel/runtime@npm:^7.12.5, @babel/runtime@npm:^7.13.10, @babel/runtime@npm:^7.14.5, @babel/runtime@npm:^7.17.2, @babel/runtime@npm:^7.18.3, @babel/runtime@npm:^7.18.6, @babel/runtime@npm:^7.18.9, @babel/runtime@npm:^7.5.5, @babel/runtime@npm:^7.8.7":
version: 7.18.9
resolution: "@babel/runtime@npm:7.18.9"
dependencies:
@@ -2005,6 +2005,16 @@ __metadata:
languageName: node
linkType: hard
+"@types/hoist-non-react-statics@npm:^3.3.1":
+ version: 3.3.1
+ resolution: "@types/hoist-non-react-statics@npm:3.3.1"
+ dependencies:
+ "@types/react": "*"
+ hoist-non-react-statics: ^3.3.0
+ checksum: 2c0778570d9a01d05afabc781b32163f28409bb98f7245c38d5eaf082416fdb73034003f5825eb5e21313044e8d2d9e1f3fe2831e345d3d1b1d20bcd12270719
+ languageName: node
+ linkType: hard
+
"@types/http-cache-semantics@npm:*":
version: 4.0.1
resolution: "@types/http-cache-semantics@npm:4.0.1"
@@ -2109,6 +2119,17 @@ __metadata:
languageName: node
linkType: hard
+"@types/react@npm:*":
+ version: 18.0.17
+ resolution: "@types/react@npm:18.0.17"
+ dependencies:
+ "@types/prop-types": "*"
+ "@types/scheduler": "*"
+ csstype: ^3.0.2
+ checksum: 18cae64f5bfd6bb58fbd8ee2ba52ec82de844f114254e26de7b513e4b86621f643f9b71d7066958cd571b0d78cb86cbceda449c5289f9349ca573df29ab69252
+ languageName: node
+ linkType: hard
+
"@types/react@npm:17.0.1":
version: 17.0.1
resolution: "@types/react@npm:17.0.1"
@@ -2128,6 +2149,13 @@ __metadata:
languageName: node
linkType: hard
+"@types/scheduler@npm:*":
+ version: 0.16.2
+ resolution: "@types/scheduler@npm:0.16.2"
+ checksum: b6b4dcfeae6deba2e06a70941860fb1435730576d3689225a421280b7742318d1548b3d22c1f66ab68e414f346a9542f29240bc955b6332c5b11e561077583bc
+ languageName: node
+ linkType: hard
+
"@types/ssh2@npm:*":
version: 1.11.5
resolution: "@types/ssh2@npm:1.11.5"
@@ -3108,6 +3136,13 @@ __metadata:
languageName: node
linkType: hard
+"core-js@npm:^3":
+ version: 3.24.1
+ resolution: "core-js@npm:3.24.1"
+ checksum: 6fb5bf0fd9e9f3e69d95616dd03332fea6758a715d2628c108b5faf17b48b0f580e90c4febb0a523c4665b0991a810de16289f86187fe79d70cc722dbd3edf0e
+ languageName: node
+ linkType: hard
+
"core-util-is@npm:~1.0.0":
version: 1.0.3
resolution: "core-util-is@npm:1.0.3"
@@ -4679,7 +4714,7 @@ __metadata:
languageName: node
linkType: hard
-"hoist-non-react-statics@npm:^3.3.1":
+"hoist-non-react-statics@npm:^3.3.0, hoist-non-react-statics@npm:^3.3.1, hoist-non-react-statics@npm:^3.3.2":
version: 3.3.2
resolution: "hoist-non-react-statics@npm:3.3.2"
dependencies:
@@ -4747,11 +4782,11 @@ __metadata:
jest: ^28.1.3
js-file-download: ^0.4.12
next: 12.1.6
+ next-i18next: ^11.3.0
prettier: ^2.7.1
prism-react-renderer: ^1.3.5
react: ^18.2.0
react-dom: ^18.2.0
- react-i18next: ^11.18.4
sharp: ^0.30.7
systeminformation: ^5.12.1
typescript: ^4.7.4
@@ -4890,6 +4925,13 @@ __metadata:
languageName: node
linkType: hard
+"i18next-fs-backend@npm:^1.1.4":
+ version: 1.1.5
+ resolution: "i18next-fs-backend@npm:1.1.5"
+ checksum: 71f6c4b0ff071676d69f1668675a68f2d72e1836dafcc8014123523bb584a78b0e4fccd16f83d7f37755b58d1dfcb4d6ad36c60b261833b509ccf20313419d9e
+ languageName: node
+ linkType: hard
+
"i18next-http-backend@npm:^1.4.1":
version: 1.4.1
resolution: "i18next-http-backend@npm:1.4.1"
@@ -4899,7 +4941,7 @@ __metadata:
languageName: node
linkType: hard
-"i18next@npm:^21.9.1":
+"i18next@npm:^21.8.13, i18next@npm:^21.9.1":
version: 21.9.1
resolution: "i18next@npm:21.9.1"
dependencies:
@@ -6246,6 +6288,24 @@ __metadata:
languageName: node
linkType: hard
+"next-i18next@npm:^11.3.0":
+ version: 11.3.0
+ resolution: "next-i18next@npm:11.3.0"
+ dependencies:
+ "@babel/runtime": ^7.18.6
+ "@types/hoist-non-react-statics": ^3.3.1
+ core-js: ^3
+ hoist-non-react-statics: ^3.3.2
+ i18next: ^21.8.13
+ i18next-fs-backend: ^1.1.4
+ react-i18next: ^11.18.0
+ peerDependencies:
+ next: ">= 10.0.0"
+ react: ">= 16.8.0"
+ checksum: fbce97a4fbf9ad846c08652471a833c7f173c3e7ddc7cafa1423625b4a684715bb85f76ae06fe9cbed3e70f12b8e78e2459e5bc1a3c3f5c517743f17648f8939
+ languageName: node
+ linkType: hard
+
"next@npm:12.1.6":
version: 12.1.6
resolution: "next@npm:12.1.6"
@@ -6925,7 +6985,7 @@ __metadata:
languageName: node
linkType: hard
-"react-i18next@npm:^11.18.4":
+"react-i18next@npm:^11.18.0":
version: 11.18.4
resolution: "react-i18next@npm:11.18.4"
dependencies: