@@ -569,18 +569,32 @@ function isInNonLinguiTaggedTemplate(node: TSESTree.Node): boolean {
569569 return false
570570}
571571
572- /** Checks if a string is in an import/export statement (module path). */
573- function isInImportExport ( node : TSESTree . Node ) : boolean {
574- let current : TSESTree . Node | undefined = node . parent ?? undefined
572+ /**
573+ * Checks if a string is an import/export module source specifier.
574+ *
575+ * Only returns true for the module path in:
576+ * - import "module-path"
577+ * - import x from "module-path"
578+ * - export * from "module-path"
579+ * - export { x } from "module-path"
580+ *
581+ * Does NOT return true for strings inside exported declarations:
582+ * - export function foo() { return "Hello World" } ← "Hello World" should be checked
583+ */
584+ function isImportExportSource ( node : TSESTree . Node ) : boolean {
585+ const parent = node . parent
586+ if ( parent === undefined ) {
587+ return false
588+ }
575589
576- while ( current !== undefined ) {
577- switch ( current . type ) {
578- case AST_NODE_TYPES . ImportDeclaration :
579- case AST_NODE_TYPES . ExportAllDeclaration :
580- case AST_NODE_TYPES . ExportNamedDeclaration :
581- return true
582- }
583- current = current . parent ?? undefined
590+ // Check if this literal is the `source` property of an import/export
591+ switch ( parent . type ) {
592+ case AST_NODE_TYPES . ImportDeclaration :
593+ return parent . source === node
594+ case AST_NODE_TYPES . ExportAllDeclaration :
595+ return parent . source === node
596+ case AST_NODE_TYPES . ExportNamedDeclaration :
597+ return parent . source === node
584598 }
585599
586600 return false
@@ -804,8 +818,8 @@ export const noUnlocalizedStrings = createRule<[Options], MessageId>({
804818 return
805819 }
806820
807- // Import/export path
808- if ( isInImportExport ( node ) ) {
821+ // Import/export module source specifier
822+ if ( isImportExportSource ( node ) ) {
809823 return
810824 }
811825
0 commit comments