isLikelyUserFacingString function
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;
}