Skip to content
Merged
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
16 changes: 16 additions & 0 deletions .changeset/30285-i18n-walk-in-lint.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
---
'@objectstack/lint': patch
'@objectstack/cli': patch
'@objectstack/spec': patch
---

refactor(lint): the i18n translatable-key walk moves from the CLI into `@objectstack/lint`

Clause-②: no
Metadata-protocol: none

`collectExpectedEntries` — the one definition of which translation keys a stack can carry, each with the source text it translates — now lives in `@objectstack/lint` (`src/i18n-walk.ts`) and is exported from the package root with `authorWarnedTranslationGroups`, `humanizeFieldPath` and the `ExpectedEntry` / `ExpectedEntryOptions` types. It moved so a browser can run the same walk the CLI runs: Studio's translation editor builds its source-to-translation table from it. `os i18n extract` and `os lint`'s translation coverage keep reading it unchanged, through the CLI's extractor module, which keeps bundle assembly and serialization and re-exports the walk.

- No key, no skeleton and no coverage verdict changes: the walk's code moved as is.
- In a browser the walk cannot read the liveness ledger from disk, so its default leaves no translation group out. That is the same set the CLI leaves out today, because the ledger warns on no translation group; a browser caller that must honour a warned group passes `warnedGroups`.
- `@objectstack/spec`: the `action` and `view` liveness ledgers cite the walk at its new path.
2 changes: 1 addition & 1 deletion packages/cli/src/commands/i18n/extract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import {
countTranslationLeaves,
type FillStrategy,
type TranslationModuleKind,
} from '../../utils/i18n-extract.js';
} from '../../utils/i18n-bundle-extract.js';
import { authoringRuleUnionStack } from '../../utils/stack-collections.js';

const FILL_STRATEGIES: FillStrategy[] = ['empty', 'default', 'todo'];
Expand Down
631 changes: 631 additions & 0 deletions packages/cli/src/utils/i18n-bundle-extract.ts

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions packages/cli/src/utils/i18n-coverage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@
* actually attached to it, and reports the ones that are missing or empty.
*
* The expected set is **not** computed here. It comes from
* {@link collectExpectedEntries} in `i18n-extract.ts` — the same walker that
* scaffolds bundles for `os i18n extract`. That sharing is the point: this
* {@link collectExpectedEntries} in `@objectstack/lint` (`packages/lint/src/i18n-walk.ts`)
* — the same walker that scaffolds bundles for `os i18n extract`. That sharing is the point: this
* detector used to keep its own parallel walk, and the two drifted until whole
* declared surfaces were extractable but ungated — most visibly the action
* labels declared *inline on an object* (`sys_approval_request`'s
Expand Down Expand Up @@ -44,7 +44,7 @@

import { deepMerge } from '@objectstack/core';
import type { TranslationBundle, TranslationData } from '@objectstack/spec/system';
import { collectExpectedEntries, type ExpectedEntry } from './i18n-extract.js';
import { collectExpectedEntries, type ExpectedEntry } from './i18n-bundle-extract.js';

export type CoverageSeverity = 'error' | 'warning';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-block-inline-title-walk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// them in English.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-book-walk.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// measure a debt of zero while the sidebar shipped in the authoring language.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-bulk-action-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
// `helpText` here would scaffold keys `.strict()` rejects.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';

Expand Down
67 changes: 67 additions & 0 deletions packages/cli/test/i18n-bundle-extract-exports.pin.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license.

/**
* The translatable-key walk moved to `@objectstack/lint` (`i18n-walk.ts`) so a
* browser can run it; the CLI's extractor module kept everything else and
* re-exports the walk. This pins that the module still offers exactly what
* `utils/i18n-extract.ts` offered before the move, and that the walk names are
* lint's own functions, not a second copy that could drift from them.
*/

import { describe, it, expect } from 'vitest';
import * as lint from '@objectstack/lint';
import * as bundleExtract from '../src/utils/i18n-bundle-extract.js';
import type {
ExpectedEntry,
ExpectedEntryOptions,
ExtractOptions,
ExtractResult,
FillStrategy,
TranslationModuleKind,
} from '../src/utils/i18n-bundle-extract.js';

/** The runtime exports of `packages/cli/src/utils/i18n-extract.ts` before the move. */
const RUNTIME_EXPORTS_BEFORE_THE_MOVE = [
'authorWarnedTranslationGroups',
'collectExpectedEntries',
'countTranslationLeaves',
'extractTranslations',
'humanizeFieldPath',
'narrowToCommittedSections',
'parseSourceHashModule',
'renderSourceHashModule',
'renderTranslationModule',
'stackAuthoredSubtree',
'translationModulePayload',
'translationModuleSections',
];

// The type exports, held by type-check: removing one fails `typecheck`.
type TypeExportsBeforeTheMove = [
ExpectedEntry,
ExpectedEntryOptions,
ExtractOptions,
ExtractResult,
FillStrategy,
TranslationModuleKind,
];

describe('the CLI extractor module after the walk moved to @objectstack/lint', () => {
it('exports exactly the runtime names it exported before', () => {
expect(Object.keys(bundleExtract).sort()).toEqual(RUNTIME_EXPORTS_BEFORE_THE_MOVE);
});

it("re-exports lint's walk functions themselves", () => {
expect(bundleExtract.collectExpectedEntries).toBe(lint.collectExpectedEntries);
expect(bundleExtract.authorWarnedTranslationGroups).toBe(lint.authorWarnedTranslationGroups);
expect(bundleExtract.humanizeFieldPath).toBe(lint.humanizeFieldPath);
});

it('still offers its type exports, with the extract options extending the walk options', () => {
const none: TypeExportsBeforeTheMove | undefined = undefined;
const options: ExtractOptions = { warnedGroups: new Set<string>() };
const walkOptions: ExpectedEntryOptions = options;
expect(none).toBeUndefined();
expect(walkOptions.warnedGroups?.size).toBe(0);
});
});
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-contributed-nav-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { describe, it, expect } from 'vitest';
import { composeStacks, defineStack } from '@objectstack/spec';
import { TRANSLATION_TARGET_UNKNOWN, validateTranslationReferences } from '@objectstack/lint';

import { collectExpectedEntries } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { authoringRuleUnionStack } from '../src/utils/stack-collections.js';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-dataset-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
// otherwise be unaddressable.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-declared-surface-gate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@

import { describe, it, expect } from 'vitest';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { collectExpectedEntries } from '../src/utils/i18n-extract';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract';

/** Only the user's own metadata; the platform metadata-form baseline is folded away by `os lint`. */
const userIssues = (report: { issues: Array<{ source: string }> }) =>
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-duplicate-demand.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
*/

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';

/** Repeated paths in a walk, as `[path, occurrences]`, occurrences > 1 only. */
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-action-cancel-text.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
// passing alone does not prove the addresses agree.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ActionSchema } from '@objectstack/spec/ui';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* `actions[]`), the regression `i18n-walk-output-parity` exists for.
*/
import { describe, it, expect } from 'vitest';
import { collectExpectedEntries } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract.js';

const envelope = (source: string) => ({ dialect: 'template', source });

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-action-description.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// its own does not prove the addresses agree.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
// Subpath entrypoints — the root barrel re-exports only a curated set, and
// neither of these two is in it.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// addresses agree.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ActionSchema } from '@objectstack/spec/ui';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-action-submit-text.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// half passing alone does not prove the addresses agree.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ActionSchema } from '@objectstack/spec/ui';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-emitted-files.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// metadata-forms module is written at all.

import { describe, it, expect } from 'vitest';
import { extractTranslations } from '../src/utils/i18n-extract';
import { extractTranslations } from '../src/utils/i18n-bundle-extract';

/**
* Mirror of the emit rule in `src/commands/i18n/extract.ts`.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import {
extractTranslations,
narrowToCommittedSections,
translationModuleSections,
} from '../src/utils/i18n-extract.js';
} from '../src/utils/i18n-bundle-extract.js';
import {
GENERATED_SECTIONS,
HAND_AUTHORED_SECTIONS,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-inline-help-text.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
// `help` into one locale had the DEFAULT locale reported missing.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries } from '../src/utils/i18n-extract';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';

const HELP_KEY = 'objects.kpi.fields.score.help';
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-outcome-messages.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* but never seeded, the rule every other action copy key follows.
*/
import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';

const config: any = {
objects: [
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-source-hashes.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
narrowToCommittedSections,
translationModulePayload,
translationModuleSections,
} from '../src/utils/i18n-extract.js';
} from '../src/utils/i18n-bundle-extract.js';

const stack = (help: string) => ({
objects: [
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract-view-key-identity.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// the string is the thing under discussion.
import { describe, it, expect } from 'vitest';
import { expandViewContainer } from '@objectstack/spec/ui';
import { collectExpectedEntries } from '../src/utils/i18n-extract';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract';

/** Every `_views` key the extractor scaffolds for `object`, in emit order. */
function extractorViewKeys(object: string, container: any): string[] {
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-extract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
extractTranslations,
renderTranslationModule,
stackAuthoredSubtree,
} from '../src/utils/i18n-extract.js';
} from '../src/utils/i18n-bundle-extract.js';

const config: any = {
objects: [
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-approval-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-liveness-gate.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import {
authorWarnedTranslationGroups,
collectExpectedEntries,
extractTranslations,
} from '../src/utils/i18n-extract.js';
} from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { authorWarnedProperties, lintLivenessProperties } from '@objectstack/lint';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-refusal-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema, flowRefusalMessageKey } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-save-notice-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema, flowNoticeMessageKey } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-screen-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage, type CoverageIssue, type CoverageReport } from '../src/utils/i18n-coverage.js';
import {
FLOW_SCREEN_COPY_KEYS,
Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-flow-toast-option-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema, translateFlow } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-form-section-entry-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
// that leaves one untranslated.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-form-thank-you-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
// a locale that leaves an authored panel untranslated.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-form-title-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
// leaves an authored title untranslated.

import { describe, it, expect } from 'vitest';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract';
import { computeI18nCoverage } from '../src/utils/i18n-coverage';
import { ObjectTranslationDataSchema } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-hook-refusal-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ vi.mock('@objectstack/lint', async (importOriginal) => ({
authorWarnedProperties: () => new Set<string>(),
}));

import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage } from '../src/utils/i18n-coverage.js';
import { TranslationDataSchema, hookRefusalMessageKey } from '@objectstack/spec/system';

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-inline-locale-map-coverage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
import { describe, it, expect } from 'vitest';
import { resolveI18nLabel } from '@objectstack/spec/ui';
import { computeI18nCoverage, inlineLocaleText } from '../src/utils/i18n-coverage.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries, extractTranslations } from '../src/utils/i18n-bundle-extract.js';

const LOCALES = ['en', 'zh-CN', 'ja-JP'];

Expand Down
2 changes: 1 addition & 1 deletion packages/cli/test/i18n-multi-bundle-merge.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import { describe, it, expect } from 'vitest';
import { composeStacks, defineStack } from '@objectstack/spec';
import { createMemoryI18n } from '@objectstack/core';

import { collectExpectedEntries } from '../src/utils/i18n-extract.js';
import { collectExpectedEntries } from '../src/utils/i18n-bundle-extract.js';
import { computeI18nCoverage, mergeTranslationBundles } from '../src/utils/i18n-coverage.js';
import { authoringRuleUnionStack } from '../src/utils/stack-collections.js';

Expand Down
Loading
Loading