ensureFlutterLocalizationsDependency function

bool ensureFlutterLocalizationsDependency(
  1. String directoryPath
)

Check if flutter_localizations dependency exists in pubspec.yaml If not, add it automatically

Implementation

bool ensureFlutterLocalizationsDependency(String directoryPath) {
  try {
    // Find pubspec.yaml file
    final pubspecFile = _findPubspecFile(directoryPath);

    if (pubspecFile == null) {
      print('\u001b[31mError: Could not find pubspec.yaml file\u001b[0m');
      print('\u001b[33mSearched in directory: $directoryPath\u001b[0m');
      return false;
    }

    print('\u001b[36mℹ️  Found pubspec.yaml at: ${pubspecFile.path}\u001b[0m');
    final content = pubspecFile.readAsStringSync();
    final lines = content.split('\n');

    // First find the dependencies section
    final dependenciesIndex =
        lines.indexWhere((line) => line.trim() == 'dependencies:');
    if (dependenciesIndex == -1) {
      print(
          '\u001b[31mError: Could not find dependencies section in pubspec.yaml\u001b[0m');
      return false;
    }

    // Analyze existing dependencies - scan the entire dependencies section
    bool hasFlutter = false;
    bool hasFlutterLocalizations = false;
    bool hasIntl = false;
    int lastSdkDependencyIndex = dependenciesIndex;
    String? intlVersion;

    // Go through each line after dependencies to find existing deps
    for (var i = dependenciesIndex + 1; i < lines.length; i++) {
      final line = lines[i].trim();

      // Stop if we hit another top-level section (no leading spaces and ends with colon)
      if (line.isNotEmpty && !lines[i].startsWith(' ') && line.endsWith(':')) {
        break;
      }

      // Skip blank lines and comments
      if (line.isEmpty || line.startsWith('#')) {
        continue;
      }

      // Check for specific dependencies
      if (line.startsWith('flutter:')) {
        hasFlutter = true;
        // Check next line to verify it's an SDK dependency
        if (i + 1 < lines.length && lines[i + 1].trim() == 'sdk: flutter') {
          lastSdkDependencyIndex = i + 1;
        }
      } else if (line.startsWith('flutter_localizations:')) {
        hasFlutterLocalizations = true;
        // Check next line to verify it's an SDK dependency
        if (i + 1 < lines.length && lines[i + 1].trim() == 'sdk: flutter') {
          lastSdkDependencyIndex = i + 1;
        }
      } else if (line.startsWith('intl:')) {
        hasIntl = true;
        // Extract version if present
        final versionMatch =
            RegExp(r'^intl:\s*[\^~]?(\d+\.\d+\.\d+)').firstMatch(line);
        if (versionMatch != null) {
          intlVersion = versionMatch.group(1);
        }
      }
    }

    // Print current status
    print('\u001b[36mDependency status:\u001b[0m');
    print('\u001b[36m  flutter: ${hasFlutter ? "✓" : "✗"}\u001b[0m');
    print(
        '\u001b[36m  flutter_localizations: ${hasFlutterLocalizations ? "✓" : "✗"}\u001b[0m');
    print(
        '\u001b[36m  intl: ${hasIntl ? "✓" : "✗"}${intlVersion != null ? " (v$intlVersion)" : ""}\u001b[0m');

    bool needsWrite = false;
    final indentation = '  ';
    final sdkIndentation = '$indentation  ';
    var insertIndex = lastSdkDependencyIndex;

    // Handle Flutter SDK if missing
    if (!hasFlutter) {
      insertIndex++;
      lines.insert(insertIndex, '${indentation}flutter:');
      insertIndex++;
      lines.insert(insertIndex, '${sdkIndentation}sdk: flutter');
      lastSdkDependencyIndex = insertIndex;
      needsWrite = true;
      print('\u001b[32m✓ Added flutter SDK dependency\u001b[0m');
    }

    // Handle flutter_localizations if missing
    if (!hasFlutterLocalizations) {
      insertIndex = lastSdkDependencyIndex + 1;
      lines.insert(insertIndex, '${indentation}flutter_localizations:');
      insertIndex++;
      lines.insert(insertIndex, '${sdkIndentation}sdk: flutter');
      lastSdkDependencyIndex = insertIndex;
      needsWrite = true;
      print('\u001b[32m✓ Added flutter_localizations dependency\u001b[0m');
    }

    // Handle intl if missing or needs version update
    // Compare version numbers properly - need at least 0.18.0
    bool needsIntlUpdate = !hasIntl;
    if (hasIntl && intlVersion != null) {
      // Parse version numbers for proper comparison
      final currentVersion = _parseVersion(intlVersion);
      final minVersion = _parseVersion('0.20.2');
      needsIntlUpdate = _compareVersions(currentVersion, minVersion) < 0;
    }

    if (needsIntlUpdate) {
      insertIndex = lastSdkDependencyIndex + 1;
      final intlLine =
          '${indentation}intl: ^0.20.2  # Required for internationalization';
      if (hasIntl) {
        // Replace existing intl line
        for (var i = 0; i < lines.length; i++) {
          if (lines[i].trim().startsWith('intl:')) {
            lines[i] = intlLine;
            break;
          }
        }
      } else {
        lines.insert(insertIndex, intlLine);
      }
      needsWrite = true;
      print(
          '\u001b[32m✓ ${hasIntl ? "Updated" : "Added"} intl dependency to v0.19.0\u001b[0m');
    }

    if (needsWrite) {
      // Write changes back to file
      try {
        pubspecFile.writeAsStringSync(lines.join('\n'));
        print(
            '\u001b[32m✓ Dependencies updated successfully in ${pubspecFile.path}\u001b[0m');
        print(
            '\u001b[36mℹ️  Run "flutter pub get" to update dependencies\u001b[0m');

        // Verify the write was successful by reading back
        final verifyContent = pubspecFile.readAsStringSync();
        final hasIntlCheck = verifyContent.contains('intl:');
        final hasFlutterLocCheck =
            verifyContent.contains('flutter_localizations:');

        if (hasIntlCheck && hasFlutterLocCheck) {
          print(
              '\u001b[32m✓ Verified: Dependencies successfully written to file\u001b[0m');
        } else {
          print(
              '\u001b[33m⚠️  Warning: Dependencies may not have been written correctly\u001b[0m');
          print(
              '\u001b[33m   intl found: $hasIntlCheck, flutter_localizations found: $hasFlutterLocCheck\u001b[0m');
        }
      } catch (writeError) {
        print('\u001b[31mError writing to pubspec.yaml: $writeError\u001b[0m');
        print('\u001b[33mFile path: ${pubspecFile.path}\u001b[0m');
        return false;
      }
    } else {
      print(
          '\u001b[32m✓ All required dependencies are already present\u001b[0m');
    }

    return true;
  } catch (e) {
    print('\u001b[31mError adding dependencies: $e\u001b[0m');
    print('\u001b[33mDirectory: $directoryPath\u001b[0m');
    return false;
  }
}