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;