packages/plugin-intl/src/index.ts (85 lines of code) (raw):
import * as path from 'path';
import { fileURLToPath } from 'url';
import fg from 'fast-glob';
import type { Plugin } from '@ice/app/types';
const _dirname = path.dirname(fileURLToPath(import.meta.url));
interface PluginOptions {
// The key of locale content read from the window object.
localeMessagesKey?: string;
defaultLocaleKey?: string;
useCDN?: boolean;
intlSolution?: 'react-intl' | 'simple';
}
const plugin: Plugin<PluginOptions> = ({
localeMessagesKey = '__LOCALE_MESSAGES__',
defaultLocaleKey = '__DEFAULT_LOCALE__',
useCDN = false,
intlSolution = 'react-intl',
} = {}) => ({
name: 'plugin-intl',
setup: ({ generator, context, createLogger, watch }) => {
const { rootDir } = context;
const logger = createLogger('plugin-intl');
const renderLocaleEntry = (localeFiles: string[]) => {
const locales = [];
let localeExport = [];
localeFiles.forEach((file) => {
const filename = path.basename(file, path.extname(file));
// `-` is not allowed in import specifier.
const specifier = filename.replace('-', '_');
locales.push(`import ${specifier} from '@/locales/${filename}';`);
localeExport.push(`'${filename}': ${specifier},`);
});
generator.addRenderFile(
path.join(_dirname, '../templates/locales.ts.ejs'),
'locales.ts',
{
localeMessagesKey,
defaultLocaleKey,
localeImport: locales.join('\n'),
localeExport: localeExport.join('\n '),
},
);
};
const globRule = 'src/locales/*.{ts,js,json}';
// Glob all locale files, and generate runtime options.
const localeFiles = fg.sync(globRule, { cwd: rootDir });
if (localeFiles.length > 0 && !useCDN) {
// Filter the entry of locale files.
const mainEntry = localeFiles.find((file) => file.match(/index\.(ts|js|json)$/));
let runtimeSource = '';
if (mainEntry) {
runtimeSource = `@/locales/${path.basename(mainEntry)}`;
} else {
// Create a locale entry file to export all locale files.
renderLocaleEntry(localeFiles);
// Add watch event for locale files added or removed.
watch.addEvent([/src\/locales/, (event) => {
if (event === 'unlink' || event === 'add') {
const files = fg.sync(globRule, { cwd: rootDir });
renderLocaleEntry(files);
}
}]);
runtimeSource = './locales';
generator.addEntryImportAhead({
source: runtimeSource,
// @ts-ignore
}, 'both');
}
} else {
renderLocaleEntry([]);
generator.addEntryImportAhead({
source: './locales',
// @ts-ignore
}, 'both');
if (!useCDN) {
logger.warn('No locale files found, please check the `src/locales` folder.');
}
}
// Add intl export from ice.
if (intlSolution === 'simple') {
generator.addExport({
specifier: ['intl'],
source: '@ice/plugin-intl/runtime-simple',
});
} else {
generator.addExport({
specifier: ['useIntl', 'intl'],
source: '@ice/plugin-intl/runtime',
});
}
},
runtime: intlSolution === 'simple' ? '@ice/plugin-intl/runtime-simple' : '@ice/plugin-intl/runtime',
});
export default plugin;