mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(console): refactor language options and refine documentation l10n url logic
This commit is contained in:
parent
c7e311c344
commit
3b9cf52996
7 changed files with 70 additions and 46 deletions
|
@ -1,9 +1,8 @@
|
||||||
import { Language } from '@logto/phrases';
|
import { Optional } from '@silverhand/essentials';
|
||||||
import { conditionalString, Optional } from '@silverhand/essentials';
|
|
||||||
import { FC, ReactNode } from 'react';
|
import { FC, ReactNode } from 'react';
|
||||||
import { TFuncKey } from 'react-i18next';
|
import { TFuncKey } from 'react-i18next';
|
||||||
|
|
||||||
import useLanguage from '@/hooks/use-language';
|
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||||
import useUserPreferences from '@/hooks/use-user-preferences';
|
import useUserPreferences from '@/hooks/use-user-preferences';
|
||||||
|
|
||||||
import Contact from './components/Contact';
|
import Contact from './components/Contact';
|
||||||
|
@ -48,7 +47,7 @@ export const useSidebarMenuItems = (): {
|
||||||
const {
|
const {
|
||||||
data: { getStartedHidden },
|
data: { getStartedHidden },
|
||||||
} = useUserPreferences();
|
} = useUserPreferences();
|
||||||
const language = useLanguage();
|
const documentationUrl = useDocumentationUrl();
|
||||||
|
|
||||||
const sections: SidebarSection[] = [
|
const sections: SidebarSection[] = [
|
||||||
{
|
{
|
||||||
|
@ -110,9 +109,7 @@ export const useSidebarMenuItems = (): {
|
||||||
{
|
{
|
||||||
Icon: Document,
|
Icon: Document,
|
||||||
title: 'docs',
|
title: 'docs',
|
||||||
externalLink: `https://docs.logto.io/${conditionalString(
|
externalLink: documentationUrl,
|
||||||
language !== Language.English && language.toLowerCase()
|
|
||||||
)}`,
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
|
27
packages/console/src/hooks/use-documentation-url.ts
Normal file
27
packages/console/src/hooks/use-documentation-url.ts
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
import { useTranslation } from 'react-i18next';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Supported languages on https://docs.logto.io
|
||||||
|
*/
|
||||||
|
enum DocumentationLanguage {
|
||||||
|
English = 'en',
|
||||||
|
Chinese = 'zh-CN',
|
||||||
|
}
|
||||||
|
|
||||||
|
const documentationSiteUrl = 'https://docs.logto.io';
|
||||||
|
|
||||||
|
const useDocumentationUrl = () => {
|
||||||
|
const {
|
||||||
|
i18n: { language },
|
||||||
|
} = useTranslation();
|
||||||
|
|
||||||
|
const documentationUrl = Object.values<string>(DocumentationLanguage)
|
||||||
|
.filter((language) => language !== DocumentationLanguage.English)
|
||||||
|
.includes(language)
|
||||||
|
? `${documentationSiteUrl}/${language.toLocaleLowerCase()}`
|
||||||
|
: documentationSiteUrl;
|
||||||
|
|
||||||
|
return documentationUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default useDocumentationUrl;
|
|
@ -1,12 +0,0 @@
|
||||||
import { Language } from '@logto/phrases';
|
|
||||||
import { useTranslation } from 'react-i18next';
|
|
||||||
|
|
||||||
const useLanguage = () => {
|
|
||||||
const {
|
|
||||||
i18n: { language },
|
|
||||||
} = useTranslation();
|
|
||||||
|
|
||||||
return Object.values<string>(Language).includes(language) ? language : Language.English;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default useLanguage;
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { AdminConsoleKey, Language } from '@logto/phrases';
|
import { AdminConsoleKey } from '@logto/phrases';
|
||||||
import { AppearanceMode, Application } from '@logto/schemas';
|
import { AppearanceMode, Application } from '@logto/schemas';
|
||||||
import { demoAppApplicationId } from '@logto/schemas/lib/seeds';
|
import { demoAppApplicationId } from '@logto/schemas/lib/seeds';
|
||||||
import { conditionalString } from '@silverhand/essentials';
|
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { useNavigate } from 'react-router-dom';
|
import { useNavigate } from 'react-router-dom';
|
||||||
import useSWR from 'swr';
|
import useSWR from 'swr';
|
||||||
|
@ -19,7 +18,7 @@ import OneClick from '@/assets/images/one-click.svg';
|
||||||
import PasswordlessDark from '@/assets/images/passwordless-dark.svg';
|
import PasswordlessDark from '@/assets/images/passwordless-dark.svg';
|
||||||
import Passwordless from '@/assets/images/passwordless.svg';
|
import Passwordless from '@/assets/images/passwordless.svg';
|
||||||
import { RequestError } from '@/hooks/use-api';
|
import { RequestError } from '@/hooks/use-api';
|
||||||
import useLanguage from '@/hooks/use-language';
|
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||||
import useSettings from '@/hooks/use-settings';
|
import useSettings from '@/hooks/use-settings';
|
||||||
import { useTheme } from '@/hooks/use-theme';
|
import { useTheme } from '@/hooks/use-theme';
|
||||||
|
|
||||||
|
@ -35,7 +34,7 @@ type GetStartedMetadata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
const useGetStartedMetadata = () => {
|
const useGetStartedMetadata = () => {
|
||||||
const language = useLanguage();
|
const documentationUrl = useDocumentationUrl();
|
||||||
const { settings, updateSettings } = useSettings();
|
const { settings, updateSettings } = useSettings();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const isLightMode = theme === AppearanceMode.LightMode;
|
const isLightMode = theme === AppearanceMode.LightMode;
|
||||||
|
@ -123,21 +122,16 @@ const useGetStartedMetadata = () => {
|
||||||
isComplete: settings?.furtherReadingsChecked,
|
isComplete: settings?.furtherReadingsChecked,
|
||||||
onClick: () => {
|
onClick: () => {
|
||||||
void updateSettings({ furtherReadingsChecked: true });
|
void updateSettings({ furtherReadingsChecked: true });
|
||||||
window.open(
|
window.open(`${documentationUrl}/docs/tutorials/get-started/further-readings/`, '_blank');
|
||||||
`https://docs.logto.io/${conditionalString(
|
|
||||||
language !== Language.English && language.toLowerCase()
|
|
||||||
)}/docs/tutorials/get-started/further-readings`,
|
|
||||||
'_blank'
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
return metadataItems.filter(({ isHidden }) => !isHidden);
|
return metadataItems.filter(({ isHidden }) => !isHidden);
|
||||||
}, [
|
}, [
|
||||||
|
documentationUrl,
|
||||||
hideDemo,
|
hideDemo,
|
||||||
isLightMode,
|
isLightMode,
|
||||||
language,
|
|
||||||
navigate,
|
navigate,
|
||||||
settings?.applicationCreated,
|
settings?.applicationCreated,
|
||||||
settings?.demoChecked,
|
settings?.demoChecked,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { languageOptions } from '@logto/phrases';
|
import { Language, languageOptions } from '@logto/phrases';
|
||||||
import { AppearanceMode } from '@logto/schemas';
|
import { AppearanceMode } from '@logto/schemas';
|
||||||
import classNames from 'classnames';
|
import classNames from 'classnames';
|
||||||
import { Controller, useForm } from 'react-hook-form';
|
import { Controller, useForm } from 'react-hook-form';
|
||||||
|
@ -12,7 +12,6 @@ import FormField from '@/components/FormField';
|
||||||
import Select from '@/components/Select';
|
import Select from '@/components/Select';
|
||||||
import TabNav, { TabNavItem } from '@/components/TabNav';
|
import TabNav, { TabNavItem } from '@/components/TabNav';
|
||||||
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
import UnsavedChangesAlertModal from '@/components/UnsavedChangesAlertModal';
|
||||||
import useLanguage from '@/hooks/use-language';
|
|
||||||
import useUserPreferences, { UserPreferences } from '@/hooks/use-user-preferences';
|
import useUserPreferences, { UserPreferences } from '@/hooks/use-user-preferences';
|
||||||
import * as detailsStyles from '@/scss/details.module.scss';
|
import * as detailsStyles from '@/scss/details.module.scss';
|
||||||
|
|
||||||
|
@ -20,8 +19,15 @@ import ChangePassword from './components/ChangePassword';
|
||||||
import * as styles from './index.module.scss';
|
import * as styles from './index.module.scss';
|
||||||
|
|
||||||
const Settings = () => {
|
const Settings = () => {
|
||||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
const {
|
||||||
const defaultLanguage = useLanguage();
|
t,
|
||||||
|
i18n: { language },
|
||||||
|
} = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||||
|
|
||||||
|
const defaultLanguage = Object.values<string>(Language).includes(language)
|
||||||
|
? language
|
||||||
|
: Language.English;
|
||||||
|
|
||||||
const { data, error, update, isLoading, isLoaded } = useUserPreferences();
|
const { data, error, update, isLoading, isLoaded } = useUserPreferences();
|
||||||
const {
|
const {
|
||||||
handleSubmit,
|
handleSubmit,
|
||||||
|
|
|
@ -12,9 +12,15 @@ export enum Language {
|
||||||
Korean = 'ko-KR',
|
Korean = 'ko-KR',
|
||||||
}
|
}
|
||||||
|
|
||||||
export const languageOptions = [
|
const languageCodeAndDisplayNameMappings: Record<Language, string> = {
|
||||||
{ value: Language.English, title: 'English' },
|
[Language.English]: 'English',
|
||||||
{ value: Language.Chinese, title: '简体中文' },
|
[Language.Chinese]: '简体中文',
|
||||||
{ value: Language.Turkish, title: 'Türkçe' },
|
[Language.Turkish]: 'Türkçe',
|
||||||
{ value: Language.Korean, title: '한국어' },
|
[Language.Korean]: '한국어',
|
||||||
];
|
};
|
||||||
|
|
||||||
|
export const languageOptions = Object.entries(languageCodeAndDisplayNameMappings)
|
||||||
|
.filter((entry): entry is [Language, string] =>
|
||||||
|
Object.values<string>(Language).includes(entry[0])
|
||||||
|
)
|
||||||
|
.map(([key, value]) => ({ value: key, title: value }));
|
||||||
|
|
|
@ -16,9 +16,15 @@ export enum Language {
|
||||||
|
|
||||||
export const languageEnumGuard = z.nativeEnum(Language);
|
export const languageEnumGuard = z.nativeEnum(Language);
|
||||||
|
|
||||||
export const languageOptions = [
|
const languageCodeAndDisplayNameMappings: Record<Language, string> = {
|
||||||
{ value: Language.English, title: 'English' },
|
[Language.English]: 'English',
|
||||||
{ value: Language.Chinese, title: '简体中文' },
|
[Language.Chinese]: '简体中文',
|
||||||
{ value: Language.Turkish, title: 'Türkçe' },
|
[Language.Turkish]: 'Türkçe',
|
||||||
{ value: Language.Korean, title: '한국어' },
|
[Language.Korean]: '한국어',
|
||||||
];
|
};
|
||||||
|
|
||||||
|
export const languageOptions = Object.entries(languageCodeAndDisplayNameMappings)
|
||||||
|
.filter((entry): entry is [Language, string] =>
|
||||||
|
Object.values<string>(Language).includes(entry[0])
|
||||||
|
)
|
||||||
|
.map(([key, value]) => ({ value: key, title: value }));
|
||||||
|
|
Loading…
Reference in a new issue