gilbsgilbs/babel-plugin-i18next-extract

View on GitHub
src/config.ts

Summary

Maintainability
A
0 mins
Test Coverage
A
100%
import { resolve } from 'path';

export interface Config {
  // config options that are common with i18next
  locales: string[];
  defaultNS: string;
  pluralSeparator: string;
  contextSeparator: string;
  keySeparator: string | null;
  nsSeparator: string | null;
  transKeepBasicHtmlNodesFor: string[];
  compatibilityJSON: 'v3' | 'v4';

  // plugin-specific options
  i18nextInstanceNames: string[];
  tFunctionNames: string[];
  defaultContexts: string[];
  outputPath: ((locale: string, namespace: string) => string) | string;
  defaultValue: string | null;
  useI18nextDefaultValue: boolean | string[];
  useI18nextDefaultValueForDerivedKeys: boolean;
  keyAsDefaultValue: boolean | string[];
  keyAsDefaultValueForDerivedKeys: boolean;
  discardOldKeys: boolean;
  jsonSpace: string | number;
  enableExperimentalIcu: boolean;
  customTransComponents: readonly [string, string][];
  customUseTranslationHooks: readonly [string, string][];
  excludes: readonly string[];

  // private cache
  cache: {
    absoluteCustomTransComponents: readonly [string, string][];
    absoluteCustomHooks: readonly [string, string][];
  };
}

function resolveIfRelative(path: string): string {
  if (path.startsWith('.')) {
    return resolve(path);
  }
  return path;
}

function coalesce<T>(v: T | undefined, defaultVal: T): T {
  return v === undefined ? defaultVal : v;
}

/**
 * Given Babel options, return an initialized Config object.
 *
 * @param opts plugin options given by Babel
 */
export function parseConfig(opts: Partial<Config>): Config {
  const defaultLocales = ['en'];
  const customTransComponents = coalesce(opts.customTransComponents, []);
  const customUseTranslationHooks = coalesce(
    opts.customUseTranslationHooks,
    [],
  );

  return {
    locales: coalesce(opts.locales, defaultLocales),
    defaultNS: coalesce(opts.defaultNS, 'translation'),
    pluralSeparator: coalesce(opts.pluralSeparator, '_'),
    contextSeparator: coalesce(opts.contextSeparator, '_'),
    keySeparator: coalesce(opts.keySeparator, '.'),
    nsSeparator: coalesce(opts.nsSeparator, ':'),
    // From react-i18next: https://github.com/i18next/react-i18next/blob/90f0e44ac2710ae422f1e8b0270de95fedc6429c/react-i18next.js#L334
    transKeepBasicHtmlNodesFor: coalesce(opts.transKeepBasicHtmlNodesFor, [
      'br',
      'strong',
      'i',
      'p',
    ]),
    // FIXME we need to default to v4 in the next major release.
    compatibilityJSON: coalesce(opts.compatibilityJSON, 'v3'),

    i18nextInstanceNames: coalesce(opts.i18nextInstanceNames, [
      'i18next',
      'i18n',
    ]),
    tFunctionNames: coalesce(opts.tFunctionNames, ['t']),
    defaultContexts: coalesce(opts.defaultContexts, ['', 'male', 'female']),
    outputPath:
      typeof opts.outputPath === 'function'
        ? opts.outputPath
        : coalesce(
            opts.outputPath,
            './extractedTranslations/{{locale}}/{{ns}}.json',
          ),
    defaultValue: coalesce(opts.defaultValue, ''),
    useI18nextDefaultValue: coalesce(
      opts.useI18nextDefaultValue,
      defaultLocales,
    ),
    useI18nextDefaultValueForDerivedKeys: coalesce(
      opts.useI18nextDefaultValueForDerivedKeys,
      false,
    ),
    keyAsDefaultValue: coalesce(opts.keyAsDefaultValue, false),
    keyAsDefaultValueForDerivedKeys: coalesce(
      opts.keyAsDefaultValueForDerivedKeys,
      true,
    ),
    discardOldKeys: coalesce(opts.discardOldKeys, false),
    jsonSpace: coalesce(opts.jsonSpace, 2),
    enableExperimentalIcu: coalesce(opts.enableExperimentalIcu, false),
    customTransComponents,
    customUseTranslationHooks,
    excludes: coalesce(opts.excludes, ['^(../)*node_modules/']),
    cache: {
      absoluteCustomTransComponents: customTransComponents.map(
        ([sourceModule, importName]) => [
          resolveIfRelative(sourceModule),
          importName,
        ],
      ),
      absoluteCustomHooks: customUseTranslationHooks.map(
        ([sourceModule, importName]) => [
          resolveIfRelative(sourceModule),
          importName,
        ],
      ),
    },
  };
}