diff --git a/docs/tooling/cli/03-commands.md b/docs/tooling/cli/03-commands.md
index 3a3af67d5d..efdf197113 100644
--- a/docs/tooling/cli/03-commands.md
+++ b/docs/tooling/cli/03-commands.md
@@ -474,15 +474,16 @@ manifest and translated message files produced by `translations export`, and
generates a TypeScript module that creates `TranslationResource` objects for each
translated ref.
+The file pattern used during export is stored in the manifest and automatically
+used by the import command.
+
```text
Usage: backstage-cli translations import [options]
Options:
- --input
Input directory containing the manifest and translated message files (default: "translations")
- --output Output path for the generated wiring module (default: "src/translations/resources.ts")
- --pattern File path pattern for message files, with {id} and {lang}
- placeholders (default: "{id}.{lang}.json")
- -h, --help display help for command
+ --input Input directory containing the manifest and translated message files (default: "translations")
+ --output Output path for the generated wiring module (default: "src/translations/resources.ts")
+ -h, --help display help for command
```
### Examples
diff --git a/packages/cli/src/modules/translations/commands/import.ts b/packages/cli/src/modules/translations/commands/import.ts
index b652eb524e..35b554ce30 100644
--- a/packages/cli/src/modules/translations/commands/import.ts
+++ b/packages/cli/src/modules/translations/commands/import.ts
@@ -31,7 +31,6 @@ import {
interface ImportOptions {
input: string;
output: string;
- pattern: string;
}
interface ManifestRefEntry {
@@ -69,8 +68,12 @@ export default async (options: ImportOptions) => {
const manifest: Manifest = await fs.readJson(manifestPath);
- // Use the pattern from manifest if available, falling back to the CLI default
- const pattern = manifest.pattern ?? options.pattern;
+ if (!manifest.pattern) {
+ throw new Error(
+ 'No pattern found in manifest.json. Re-run "backstage-cli translations export" to regenerate it.',
+ );
+ }
+ const pattern = manifest.pattern;
const parsePath = createMessagePathParser(pattern);
diff --git a/packages/cli/src/modules/translations/index.ts b/packages/cli/src/modules/translations/index.ts
index 7a7d33a28a..0d7425ad41 100644
--- a/packages/cli/src/modules/translations/index.ts
+++ b/packages/cli/src/modules/translations/index.ts
@@ -65,12 +65,6 @@ export default createCliPlugin({
default: 'src/translations/resources.ts',
description: 'Output path for the generated wiring module',
},
- pattern: {
- type: 'string',
- default: DEFAULT_MESSAGE_PATTERN,
- description:
- 'File path pattern for message files, with {id} and {lang} placeholders',
- },
})
.help()
.parse(args);
diff --git a/packages/cli/src/modules/translations/lib/discoverPackages.ts b/packages/cli/src/modules/translations/lib/discoverPackages.ts
index b8793accd5..32c54da297 100644
--- a/packages/cli/src/modules/translations/lib/discoverPackages.ts
+++ b/packages/cli/src/modules/translations/lib/discoverPackages.ts
@@ -17,22 +17,11 @@
import {
BackstagePackageJson,
PackageGraph,
- PackageRole,
+ PackageRoles,
} from '@backstage/cli-node';
import { dirname, resolve as resolvePath } from 'node:path';
import fs from 'fs-extra';
-/**
- * Package roles that can contain frontend translation refs.
- */
-const FRONTEND_ROLES: PackageRole[] = [
- 'frontend',
- 'frontend-plugin',
- 'frontend-plugin-module',
- 'web-library',
- 'common-library',
-];
-
/** A discovered package with its entry points resolved to file paths. */
export interface DiscoveredPackage {
/** The package name, e.g. '@backstage/plugin-org' */
@@ -141,7 +130,7 @@ export async function discoverFrontendPackages(
}
const role = depPkgJson.backstage?.role;
- if (role && FRONTEND_ROLES.includes(role)) {
+ if (role && isFrontendRole(role)) {
const entryPoints = resolveEntryPoints(depPkgJson, depDir, isWorkspace);
if (entryPoints.size > 0) {
result.push({ name: depName, dir: depDir, entryPoints });
@@ -208,3 +197,11 @@ function resolveEntryPoints(
return entryPoints;
}
+
+function isFrontendRole(role: string): boolean {
+ try {
+ return PackageRoles.getRoleInfo(role).platform === 'web';
+ } catch {
+ return false;
+ }
+}