import { DevidedPagePath, Lang, AllLang } from '@growi/core'; import { GetServerSideProps, GetServerSidePropsContext } from 'next'; import { SSRConfig, UserConfig } from 'next-i18next'; import * as nextI18NextConfig from '^/config/next-i18next.config'; import { SupportedActionType } from '~/interfaces/activity'; import { CrowiRequest } from '~/interfaces/crowi-request'; import { GrowiThemes } from '~/interfaces/theme'; export type CommonProps = { namespacesRequired: string[], // i18next currentPathname: string, appTitle: string, siteUrl: string, confidential: string, theme: GrowiThemes, customTitleTemplate: string, csrfToken: string, isContainerFluid: boolean, growiVersion: string, isMaintenanceMode: boolean, redirectDestination: string | null, customizedLogoSrc?: string, } & Partial; // eslint-disable-next-line max-len export const getServerSideCommonProps: GetServerSideProps = async(context: GetServerSidePropsContext) => { const req: CrowiRequest = context.req as CrowiRequest; const { crowi } = req; const { appService, configManager, customizeService, } = crowi; const url = new URL(context.resolvedUrl, 'http://example.com'); const currentPathname = decodeURI(url.pathname); const isMaintenanceMode = appService.isMaintenanceMode(); // eslint-disable-next-line max-len, no-nested-ternary const redirectDestination = !isMaintenanceMode && currentPathname === '/maintenance' ? '/' : isMaintenanceMode && !currentPathname.match('/admin/*') && !(currentPathname === '/maintenance') ? '/maintenance' : null; const isDefaultLogo = crowi.configManager.getConfig('crowi', 'customize:isDefaultLogo'); const props: CommonProps = { namespacesRequired: ['translation'], currentPathname, appTitle: appService.getAppTitle(), siteUrl: configManager.getConfig('crowi', 'app:siteUrl'), // DON'T USE appService.getSiteUrl() confidential: appService.getAppConfidential() || '', theme: configManager.getConfig('crowi', 'customize:theme'), customTitleTemplate: customizeService.customTitleTemplate, csrfToken: req.csrfToken(), isContainerFluid: configManager.getConfig('crowi', 'customize:isContainerFluid') ?? false, growiVersion: crowi.version, isMaintenanceMode, redirectDestination, customizedLogoSrc: isDefaultLogo ? null : configManager.getConfig('crowi', 'customize:customizedLogoSrc'), }; return { props }; }; export const getNextI18NextConfig = async( // 'serverSideTranslations' method should be given from Next.js Page // because importing it in this file causes https://github.com/isaachinman/next-i18next/issues/1545 serverSideTranslations: ( initialLocale: string, namespacesRequired?: string[] | undefined, configOverride?: UserConfig | null, extraLocales?: string[] | false ) => Promise, context: GetServerSidePropsContext, namespacesRequired?: string[] | undefined, preloadAllLang = false, ): Promise => { const req: CrowiRequest = context.req as CrowiRequest; const { crowi, user } = req; const { configManager } = crowi; // determine language const locale = user?.lang ?? configManager.getConfig('crowi', 'app:globalLang') as Lang ?? Lang.en_US; const namespaces = ['commons']; if (namespacesRequired != null) { namespaces.push(...namespacesRequired); } // TODO: deprecate 'translation.json' in the future else { namespaces.push('translation'); } return serverSideTranslations(locale, namespaces, nextI18NextConfig, preloadAllLang ? AllLang : false); }; /** * Generate whole title string for the specified title * @param props * @param title */ export const useCustomTitle = (props: CommonProps, title: string): string => { return props.customTitleTemplate .replace('{{sitename}}', props.appTitle) .replace('{{page}}', title) .replace('{{pagepath}}', title) .replace('{{pagename}}', title); }; /** * Generate whole title string for the specified page path * @param props * @param pagePath */ export const useCustomTitleForPage = (props: CommonProps, pagePath: string): string => { const dPagePath = new DevidedPagePath(pagePath, true, true); return props.customTitleTemplate .replace('{{sitename}}', props.appTitle) .replace('{{pagepath}}', pagePath) .replace('{{page}}', dPagePath.latter) // for backward compatibility .replace('{{pagename}}', dPagePath.latter); };