mirror of
https://github.com/ajnart/homarr.git
synced 2025-11-10 07:25:48 +01:00
🌐 fix slug and login page translations
This commit is contained in:
27
public/locales/en/authentication/login.json
Normal file
27
public/locales/en/authentication/login.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"title": "Welcome back!",
|
||||||
|
"text": "Please enter the Password",
|
||||||
|
"form": {
|
||||||
|
"fields": {
|
||||||
|
"password": {
|
||||||
|
"label": "Password",
|
||||||
|
"placeholder": "Your password"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buttons": {
|
||||||
|
"submit": "Sign in"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notifications": {
|
||||||
|
"checking": {
|
||||||
|
"title": "Checking your password",
|
||||||
|
"message": "Your password is being checked..."
|
||||||
|
},
|
||||||
|
"correct": {
|
||||||
|
"title": "Password correct, redirecting you..."
|
||||||
|
},
|
||||||
|
"wrong": {
|
||||||
|
"title": "Password is wrong, please try again."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ export default function LanguageSwitch() {
|
|||||||
const { t, i18n } = useTranslation('settings/general/internationalization');
|
const { t, i18n } = useTranslation('settings/general/internationalization');
|
||||||
const { changeLanguage } = i18n;
|
const { changeLanguage } = i18n;
|
||||||
const configLocale = getCookie('config-locale');
|
const configLocale = getCookie('config-locale');
|
||||||
const { locale, locales, push } = useRouter();
|
const { locale, locales, pathname, query, asPath, push } = useRouter();
|
||||||
const [selectedLanguage, setSelectedLanguage] = useState<string>(
|
const [selectedLanguage, setSelectedLanguage] = useState<string>(
|
||||||
(configLocale as string) ?? locale ?? 'en'
|
(configLocale as string) ?? locale ?? 'en'
|
||||||
);
|
);
|
||||||
@@ -36,7 +36,14 @@ export default function LanguageSwitch() {
|
|||||||
sameSite: 'strict',
|
sameSite: 'strict',
|
||||||
});
|
});
|
||||||
|
|
||||||
push('/', '/', { locale: value });
|
push(
|
||||||
|
{
|
||||||
|
pathname,
|
||||||
|
query,
|
||||||
|
},
|
||||||
|
asPath,
|
||||||
|
{ locale: value }
|
||||||
|
);
|
||||||
|
|
||||||
showNotification({
|
showNotification({
|
||||||
title: 'Language changed',
|
title: 'Language changed',
|
||||||
|
|||||||
@@ -1,23 +1,30 @@
|
|||||||
import { GetServerSidePropsContext } from 'next';
|
import { getCookie } from 'cookies-next';
|
||||||
import path from 'path';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
|
import { GetServerSidePropsContext } from 'next';
|
||||||
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||||
|
import path from 'path';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
import AppShelf from '../components/AppShelf/AppShelf';
|
import AppShelf from '../components/AppShelf/AppShelf';
|
||||||
import LoadConfigComponent from '../components/Config/LoadConfig';
|
import LoadConfigComponent from '../components/Config/LoadConfig';
|
||||||
import { Config } from '../tools/types';
|
|
||||||
import { useConfig } from '../tools/state';
|
|
||||||
import Layout from '../components/layout/Layout';
|
import Layout from '../components/layout/Layout';
|
||||||
|
import { getConfig } from '../tools/getConfig';
|
||||||
|
import { useConfig } from '../tools/state';
|
||||||
|
import { dashboardNamespaces } from '../tools/translation-namespaces';
|
||||||
|
import { Config } from '../tools/types';
|
||||||
|
|
||||||
export async function getServerSideProps(
|
export async function getServerSideProps({
|
||||||
context: GetServerSidePropsContext
|
req,
|
||||||
): Promise<{ props: { config: Config } }> {
|
res,
|
||||||
const configByUrl = context.query.slug;
|
locale,
|
||||||
|
query,
|
||||||
|
}: GetServerSidePropsContext): Promise<{ props: { config: Config } }> {
|
||||||
|
const configByUrl = query.slug;
|
||||||
const configPath = path.join(process.cwd(), 'data/configs', `${configByUrl}.json`);
|
const configPath = path.join(process.cwd(), 'data/configs', `${configByUrl}.json`);
|
||||||
const configExists = fs.existsSync(configPath);
|
const configExists = fs.existsSync(configPath);
|
||||||
if (!configExists) {
|
if (!configExists) {
|
||||||
// Redirect to 404
|
// Redirect to 404
|
||||||
context.res.writeHead(301, { Location: '/404' });
|
res.writeHead(301, { Location: '/404' });
|
||||||
context.res.end();
|
res.end();
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
config: {
|
config: {
|
||||||
@@ -31,13 +38,11 @@ export async function getServerSideProps(
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const config = fs.readFileSync(configPath, 'utf8');
|
|
||||||
// Print loaded config
|
const configLocale = getCookie('config-locale', { req, res });
|
||||||
return {
|
const targetLanguage = (configLocale ?? locale) as string;
|
||||||
props: {
|
const translations = await serverSideTranslations(targetLanguage, dashboardNamespaces);
|
||||||
config: JSON.parse(config),
|
return getConfig(configByUrl as string, translations);
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function HomePage(props: any) {
|
export default function HomePage(props: any) {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { migrateToIdConfig } from '../tools/migrate';
|
|||||||
import { getConfig } from '../tools/getConfig';
|
import { getConfig } from '../tools/getConfig';
|
||||||
import { useColorTheme } from '../tools/color';
|
import { useColorTheme } from '../tools/color';
|
||||||
import Layout from '../components/layout/Layout';
|
import Layout from '../components/layout/Layout';
|
||||||
|
import { dashboardNamespaces } from '../tools/translation-namespaces';
|
||||||
|
|
||||||
export async function getServerSideProps({
|
export async function getServerSideProps({
|
||||||
req,
|
req,
|
||||||
@@ -29,37 +30,10 @@ export async function getServerSideProps({
|
|||||||
configName = 'default';
|
configName = 'default';
|
||||||
}
|
}
|
||||||
|
|
||||||
const translations = await serverSideTranslations((configLocale ?? locale) as string, [
|
const translations = await serverSideTranslations(
|
||||||
'common',
|
(configLocale ?? locale) as string,
|
||||||
'layout/app-shelf',
|
dashboardNamespaces
|
||||||
'layout/add-service-app-shelf',
|
);
|
||||||
'layout/app-shelf-menu',
|
|
||||||
'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',
|
|
||||||
'settings/customization/app-width',
|
|
||||||
'settings/customization/opacity-selector',
|
|
||||||
'modules/common',
|
|
||||||
'modules/date',
|
|
||||||
'modules/calendar',
|
|
||||||
'modules/dlspeed',
|
|
||||||
'modules/usenet',
|
|
||||||
'modules/search',
|
|
||||||
'modules/torrents-status',
|
|
||||||
'modules/weather',
|
|
||||||
'modules/ping',
|
|
||||||
'modules/docker',
|
|
||||||
'modules/dashdot',
|
|
||||||
'modules/overseerr',
|
|
||||||
'modules/common-media-cards',
|
|
||||||
]);
|
|
||||||
return getConfig(configName as string, translations);
|
return getConfig(configName as string, translations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,12 +5,16 @@ import { showNotification, updateNotification } from '@mantine/notifications';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { IconCheck, IconX } from '@tabler/icons';
|
import { IconCheck, IconX } from '@tabler/icons';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
|
import { Trans, useTranslation } from 'next-i18next';
|
||||||
import { useForm } from '@mantine/form';
|
import { useForm } from '@mantine/form';
|
||||||
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
import { serverSideTranslations } from 'next-i18next/serverSideTranslations';
|
||||||
|
import { loginNamespaces } from '../tools/translation-namespaces';
|
||||||
|
|
||||||
// TODO: Add links to the wiki articles about the login process.
|
// TODO: Add links to the wiki articles about the login process.
|
||||||
export default function AuthenticationTitle() {
|
export default function AuthenticationTitle() {
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const { t } = useTranslation('authentication/login');
|
||||||
|
|
||||||
const form = useForm({
|
const form = useForm({
|
||||||
initialValues: {
|
initialValues: {
|
||||||
password: '',
|
password: '',
|
||||||
@@ -33,15 +37,12 @@ export default function AuthenticationTitle() {
|
|||||||
align="center"
|
align="center"
|
||||||
sx={(theme) => ({ fontFamily: `Greycliff CF, ${theme.fontFamily}`, fontWeight: 900 })}
|
sx={(theme) => ({ fontFamily: `Greycliff CF, ${theme.fontFamily}`, fontWeight: 900 })}
|
||||||
>
|
>
|
||||||
Welcome back!
|
{t('title')}
|
||||||
</Title>
|
</Title>
|
||||||
</Group>
|
</Group>
|
||||||
|
|
||||||
<Text color="dimmed" size="sm" align="center" mt={5}>
|
<Text color="dimmed" size="sm" align="center" mt={5}>
|
||||||
Please enter the{' '}
|
{t('text')}
|
||||||
<Anchor<'a'> href="#" size="sm" onClick={(event) => event.preventDefault()}>
|
|
||||||
password
|
|
||||||
</Anchor>
|
|
||||||
</Text>
|
</Text>
|
||||||
|
|
||||||
<Paper
|
<Paper
|
||||||
@@ -61,8 +62,8 @@ export default function AuthenticationTitle() {
|
|||||||
showNotification({
|
showNotification({
|
||||||
id: 'load-data',
|
id: 'load-data',
|
||||||
loading: true,
|
loading: true,
|
||||||
title: 'Checking your password',
|
title: t('notifications.checking.title'),
|
||||||
message: 'Your password is being checked...',
|
message: t('notifications.checking.message'),
|
||||||
autoClose: false,
|
autoClose: false,
|
||||||
disallowClose: true,
|
disallowClose: true,
|
||||||
});
|
});
|
||||||
@@ -77,7 +78,7 @@ export default function AuthenticationTitle() {
|
|||||||
updateNotification({
|
updateNotification({
|
||||||
id: 'load-data',
|
id: 'load-data',
|
||||||
color: 'teal',
|
color: 'teal',
|
||||||
title: 'Password correct, redirecting you...',
|
title: t('notifications.correct.title'),
|
||||||
message: undefined,
|
message: undefined,
|
||||||
icon: <IconCheck />,
|
icon: <IconCheck />,
|
||||||
autoClose: 1000,
|
autoClose: 1000,
|
||||||
@@ -87,7 +88,7 @@ export default function AuthenticationTitle() {
|
|||||||
updateNotification({
|
updateNotification({
|
||||||
id: 'load-data',
|
id: 'load-data',
|
||||||
color: 'red',
|
color: 'red',
|
||||||
title: 'Password is wrong, please try again.',
|
title: t('notifications.wrong.title'),
|
||||||
message: undefined,
|
message: undefined,
|
||||||
icon: <IconX />,
|
icon: <IconX />,
|
||||||
autoClose: 2000,
|
autoClose: 2000,
|
||||||
@@ -99,15 +100,15 @@ export default function AuthenticationTitle() {
|
|||||||
>
|
>
|
||||||
<PasswordInput
|
<PasswordInput
|
||||||
id="password"
|
id="password"
|
||||||
label="Password"
|
label={t('form.fields.password.label')}
|
||||||
placeholder="Your password"
|
placeholder={t('form.fields.password.placeholder')}
|
||||||
required
|
required
|
||||||
autoFocus
|
autoFocus
|
||||||
mt="md"
|
mt="md"
|
||||||
{...form.getInputProps('password')}
|
{...form.getInputProps('password')}
|
||||||
/>
|
/>
|
||||||
<Button fullWidth type="submit" mt="xl">
|
<Button fullWidth type="submit" mt="xl">
|
||||||
Sign in
|
{t('form.buttons.submit')}
|
||||||
</Button>
|
</Button>
|
||||||
</form>
|
</form>
|
||||||
</Paper>
|
</Paper>
|
||||||
@@ -115,10 +116,10 @@ export default function AuthenticationTitle() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStaticProps({ locale }: { locale: string }) {
|
export async function getServerSideProps({ locale }: { locale: string }) {
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
...(await serverSideTranslations(locale, ['common'])),
|
...(await serverSideTranslations(locale, loginNamespaces)),
|
||||||
// Will be passed to the page component as props
|
// Will be passed to the page component as props
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
35
src/tools/translation-namespaces.ts
Normal file
35
src/tools/translation-namespaces.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
export const dashboardNamespaces = [
|
||||||
|
'common',
|
||||||
|
'layout/app-shelf',
|
||||||
|
'layout/add-service-app-shelf',
|
||||||
|
'layout/app-shelf-menu',
|
||||||
|
'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',
|
||||||
|
'settings/customization/app-width',
|
||||||
|
'settings/customization/opacity-selector',
|
||||||
|
'modules/common',
|
||||||
|
'modules/date',
|
||||||
|
'modules/calendar',
|
||||||
|
'modules/dlspeed',
|
||||||
|
'modules/usenet',
|
||||||
|
'modules/search',
|
||||||
|
'modules/torrents-status',
|
||||||
|
'modules/weather',
|
||||||
|
'modules/ping',
|
||||||
|
'modules/docker',
|
||||||
|
'modules/dashdot',
|
||||||
|
'modules/overseerr',
|
||||||
|
'modules/common-media-cards',
|
||||||
|
];
|
||||||
|
|
||||||
|
export const loginNamespaces = [
|
||||||
|
'authentication/login',
|
||||||
|
];
|
||||||
Reference in New Issue
Block a user