Suggest a potential valid name for the flutter project when using `flutter create` (#130900)

Fixes https://github.com/flutter/flutter/issues/109775

*If you had to change anything in the [flutter/tests] repo, include a link to the migration guide as per the [breaking change policy].*
diff --git a/packages/flutter_tools/lib/src/commands/create_base.dart b/packages/flutter_tools/lib/src/commands/create_base.dart
index 36e84c4..b0de202 100644
--- a/packages/flutter_tools/lib/src/commands/create_base.dart
+++ b/packages/flutter_tools/lib/src/commands/create_base.dart
@@ -784,12 +784,38 @@
       !_keywords.contains(name);
 }
 
+/// Returns a potential valid name from the given [name].
+///
+/// If a valid name cannot be found, returns `null`.
+@visibleForTesting
+String? potentialValidPackageName(String name){
+  String newName = name.toLowerCase();
+  if (newName.startsWith(RegExp(r'[0-9]'))) {
+    newName = '_$newName';
+  }
+  newName = newName.replaceAll('-', '_');
+  if (isValidPackageName(newName)) {
+    return newName;
+  } else {
+    return null;
+  }
+}
+
 // Return null if the project name is legal. Return a validation message if
 // we should disallow the project name.
 String? _validateProjectName(String projectName) {
   if (!isValidPackageName(projectName)) {
-    return '"$projectName" is not a valid Dart package name.\n\n'
-        'See https://dart.dev/tools/pub/pubspec#name for more information.';
+    final String? potentialValidName = potentialValidPackageName(projectName);
+
+    return <String>[
+      '"$projectName" is not a valid Dart package name.',
+      '\n\n',
+      'The name should be all lowercase, with underscores to separate words, "just_like_this".',
+      'Use only basic Latin letters and Arabic digits: [a-z0-9_].',
+      "Also, make sure the name is a valid Dart identifier—that it doesn't start with digits and isn't a reserved word.\n",
+      'See https://dart.dev/tools/pub/pubspec#name for more information.',
+      if (potentialValidName != null) '\nTry "$potentialValidName" instead.',
+    ].join();
   }
   if (_packageDependencies.contains(projectName)) {
     return "Invalid project name: '$projectName' - this will conflict with Flutter "
diff --git a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
index 1663f8c..4e54885 100644
--- a/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
+++ b/packages/flutter_tools/test/commands.shard/permeable/create_test.dart
@@ -735,10 +735,13 @@
   testUsingContext('plugin project with invalid custom project name', () async {
     expect(
       () => _createProject(projectDir,
-        <String>['--no-pub', '--template=plugin', '--project-name', 'xyz.xyz', '--platforms', 'android,ios',],
+        <String>['--no-pub', '--template=plugin', '--project-name', 'xyz-xyz', '--platforms', 'android,ios',],
         <String>[],
       ),
-      throwsToolExit(message: '"xyz.xyz" is not a valid Dart package name.'),
+      allOf(
+        throwsToolExit(message: '"xyz-xyz" is not a valid Dart package name.'),
+        throwsToolExit(message: 'Try "xyz_xyz" instead.'),
+      ),
     );
   });
 
diff --git a/packages/flutter_tools/test/general.shard/create_config_test.dart b/packages/flutter_tools/test/general.shard/create_config_test.dart
index 4d41ec9..bc48b2d 100644
--- a/packages/flutter_tools/test/general.shard/create_config_test.dart
+++ b/packages/flutter_tools/test/general.shard/create_config_test.dart
@@ -20,6 +20,18 @@
     expect(isValidPackageName('Foo_bar'), false);
   });
 
+  test('Suggests a valid Pub package name', () {
+    expect(potentialValidPackageName('92'), '_92');
+    expect(potentialValidPackageName('a-b-c'), 'a_b_c');
+
+
+    expect(potentialValidPackageName('Foo_bar'), 'foo_bar');
+    expect(potentialValidPackageName('foo-_bar'), 'foo__bar');
+
+    expect(potentialValidPackageName('잘못된 이름'), isNull, reason: 'It should return null if it cannot find a valid name.');
+
+  });
+
   test('kWindowsDrivePattern', () {
     expect(CreateBase.kWindowsDrivePattern.hasMatch(r'D:\'), isFalse);
     expect(CreateBase.kWindowsDrivePattern.hasMatch(r'z:\'), isFalse);