isLikelyUserFacingString function

bool isLikelyUserFacingString(
  1. String str
)

Heuristic to check if a string is likely a user-facing translatable string.

Implementation

bool isLikelyUserFacingString(String str) {
  final s = str.trim();
  if (s.isEmpty || s.length < 2) return false;

  // ===== CRITICAL: Filter out import/part/file paths =====
  // .dart files (imports, exports, parts)
  if (s.endsWith('.dart')) return false;
  if (s.endsWith('.g.dart') || s.endsWith('.freezed.dart')) return false;

  // Relative paths
  if (s.startsWith('../') || s.startsWith('./')) return false;

  // Common file extensions
  if (s.endsWith('.json') ||
      s.endsWith('.yaml') ||
      s.endsWith('.yml') ||
      s.endsWith('.xml') ||
      s.endsWith('.arb') ||
      s.endsWith('.md') ||
      s.endsWith('.png') ||
      s.endsWith('.jpg') ||
      s.endsWith('.svg')) {
    return false;
  }

  // Package and dart imports
  if (s.startsWith('package:') || s.startsWith('dart:')) return false;

  // Part declarations
  if (s.startsWith('part of ') ||
      s.startsWith("part '") ||
      s.startsWith('part "')) {
    return false;
  }

  // ===== URL and path patterns =====
  if (s.startsWith('http://') || s.startsWith('https://') || s.contains('://'))
    return false;
  if (s.startsWith('assets/') ||
      s.startsWith('lib/') ||
      s.startsWith('images/')) return false;

  // ===== Variable interpolation =====
  // if (s.startsWith(r'$') || s.contains(r'${')) return false;

  // ===== Code patterns =====
  if (RegExp(r'^#[0-9a-fA-F]{3,8}$').hasMatch(s)) return false; // Colors
  if (RegExp(r'^[\d\-_./]+$').hasMatch(s)) return false; // path-like/numeric
  if (RegExp(r'^[A-Z0-9_]{2,}$').hasMatch(s)) return false; // CONSTANTS
  if (RegExp(r'^[a-z]+([A-Z][a-z]*)+$').hasMatch(s) && !s.contains(' '))
    return false; // camelCase
  if (RegExp(r'^[a-z][a-z0-9]*(_[a-z0-9]+)+$').hasMatch(s) && !s.contains(' '))
    return false; // snake_case

  // Provider/Bloc/Controller patterns
  if (RegExp(r'^\w*(Provider|Bloc|Cubit|Controller|Service|Repository|Widget)$')
      .hasMatch(s)) return false;

  // File paths with slashes (but no spaces - likely paths not sentences)
  if (s.contains('/') &&
      !s.contains(' ') &&
      RegExp(r'^[\w\-_.]+/[\w\-_./]+$').hasMatch(s)) return false;

  // ===== POSITIVE: Likely translatable =====
  // Contains spaces and >= 5 chars suggests a phrase/sentence
  if (s.contains(' ') && s.length >= 5) return true;
  // Capitalized short labels like "Save", "Cancel", etc.
  if (s.length <= 30 && RegExp(r'^[A-Z][a-z]+(\s+[A-Z][a-z]+)*$').hasMatch(s))
    return true;
  // Fallback for short labels with alphanumeric content
  if (s.length >= 3 && RegExp(r'^[A-Za-z0-9\s]+$').hasMatch(s)) return true;

  return false;
}