Skip to content

Deprecate decoupled localizations, add dart fixes - #192954

Merged
auto-submit[bot] merged 3 commits into
flutter:masterfrom
Piinks:depDesign-2
Sep 18, 2026
Merged

auto-submit[bot] merged 3 commits into
flutter:masterfrom
Piinks:depDesign-2

Conversation

@Piinks

@Piinks Piinks commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

Deprecates the Material and Cupertino localization classes and symbols in package:flutter_localizations in favor of package:material_ui/material_ui.dart and package:cupertino_ui/cupertino_ui.dart, and adds dart fix migrations.

  • Deprecates GlobalMaterialLocalizations, kMaterialSupportedLanguages, getMaterialTranslation, and all generated MaterialLocalization* classes in flutter_localizations in favor of package:material_ui/material_ui.dart.
  • Deprecates GlobalCupertinoLocalizations, kCupertinoSupportedLanguages, getCupertinoTranslation, and all generated CupertinoLocalization* classes in flutter_localizations in favor of package:cupertino_ui/cupertino_ui.dart.
  • Updates dev/tools/localization/bin/gen_localizations.dart to generate the @Deprecated annotations as well as the corresponding dart fix rules (fix_material_localizations.yaml and fix_cupertino_localizations.yaml).
  • Adds dart fix golden tests under packages/flutter_localizations/test_fixes/ and enables runFixTests('flutter_localizations') in CI.

Part of #172935

Pre-launch Checklist

If you need help, consider asking for advice on the #hackers-new channel on Discord.

If this change needs to override an active code freeze, provide a comment explaining why. The code freeze workflow can be overridden by code reviewers. See pinned issues for any active code freezes with guidance.

Note: The Flutter team is currently trialing the use of Gemini Code Assist for GitHub. Comments from the gemini-code-assist bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed.

@flutter-dashboard flutter-dashboard Bot added the CICD Run CI/CD label Sep 17, 2026
@github-actions github-actions Bot added framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages a: internationalization Supporting other languages or locales. (aka i18n) c: tech-debt Technical debt, code quality, testing, etc. f: cupertino labels Sep 17, 2026

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces automated data-driven fixes to support migrating localization classes from flutter_localizations to external packages like material_ui and cupertino_ui. It updates the localization generator to add deprecation annotations to generated classes, constructors, variables, and factory functions, and outputs YAML transform files for the dart fix tool. Feedback on the changes suggests refactoring the collection of generated class names from a List to a Set to avoid duplicate entries and duplicate transform blocks in the generated YAML. Additionally, it is recommended to use the explicit package URI package:flutter_localizations/flutter_localizations.dart instead of the relative path in the generated fix files to ensure robust resolution by the analyzer.

Comment on lines +76 to 78
String? deprecatedReplacementPackage,
List<String>? generatedClassNames,
}) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a Set instead of a List for generatedClassNames prevents duplicate class names from being added and subsequently generating duplicate transform blocks in the output YAML files.

Suggested change
String? deprecatedReplacementPackage,
List<String>? generatedClassNames,
}) {
String? deprecatedReplacementPackage,
Set<String>? generatedClassNames,
}) {
References
  1. Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)

supportedLanguagesDocMacro: widgetsSupportedLanguagesDocMacro,
)
: null;
final materialGeneratedClasses = <String>[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Initialize materialGeneratedClasses as a Set to ensure uniqueness of the generated class names.

Suggested change
final materialGeneratedClasses = <String>[];
final materialGeneratedClasses = <String>{};
References
  1. Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Gemini is right? No need to do this multiple times for the same string.

generatedClassNames: materialGeneratedClasses,
)
: null;
final cupertinoGeneratedClasses = <String>[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Initialize cupertinoGeneratedClasses as a Set to ensure uniqueness of the generated class names.

Suggested change
final cupertinoGeneratedClasses = <String>[];
final cupertinoGeneratedClasses = <String>{};
References
  1. Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)

required String baseClass,
required String supportedLanguagesConstant,
required String factoryName,
required List<String> generatedClassNames,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the parameter type of generatedClassNames to Set to match the updated caller types and guarantee uniqueness.

Suggested change
required List<String> generatedClassNames,
required Set<String> generatedClassNames,
References
  1. Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)

Comment on lines +782 to +852
final buffer = StringBuffer('''
# Copyright 2014 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# THIS FILE IS GENERATED. DO NOT EDIT BY HAND.
#
# This file is generated by:
# dart dev/tools/localization/bin/gen_localizations.dart --overwrite

# For details regarding the *Flutter Fix* feature, see
# https://flutter.dev/to/flutter-fix

# Every fix must be tested. See the
# flutter/packages/flutter_localizations/test_fixes/README.md file for
# instructions on testing these data driven fixes.

# For documentation about this file format, see
# https://dart.dev/go/data-driven-fixes.

version: 1
transforms:
- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
class: '$baseClass'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
class: '$baseClass'

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
variable: '$supportedLanguagesConstant'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
variable: '$supportedLanguagesConstant'

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
function: '$factoryName'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
function: '$factoryName'
''');

for (final className in generatedClassNames) {
buffer.write('''

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
class: '$className'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
class: '$className'
''');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using the explicit package URI package:flutter_localizations/flutter_localizations.dart instead of the relative/shortened flutter_localizations.dart is the standard practice for Flutter's data-driven fixes and ensures robust resolution by the analyzer.

  final buffer = StringBuffer('''
# Copyright 2014 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# THIS FILE IS GENERATED. DO NOT EDIT BY HAND.
#
# This file is generated by:
#   dart dev/tools/localization/bin/gen_localizations.dart --overwrite

# For details regarding the *Flutter Fix* feature, see
# https://flutter.dev/to/flutter-fix

# Every fix must be tested. See the
# flutter/packages/flutter_localizations/test_fixes/README.md file for
# instructions on testing these data driven fixes.

# For documentation about this file format, see
# https://dart.dev/go/data-driven-fixes.

version: 1
transforms:
  - title: "Migrate to '$replacementPackageUri'"
    date: 2026-09-17
    element:
      uris: ['package:flutter_localizations/flutter_localizations.dart']
      class: '$baseClass'
    changes:
      - kind: 'replacedBy'
        newElement:
          uris: ['$replacementPackageUri']
          class: '$baseClass'

  - title: "Migrate to '$replacementPackageUri'"
    date: 2026-09-17
    element:
      uris: ['package:flutter_localizations/flutter_localizations.dart']
      variable: '$supportedLanguagesConstant'
    changes:
      - kind: 'replacedBy'
        newElement:
          uris: ['$replacementPackageUri']
          variable: '$supportedLanguagesConstant'

  - title: "Migrate to '$replacementPackageUri'"
    date: 2026-09-17
    element:
      uris: ['package:flutter_localizations/flutter_localizations.dart']
      function: '$factoryName'
    changes:
      - kind: 'replacedBy'
        newElement:
          uris: ['$replacementPackageUri']
          function: '$factoryName'
''');

  for (final className in generatedClassNames) {
    buffer.write('''

  - title: "Migrate to '$replacementPackageUri'"
    date: 2026-09-17
    element:
      uris: ['package:flutter_localizations/flutter_localizations.dart']
      class: '$className'
    changes:
      - kind: 'replacedBy'
        newElement:
          uris: ['$replacementPackageUri']
          class: '$className'
''');
  }
References
  1. Suggest simplification and refactoring: Assess whether the code can be made simpler or refactored to enhance readability and maintainability. (link)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable but I'm not sure what the best practice is.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bot's claim is backwards. Across all existing fix_data files in the repo (packages/flutter/lib/fix_data/, packages/flutter_test/lib/fix_data/, packages/flutter_driver/lib/fix_data/) as well as Data-driven-Fixes.md:191, relative URIs (uris: ['flutter_driver.dart'], uris: ['material.dart']) are the standard convention for elements defined in the same package, while full package:... URIs are used for external packages in newElement.

justinmc
justinmc previously approved these changes Sep 17, 2026

@justinmc justinmc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

supportedLanguagesDocMacro: widgetsSupportedLanguagesDocMacro,
)
: null;
final materialGeneratedClasses = <String>[];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Gemini is right? No need to do this multiple times for the same string.

Comment on lines +782 to +852
final buffer = StringBuffer('''
# Copyright 2014 The Flutter Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# THIS FILE IS GENERATED. DO NOT EDIT BY HAND.
#
# This file is generated by:
# dart dev/tools/localization/bin/gen_localizations.dart --overwrite

# For details regarding the *Flutter Fix* feature, see
# https://flutter.dev/to/flutter-fix

# Every fix must be tested. See the
# flutter/packages/flutter_localizations/test_fixes/README.md file for
# instructions on testing these data driven fixes.

# For documentation about this file format, see
# https://dart.dev/go/data-driven-fixes.

version: 1
transforms:
- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
class: '$baseClass'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
class: '$baseClass'

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
variable: '$supportedLanguagesConstant'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
variable: '$supportedLanguagesConstant'

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
function: '$factoryName'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
function: '$factoryName'
''');

for (final className in generatedClassNames) {
buffer.write('''

- title: "Migrate to '$replacementPackageUri'"
date: 2026-09-17
element:
uris: ['flutter_localizations.dart']
class: '$className'
changes:
- kind: 'replacedBy'
newElement:
uris: ['$replacementPackageUri']
class: '$className'
''');
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds reasonable but I'm not sure what the best practice is.

'Use GlobalCupertinoLocalizations from package:cupertino_ui/cupertino_ui.dart instead. '
'This feature was deprecated after v3.47.0-0.0.pre.',
)
abstract class GlobalCupertinoLocalizations implements CupertinoLocalizations {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are some usages of these classes that are causing CI to fail.

Comment on lines +5 to +10
# Since these test cases live inside the `flutter_localizations` package, the
# lint `deprecated_member_use_from_same_package` is required in
# order to trigger them. Customer code (which lives outside of the
# `flutter_localizations` package) will be triggered by the analyzer warning
# `deprecated_member_use`, which is enabled by default.
- deprecated_member_use_from_same_package

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to remove this when the deprecated code gets deleted? Maybe create an issue and/or a TODO.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, test_fixes/analysis_options.yaml (with deprecated_member_use_from_same_package) and the fix_data / test_fixes files are permanent and identical packages/flutter/test_fixes/analysis_options.yaml, packages/flutter_test/test_fixes/analysis_options.yaml, and packages/flutter_driver/test_fixes/analysis_options.yaml. Per Data-driven-Fixes.md:32, dart fix rules continue to work and be tested in test_fixes/ even after deprecated APIs are removed (at which point the undefined_identifier / undefined_class diagnostic triggers the exact same fix).

This is the first time this package is adopting dart fix, which is why it stands out. :)

// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:flutter_localizations/flutter_localizations.dart';

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this import be removed from the expected output?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

package:flutter_localizations/flutter_localizations.dart is not deprecated as a whole library (since GlobalWidgetsLocalizations and WidgetsLocalization* remain in flutter_localizations). Therefore, these are element-level replacedBy transforms rather than a library-level replacedBy transform. In dart fix, element-level replacedBy transforms add the new library import (package:material_ui/material_ui.dart) so the migrated symbols resolve, and do not remove existing imports (the same behavior occurs in packages/flutter/test_fixes/material/material.dart.expect).

@flutter-dashboard

Copy link
Copy Markdown

Golden file changes have been found for this pull request. Click here to view and triage (e.g. because this is an intentional change).

If you are still iterating on this change and are not ready to resolve the images on the Flutter Gold dashboard, consider marking this PR as a draft pull request above. You will still be able to view image results on the dashboard, commenting will be silenced, and the check will not try to resolve itself until marked ready for review.

For more guidance, visit Writing a golden file test for package:flutter.

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

Changes reported for pull request #192954 at sha 9db5446

@flutter-dashboard flutter-dashboard Bot added the will affect goldens Changes to golden files label Sep 17, 2026

@QuncCccccc QuncCccccc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. Thanks for adding this!

@Piinks Piinks added the autosubmit Merge PR when tree becomes green via auto submit App label Sep 17, 2026
@auto-submit
auto-submit Bot added this pull request to the merge queue Sep 18, 2026
Merged via the queue into flutter:master with commit d704f3a Sep 18, 2026
23 checks passed
@flutter-dashboard flutter-dashboard Bot removed the autosubmit Merge PR when tree becomes green via auto submit App label Sep 18, 2026
chrisbobbe pushed a commit to rajveermalviya/zulip-flutter that referenced this pull request Sep 21, 2026
Flutter deprecated GlobalMaterialLocalizations and
GlobalCupertinoLocalizations, in favor of package:material_ui and
package:cupertino_ui:
  flutter/flutter#192954

Without this change, `tools/check analyze` fails with a
deprecated_member_use info on each of them, in
lib/generated/l10n/zulip_localizations.dart.  That has been breaking
CI on every branch, most recently:
  https://github.com/zulip/zulip-flutter/actions/runs/35577698483/job/106263172114

Both lines are written by gen-l10n itself, and come back on every
`flutter gen-l10n`.  So suppress them through gen-l10n's own `header`
option, which gets regenerated along with them.

See zulip#2463 for the migration, which waits in part on gen-l10n learning
about the new packages:
  flutter/flutter#191072

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

a: internationalization Supporting other languages or locales. (aka i18n) c: tech-debt Technical debt, code quality, testing, etc. CICD Run CI/CD f: cupertino framework flutter/packages/flutter repository. See also f: labels. p: material_ui material_ui package in flutter/packages will affect goldens Changes to golden files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants