Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,5 @@ $ svelte-i18n extract [options] <glob-pattern> [output-file]
- `--overwrite` - overwrite the content of the `output` file instead of just appending missing properties. Default: `false`.

- `-c, --config` - define the path of a `svelte.config.js` in case your svelte components need to be preprocessed.

- `--unsave` - disable the import library check. This can be used if the library name for some reason is not exactly "svelte-i18n". Default: `false`.
29 changes: 19 additions & 10 deletions src/cli/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,15 +50,19 @@ function isMessagesDefinitionCall(node: Node, methodName: string) {
);
}

function getLibImportDeclarations(ast: Ast): ImportDeclaration[] {
function getLibImportDeclarations(
ast: Ast,
ignoreImport: boolean,
): ImportDeclaration[] {
const bodyElements = [
...(ast.instance?.content.body ?? []),
...(ast.module?.content.body ?? []),
];

return bodyElements.filter(
(node) =>
node.type === 'ImportDeclaration' && node.source.value === LIB_NAME,
node.type === 'ImportDeclaration' &&
(node.source.value === LIB_NAME || ignoreImport),
) as ImportDeclaration[];
}

Expand All @@ -75,8 +79,8 @@ function getFormatSpecifiers(decl: ImportDeclaration) {
) as ImportSpecifier[];
}

export function collectFormatCalls(ast: Ast) {
const importDecls = getLibImportDeclarations(ast);
export function collectFormatCalls(ast: Ast, ignoreLib = false) {
const importDecls = getLibImportDeclarations(ast, ignoreLib);

if (importDecls.length === 0) return [];

Expand Down Expand Up @@ -112,9 +116,9 @@ export function collectFormatCalls(ast: Ast) {
// replace: (node: import("estree").BaseNode) => void;
// }, node: import("estree").BaseNode, parent: import("estree").BaseNode, key: string, index: number) => void;

export function collectMessageDefinitions(ast: Ast) {
export function collectMessageDefinitions(ast: Ast, ignoreImport = false) {
const definitions: ObjectExpression[] = [];
const defineImportDecl = getLibImportDeclarations(ast).find(
const defineImportDecl = getLibImportDeclarations(ast, ignoreImport).find(
getDefineMessagesSpecifier,
);

Expand Down Expand Up @@ -155,10 +159,13 @@ export function collectMessageDefinitions(ast: Ast) {
);
}

export function collectMessages(markup: string): Message[] {
export function collectMessages(
markup: string,
ignoreImport = false,
): Message[] {
const ast = parse(markup);
const calls = collectFormatCalls(ast);
const definitions = collectMessageDefinitions(ast);
const calls = collectFormatCalls(ast, ignoreImport);
const definitions = collectMessageDefinitions(ast, ignoreImport);

return [
...definitions.map((definition) => getObjFromExpression(definition)),
Expand Down Expand Up @@ -194,13 +201,15 @@ export function extractMessages(
markup: string,
{
accumulator = {},
ignoreImport = false,
shallow = false,
}: {
accumulator?: Record<string, any>;
ignoreImport?: boolean;
shallow?: boolean;
} = {},
) {
collectMessages(markup).forEach((messageObj) => {
collectMessages(markup, ignoreImport).forEach((messageObj) => {
let defaultValue = messageObj.default;

if (typeof defaultValue === 'undefined') {
Expand Down
6 changes: 4 additions & 2 deletions src/cli/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,13 @@ program
'path to the "svelte.config.js" file',
`${process.cwd()}/svelte.config.js`,
)
.action(async (globStr, output, { shallow, overwrite, config }) => {
.option('--unsave', 'disable the import-lib validation', false)
.action(async (globStr, output, { shallow, overwrite, config, unsave }) => {
const filesToExtract = (await glob(globStr)).filter((file) =>
file.match(/\.html|svelte$/i),
);

const ignoreImport = unsave;
const isConfigDir = await isDirectory(config);
const resolvedConfigPath = resolve(
config,
Expand Down Expand Up @@ -98,7 +100,7 @@ program
content = processed.code;
}

extractMessages(content, { accumulator, shallow });
extractMessages(content, { accumulator, shallow, ignoreImport });
} catch (e: unknown) {
if (
isSvelteError(e, 'parse-error') &&
Expand Down
24 changes: 24 additions & 0 deletions test/cli/extract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,30 @@ describe('collecting format calls', () => {
expect(calls).toHaveLength(0);
});

it('returns nothing if import from wrong lib', () => {
const ast = parse(`<script>
import { _ } from '../helpers/i18n'
let label = $_('bar')
</script>`);

const calls = collectFormatCalls(ast);

expect(calls).toHaveLength(0);
});

it('returns all format calls if import from wrong lib and import-check is disabled', () => {
const ast = parse(`<script>
import { _ } from '../helpers/i18n'
let label = $_('bar')
</script>`);

const ignoreLib = true;
const calls = collectFormatCalls(ast, ignoreLib);

expect(calls).toHaveLength(1);
expect(calls[0]).toMatchObject({ type: 'CallExpression' });
});

it('returns nothing if there are no format imports', () => {
const ast = parse(
`<script>
Expand Down