create-config.ts 4.7 KB
Newer Older
P
Peter Pan 已提交
1 2
/* eslint-disable @typescript-eslint/no-explicit-any */

P
Peter Pan 已提交
3
import {consoleMessage, isServer} from '../utils';
4

5
import {Config} from '../../types';
6
import {defaultConfig} from './default-config';
P
Peter Pan 已提交
7 8 9 10 11 12 13 14 15 16 17

const deepMergeObjects = ['backend', 'detection'];
const dedupe = (names: string[]) => names.filter((v, i) => names.indexOf(v) === i);
const STATIC_LOCALE_PATH = 'static/locales';

export const createConfig = (userConfig: Config): Config => {
    if (typeof userConfig.localeSubpaths === 'string') {
        throw new Error('The localeSubpaths option has been changed to an object. Please refer to documentation.');
    }

    /*
P
Peter Pan 已提交
18 19
        Initial merge of default and user-provided config
    */
P
Peter Pan 已提交
20 21 22 23 24 25
    const combinedConfig = {
        ...defaultConfig,
        ...userConfig
    };

    /*
P
Peter Pan 已提交
26 27
        Sensible defaults to prevent user duplication
    */
P
Peter Pan 已提交
28 29 30 31 32 33 34
    combinedConfig.allLanguages = dedupe(combinedConfig.otherLanguages.concat([combinedConfig.defaultLanguage]));
    combinedConfig.whitelist = combinedConfig.allLanguages;

    const {allLanguages, defaultLanguage, localeExtension, localePath, localeStructure} = combinedConfig;

    if (isServer()) {
        const fs = eval("require('fs')");
P
Peter Pan 已提交
35
        const path = require('path'); // eslint-disable-line @typescript-eslint/no-var-requires
36 37

        const projectRoot = combinedConfig.projectRoot || process.cwd();
P
Peter Pan 已提交
38 39 40
        let serverLocalePath = localePath;

        /*
P
Peter Pan 已提交
41 42 43
            Validate defaultNS
            https://github.com/isaachinman/next-i18next/issues/358
        */
P
Peter Pan 已提交
44 45
        if (typeof combinedConfig.defaultNS === 'string') {
            const defaultFile = `/${defaultLanguage}/${combinedConfig.defaultNS}.${localeExtension}`;
46
            const defaultNSPath = path.join(projectRoot, localePath, defaultFile);
P
Peter Pan 已提交
47 48 49
            const defaultNSExists = fs.existsSync(defaultNSPath);
            if (!defaultNSExists) {
                /*
P
Peter Pan 已提交
50 51 52
                    If defaultNS doesn't exist, try to fall back to the deprecated static folder
                    https://github.com/isaachinman/next-i18next/issues/523
                */
53
                const staticDirPath = path.join(projectRoot, STATIC_LOCALE_PATH, defaultFile);
P
Peter Pan 已提交
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
                const staticDirExists = fs.existsSync(staticDirPath);

                if (staticDirExists) {
                    consoleMessage(
                        'warn',
                        'next-i18next: Falling back to /static folder, deprecated in next@9.1.*',
                        combinedConfig as Config
                    );
                    serverLocalePath = STATIC_LOCALE_PATH;
                } else if (process.env.NODE_ENV !== 'production') {
                    throw new Error(`Default namespace not found at ${defaultNSPath}`);
                }
            }
        }

        /*
P
Peter Pan 已提交
70 71
            Set server side backend
        */
P
Peter Pan 已提交
72
        combinedConfig.backend = {
73 74
            loadPath: path.join(projectRoot, `${serverLocalePath}/${localeStructure}.${localeExtension}`),
            addPath: path.join(projectRoot, `${serverLocalePath}/${localeStructure}.missing.${localeExtension}`)
P
Peter Pan 已提交
75 76 77
        };

        /*
P
Peter Pan 已提交
78 79
            Set server side preload (languages and namespaces)
        */
P
Peter Pan 已提交
80 81 82 83
        combinedConfig.preload = allLanguages;
        if (!combinedConfig.ns) {
            const getAllNamespaces = (p: string) =>
                fs.readdirSync(p).map((file: string) => file.replace(`.${localeExtension}`, ''));
84
            combinedConfig.ns = getAllNamespaces(path.join(projectRoot, `${serverLocalePath}/${defaultLanguage}`));
P
Peter Pan 已提交
85 86 87 88 89
        }
    } else {
        let clientLocalePath = localePath;

        /*
P
Peter Pan 已提交
90 91
            Remove public prefix from client site config
        */
P
Peter Pan 已提交
92 93 94 95 96
        if (localePath.startsWith('public/')) {
            clientLocalePath = localePath.replace(/^public\//, '');
        }

        /*
P
Peter Pan 已提交
97 98
            Set client side backend
        */
P
Peter Pan 已提交
99 100 101 102 103 104 105 106 107
        combinedConfig.backend = {
            loadPath: `${process.env.PUBLIC_PATH}/${clientLocalePath}/${localeStructure}.${localeExtension}`,
            addPath: `${process.env.PUBLIC_PATH}/${clientLocalePath}/${localeStructure}.missing.${localeExtension}`
        };

        combinedConfig.ns = [combinedConfig.defaultNS];
    }

    /*
P
Peter Pan 已提交
108 109
        Set fallback language to defaultLanguage in production
    */
P
Peter Pan 已提交
110 111 112 113 114 115
    if (!userConfig.fallbackLng) {
        (combinedConfig as any).fallbackLng =
            process.env.NODE_ENV === 'production' ? combinedConfig.defaultLanguage : false;
    }

    /*
P
Peter Pan 已提交
116 117
        Deep merge with overwrite - goes last
    */
P
Peter Pan 已提交
118 119 120 121 122 123 124 125 126 127 128
    deepMergeObjects.forEach(obj => {
        if ((userConfig as any)[obj]) {
            (combinedConfig as any)[obj] = {
                ...(defaultConfig as any)[obj],
                ...(userConfig as any)[obj]
            };
        }
    });

    return combinedConfig as Config;
};