@bdayadev/flutter-ultra-mcp 1.11.7 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/dart/ultra_flutter/pubspec.yaml +1 -1
- package/dart/ultra_flutter_devtools/pubspec.yaml +1 -1
- package/package.json +1 -1
- package/skills/UPSTREAM-LICENSES +75 -0
- package/skills/add-integration-test/SKILL.md +179 -0
- package/skills/add-unit-test/SKILL.md +141 -0
- package/skills/add-widget-preview/SKILL.md +166 -0
- package/skills/add-widget-test/SKILL.md +171 -0
- package/skills/apply-architecture-best-practices/SKILL.md +182 -0
- package/skills/build-cli-app/SKILL.md +200 -0
- package/skills/build-responsive-layout/SKILL.md +160 -0
- package/skills/collect-coverage/SKILL.md +168 -0
- package/skills/fix-layout-issues/SKILL.md +152 -0
- package/skills/fix-runtime-errors/SKILL.md +197 -0
- package/skills/generate-test-mocks/SKILL.md +177 -0
- package/skills/implement-json-serialization/SKILL.md +168 -0
- package/skills/migrate-to-checks-package/SKILL.md +156 -0
- package/skills/resolve-package-conflicts/SKILL.md +140 -0
- package/skills/run-static-analysis/SKILL.md +120 -0
- package/skills/setup-declarative-routing/SKILL.md +293 -0
- package/skills/setup-localization/SKILL.md +247 -0
- package/skills/use-http-package/SKILL.md +189 -0
- package/skills/use-pattern-matching/SKILL.md +169 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: run-static-analysis
|
|
3
|
+
description: Execute `dart analyze` to identify warnings and errors, and use `dart fix --apply` to automatically resolve mechanical lint issues. Use during development to ensure code quality and before committing changes.
|
|
4
|
+
last_modified: Fri, 24 Apr 2026 15:09:34 GMT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Analyzing and Fixing Dart Code
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Analysis Configuration](#analysis-configuration)
|
|
12
|
+
- [Diagnostic Suppression](#diagnostic-suppression)
|
|
13
|
+
- [Workflow: Executing Static Analysis](#workflow-executing-static-analysis)
|
|
14
|
+
- [Workflow: Applying Automated Fixes](#workflow-applying-automated-fixes)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
|
|
17
|
+
## Analysis Configuration
|
|
18
|
+
|
|
19
|
+
Configure the Dart analyzer using the `analysis_options.yaml` file located at the package root.
|
|
20
|
+
|
|
21
|
+
- **Base Configuration:** Always include a standard rule set (e.g., `package:lints/recommended.yaml` or `package:flutter_lints/flutter.yaml`) using the `include:` directive.
|
|
22
|
+
- **Strict Type Checks:** Enable strict type checks under the `analyzer: language:` node to prevent implicit downcasts and dynamic inferences. Set `strict-casts: true`, `strict-inference: true`, and `strict-raw-types: true`.
|
|
23
|
+
- **Linter Rules:** Explicitly enable or disable specific rules under the `linter: rules:` node. Use a key-value map (`rule_name: true/false`) when overriding included rules, or a list (`- rule_name`) when defining a fresh set. Do not mix list and map syntax in the same `rules` block.
|
|
24
|
+
- **Formatter Configuration:** Configure `dart format` behavior under the `formatter:` node. Set `page_width` (default 80) and `trailing_commas` (`automate` or `preserve`).
|
|
25
|
+
- **Analyzer Plugins:** Enable custom diagnostics by adding plugins under the `analyzer: plugins:` node. Ensure the plugin package is added as a `dev_dependency` in `pubspec.yaml`.
|
|
26
|
+
|
|
27
|
+
## Diagnostic Suppression
|
|
28
|
+
|
|
29
|
+
When a diagnostic (lint or warning) yields a false positive or applies to generated code, suppress it explicitly.
|
|
30
|
+
|
|
31
|
+
- **File-level Exclusion:** Use the `analyzer: exclude:` node in `analysis_options.yaml` to exclude entire files or directories (e.g., `**/*.g.dart`) using glob patterns.
|
|
32
|
+
- **File-level Suppression:** Add `// ignore_for_file: <diagnostic_code>` at the top of a Dart file to suppress specific diagnostics for the entire file. Use `// ignore_for_file: type=lint` to suppress all linter rules.
|
|
33
|
+
- **Line-level Suppression:** Add `// ignore: <diagnostic_code>` on the line directly above the offending code, or appended to the end of the offending line.
|
|
34
|
+
- **Pubspec Suppression:** Add `# ignore: <diagnostic_code>` above the offending line in `pubspec.yaml` files (e.g., `# ignore: sort_pub_dependencies`).
|
|
35
|
+
- **Plugin Diagnostics:** Prefix the diagnostic code with the plugin name when suppressing plugin-specific issues (e.g., `// ignore: some_plugin/some_code`).
|
|
36
|
+
|
|
37
|
+
## Workflow: Executing Static Analysis
|
|
38
|
+
|
|
39
|
+
Use this workflow to identify type-related bugs, style violations, and potential runtime errors.
|
|
40
|
+
|
|
41
|
+
**Task Progress:**
|
|
42
|
+
|
|
43
|
+
- [ ] 1. Verify `analysis_options.yaml` exists at the project root.
|
|
44
|
+
- [ ] 2. Run the analyzer using the `analyze_files` MCP tool (if available) or the CLI command `dart analyze <target_directory>`.
|
|
45
|
+
- [ ] 3. Review the diagnostic output.
|
|
46
|
+
- [ ] 4. If info-level issues must be treated as failures, append the `--fatal-infos` flag.
|
|
47
|
+
- [ ] 5. Resolve reported errors manually or proceed to the Automated Fixes workflow.
|
|
48
|
+
|
|
49
|
+
## Workflow: Applying Automated Fixes
|
|
50
|
+
|
|
51
|
+
Use this workflow to resolve outdated API usages, apply quick fixes, and migrate code (e.g., Dart 3 migrations).
|
|
52
|
+
|
|
53
|
+
**Task Progress:**
|
|
54
|
+
|
|
55
|
+
- [ ] 1. Execute a dry run to preview proposed changes using the `dart_fix` MCP tool or CLI command `dart fix --dry-run`.
|
|
56
|
+
- [ ] 2. Review the proposed fixes to ensure they align with the intended architecture.
|
|
57
|
+
- [ ] 3. If additional fixes are required, verify that the corresponding linter rules are enabled in `analysis_options.yaml`.
|
|
58
|
+
- [ ] 4. Apply the fixes using the `dart_fix` MCP tool or CLI command `dart fix --apply`.
|
|
59
|
+
- [ ] 5. Format the modified code using the `dart_format` MCP tool or CLI command `dart format .`.
|
|
60
|
+
- [ ] 6. Run the static analysis workflow to verify all diagnostics are resolved.
|
|
61
|
+
|
|
62
|
+
## Examples
|
|
63
|
+
|
|
64
|
+
### Comprehensive `analysis_options.yaml`
|
|
65
|
+
|
|
66
|
+
```yaml
|
|
67
|
+
include: package:flutter_lints/recommended.yaml
|
|
68
|
+
|
|
69
|
+
analyzer:
|
|
70
|
+
exclude:
|
|
71
|
+
- '**/*.g.dart'
|
|
72
|
+
- 'lib/generated/**'
|
|
73
|
+
language:
|
|
74
|
+
strict-casts: true
|
|
75
|
+
strict-inference: true
|
|
76
|
+
strict-raw-types: true
|
|
77
|
+
errors:
|
|
78
|
+
todo: ignore
|
|
79
|
+
invalid_assignment: warning
|
|
80
|
+
missing_return: error
|
|
81
|
+
|
|
82
|
+
linter:
|
|
83
|
+
rules:
|
|
84
|
+
avoid_shadowing_type_parameters: false
|
|
85
|
+
await_only_futures: true
|
|
86
|
+
use_super_parameters: true
|
|
87
|
+
|
|
88
|
+
formatter:
|
|
89
|
+
page_width: 100
|
|
90
|
+
trailing_commas: preserve
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Inline Diagnostic Suppression
|
|
94
|
+
|
|
95
|
+
```dart
|
|
96
|
+
// Suppress for the entire file
|
|
97
|
+
// ignore_for_file: unused_local_variable, dead_code
|
|
98
|
+
|
|
99
|
+
void processData() {
|
|
100
|
+
// Suppress for a specific line
|
|
101
|
+
// ignore: invalid_assignment
|
|
102
|
+
int x = '';
|
|
103
|
+
|
|
104
|
+
const y = 10; // ignore: constant_identifier_names
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Flutter Ultra Integration
|
|
109
|
+
|
|
110
|
+
Run analysis and auto-fix via flutter-ultra tools:
|
|
111
|
+
|
|
112
|
+
- `mcp__plugin_flutter_flutter-ultra-build__analyze` — Run dart analyze with full diagnostics
|
|
113
|
+
- `mcp__plugin_flutter_flutter-ultra-build__fix` — Apply dart fix --apply for automated lint fixes
|
|
114
|
+
- `mcp__plugin_flutter_flutter-ultra-build__fix_preview` — Preview fixes before applying
|
|
115
|
+
- `mcp__plugin_flutter_flutter-ultra-build__format` — Format code after fixes
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
> **Attribution:** This skill is vendored from [dart-lang/skills](https://github.com/dart-lang/skills) (BSD-3-Clause).
|
|
120
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,293 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-declarative-routing
|
|
3
|
+
description: Configure `MaterialApp.router` using a package like `go_router` for advanced URL-based navigation. Use when developing web applications or mobile apps that require specific deep linking and browser history support.
|
|
4
|
+
last_modified: Tue, 21 Apr 2026 21:08:03 GMT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Implementing Routing and Deep Linking
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Core Concepts](#core-concepts)
|
|
12
|
+
- [Workflow: Initializing the Application and Router](#workflow-initializing-the-application-and-router)
|
|
13
|
+
- [Workflow: Configuring Platform Deep Linking](#workflow-configuring-platform-deep-linking)
|
|
14
|
+
- [Workflow: Implementing Nested Navigation](#workflow-implementing-nested-navigation)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
|
|
17
|
+
## Core Concepts
|
|
18
|
+
|
|
19
|
+
Use the `go_router` package for declarative routing in Flutter. It provides a robust API for complex routing scenarios, deep linking, and nested navigation.
|
|
20
|
+
|
|
21
|
+
- **GoRouter**: The central configuration object defining the application's route tree.
|
|
22
|
+
- **GoRoute**: A standard route mapping a URL path to a Flutter screen.
|
|
23
|
+
- **ShellRoute / StatefulShellRoute**: Wraps child routes in a persistent UI shell (e.g., a `BottomNavigationBar`). `StatefulShellRoute` maintains the state of parallel navigation branches.
|
|
24
|
+
- **Path URL Strategy**: Removes the default `#` fragment from web URLs, essential for clean deep linking across platforms.
|
|
25
|
+
|
|
26
|
+
## Workflow: Initializing the Application and Router
|
|
27
|
+
|
|
28
|
+
Follow this workflow to bootstrap a new Flutter application with `go_router` and configure the root routing mechanism.
|
|
29
|
+
|
|
30
|
+
### Task Progress
|
|
31
|
+
|
|
32
|
+
- [ ] Create the Flutter application.
|
|
33
|
+
- [ ] Add the `go_router` dependency.
|
|
34
|
+
- [ ] Configure the URL strategy for web/deep linking.
|
|
35
|
+
- [ ] Implement the `GoRouter` configuration.
|
|
36
|
+
- [ ] Bind the router to `MaterialApp.router`.
|
|
37
|
+
|
|
38
|
+
### 1. Scaffold the Application
|
|
39
|
+
|
|
40
|
+
Run the following commands to create the app and add the required routing package:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
flutter create <app-name>
|
|
44
|
+
cd <app-name>
|
|
45
|
+
flutter pub add go_router
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### 2. Configure the Router
|
|
49
|
+
|
|
50
|
+
Define a top-level `GoRouter` instance. Handle authentication or state-based routing using the `redirect` parameter.
|
|
51
|
+
|
|
52
|
+
```dart
|
|
53
|
+
import 'package:flutter/material.dart';
|
|
54
|
+
import 'package:go_router/go_router.dart';
|
|
55
|
+
import 'package:flutter_web_plugins/url_strategy.dart';
|
|
56
|
+
|
|
57
|
+
void main() {
|
|
58
|
+
// Use path URL strategy to remove the '#' from web URLs
|
|
59
|
+
usePathUrlStrategy();
|
|
60
|
+
runApp(const MyApp());
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
final GoRouter _router = GoRouter(
|
|
64
|
+
initialLocation: '/',
|
|
65
|
+
routes: [
|
|
66
|
+
GoRoute(
|
|
67
|
+
path: '/',
|
|
68
|
+
builder: (context, state) => const HomeScreen(),
|
|
69
|
+
routes: [
|
|
70
|
+
GoRoute(
|
|
71
|
+
path: 'details/:id',
|
|
72
|
+
builder: (context, state) => DetailsScreen(id: state.pathParameters['id']!),
|
|
73
|
+
),
|
|
74
|
+
],
|
|
75
|
+
),
|
|
76
|
+
],
|
|
77
|
+
errorBuilder: (context, state) => ErrorScreen(error: state.error),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
class MyApp extends StatelessWidget {
|
|
81
|
+
const MyApp({super.key});
|
|
82
|
+
|
|
83
|
+
@override
|
|
84
|
+
Widget build(BuildContext context) {
|
|
85
|
+
return MaterialApp.router(
|
|
86
|
+
routerConfig: _router,
|
|
87
|
+
title: 'Routing App',
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Workflow: Configuring Platform Deep Linking
|
|
94
|
+
|
|
95
|
+
Configure the native platforms to intercept specific URLs and route them into the Flutter application.
|
|
96
|
+
|
|
97
|
+
### Task Progress
|
|
98
|
+
|
|
99
|
+
- [ ] Determine target platforms (iOS, Android, or both).
|
|
100
|
+
- [ ] Apply conditional configuration for Android (Manifest + Asset Links).
|
|
101
|
+
- [ ] Apply conditional configuration for iOS (Plist + Entitlements + AASA).
|
|
102
|
+
- [ ] Run validator -> review errors -> fix.
|
|
103
|
+
|
|
104
|
+
### If configuring for Android:
|
|
105
|
+
|
|
106
|
+
1. **Modify `AndroidManifest.xml`**: Add the intent filter inside the `<activity>` tag for `.MainActivity`.
|
|
107
|
+
|
|
108
|
+
```xml
|
|
109
|
+
<intent-filter android:autoVerify="true">
|
|
110
|
+
<action android:name="android.intent.action.VIEW" />
|
|
111
|
+
<category android:name="android.intent.category.DEFAULT" />
|
|
112
|
+
<category android:name="android.intent.category.BROWSABLE" />
|
|
113
|
+
<data android:scheme="http" android:host="yourdomain.com" />
|
|
114
|
+
<data android:scheme="https" />
|
|
115
|
+
</intent-filter>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
2. **Host `assetlinks.json`**: Serve the following JSON at `https://yourdomain.com/.well-known/assetlinks.json`.
|
|
119
|
+
|
|
120
|
+
```json
|
|
121
|
+
[
|
|
122
|
+
{
|
|
123
|
+
"relation": ["delegate_permission/common.handle_all_urls"],
|
|
124
|
+
"target": {
|
|
125
|
+
"namespace": "android_app",
|
|
126
|
+
"package_name": "com.yourcompany.yourapp",
|
|
127
|
+
"sha256_cert_fingerprints": ["YOUR_SHA256_FINGERPRINT"]
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
]
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### If configuring for iOS:
|
|
134
|
+
|
|
135
|
+
1. **Modify `Info.plist`**: Opt-in to Flutter's default deep link handler.
|
|
136
|
+
_Note: If using a third-party deep linking plugin (e.g., `app_links`), set this to `NO` to prevent conflicts._
|
|
137
|
+
|
|
138
|
+
```xml
|
|
139
|
+
<key>FlutterDeepLinkingEnabled</key>
|
|
140
|
+
<true/>
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
2. **Modify `Runner.entitlements`**: Add the associated domain.
|
|
144
|
+
|
|
145
|
+
```xml
|
|
146
|
+
<key>com.apple.developer.associated-domains</key>
|
|
147
|
+
<array>
|
|
148
|
+
<string>applinks:yourdomain.com</string>
|
|
149
|
+
</array>
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
3. **Host `apple-app-site-association`**: Serve the following JSON (without a `.json` extension) at `https://yourdomain.com/.well-known/apple-app-site-association`.
|
|
153
|
+
|
|
154
|
+
```json
|
|
155
|
+
{
|
|
156
|
+
"applinks": {
|
|
157
|
+
"apps": [],
|
|
158
|
+
"details": [
|
|
159
|
+
{
|
|
160
|
+
"appIDs": ["TEAM_ID.com.yourcompany.yourapp"],
|
|
161
|
+
"paths": ["*"],
|
|
162
|
+
"components": [{ "/": "/*" }]
|
|
163
|
+
}
|
|
164
|
+
]
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Validation Loop
|
|
170
|
+
|
|
171
|
+
Run validator -> review errors -> fix.
|
|
172
|
+
|
|
173
|
+
- **Android**: Test using ADB.
|
|
174
|
+
```bash
|
|
175
|
+
adb shell 'am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://yourdomain.com/details/123"' com.yourcompany.yourapp
|
|
176
|
+
```
|
|
177
|
+
- **iOS**: Test using `xcrun` on a booted simulator.
|
|
178
|
+
```bash
|
|
179
|
+
xcrun simctl openurl booted https://yourdomain.com/details/123
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
## Workflow: Implementing Nested Navigation
|
|
183
|
+
|
|
184
|
+
Use `StatefulShellRoute` to implement persistent UI shells (like a bottom navigation bar) that maintain the state of their child routes.
|
|
185
|
+
|
|
186
|
+
### Task Progress
|
|
187
|
+
|
|
188
|
+
- [ ] Define `StatefulShellRoute.indexedStack` in the `GoRouter` configuration.
|
|
189
|
+
- [ ] Create `StatefulShellBranch` instances for each navigation tab.
|
|
190
|
+
- [ ] Implement the shell widget using `StatefulNavigationShell`.
|
|
191
|
+
|
|
192
|
+
```dart
|
|
193
|
+
final GoRouter _router = GoRouter(
|
|
194
|
+
initialLocation: '/home',
|
|
195
|
+
routes: [
|
|
196
|
+
StatefulShellRoute.indexedStack(
|
|
197
|
+
builder: (context, state, navigationShell) {
|
|
198
|
+
return ScaffoldWithNavBar(navigationShell: navigationShell);
|
|
199
|
+
},
|
|
200
|
+
branches: [
|
|
201
|
+
StatefulShellBranch(
|
|
202
|
+
routes: [
|
|
203
|
+
GoRoute(
|
|
204
|
+
path: '/home',
|
|
205
|
+
builder: (context, state) => const HomeScreen(),
|
|
206
|
+
),
|
|
207
|
+
],
|
|
208
|
+
),
|
|
209
|
+
StatefulShellBranch(
|
|
210
|
+
routes: [
|
|
211
|
+
GoRoute(
|
|
212
|
+
path: '/settings',
|
|
213
|
+
builder: (context, state) => const SettingsScreen(),
|
|
214
|
+
),
|
|
215
|
+
],
|
|
216
|
+
),
|
|
217
|
+
],
|
|
218
|
+
),
|
|
219
|
+
],
|
|
220
|
+
);
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Examples
|
|
224
|
+
|
|
225
|
+
### High-Fidelity Shell Widget Implementation
|
|
226
|
+
|
|
227
|
+
Implement the UI shell that consumes the `StatefulNavigationShell` to handle branch switching.
|
|
228
|
+
|
|
229
|
+
```dart
|
|
230
|
+
class ScaffoldWithNavBar extends StatelessWidget {
|
|
231
|
+
const ScaffoldWithNavBar({
|
|
232
|
+
required this.navigationShell,
|
|
233
|
+
super.key,
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
final StatefulNavigationShell navigationShell;
|
|
237
|
+
|
|
238
|
+
void _goBranch(int index) {
|
|
239
|
+
navigationShell.goBranch(
|
|
240
|
+
index,
|
|
241
|
+
// Support navigating to the initial location when tapping the active tab.
|
|
242
|
+
initialLocation: index == navigationShell.currentIndex,
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
@override
|
|
247
|
+
Widget build(BuildContext context) {
|
|
248
|
+
return Scaffold(
|
|
249
|
+
body: navigationShell,
|
|
250
|
+
bottomNavigationBar: NavigationBar(
|
|
251
|
+
selectedIndex: navigationShell.currentIndex,
|
|
252
|
+
onDestinationSelected: _goBranch,
|
|
253
|
+
destinations: const [
|
|
254
|
+
NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
|
|
255
|
+
NavigationDestination(icon: Icon(Icons.settings), label: 'Settings'),
|
|
256
|
+
],
|
|
257
|
+
),
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
### Programmatic Navigation
|
|
264
|
+
|
|
265
|
+
Use the `context.go()` and `context.push()` extension methods provided by `go_router`.
|
|
266
|
+
|
|
267
|
+
```dart
|
|
268
|
+
// Replaces the current route stack with the target route (Declarative)
|
|
269
|
+
context.go('/details/123');
|
|
270
|
+
|
|
271
|
+
// Pushes the target route onto the existing stack (Imperative)
|
|
272
|
+
context.push('/details/123');
|
|
273
|
+
|
|
274
|
+
// Navigates using a named route and path parameters
|
|
275
|
+
context.goNamed('details', pathParameters: {'id': '123'});
|
|
276
|
+
|
|
277
|
+
// Pops the current route
|
|
278
|
+
context.pop();
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Flutter Ultra Integration
|
|
282
|
+
|
|
283
|
+
After configuring routes, test navigation in the running app:
|
|
284
|
+
|
|
285
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__launch_app` — Launch the app to test routing
|
|
286
|
+
- `mcp__plugin_flutter_flutter-ultra-browser__navigate` — Navigate to specific routes in the browser (web targets)
|
|
287
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__screenshot` — Capture each route for visual verification
|
|
288
|
+
- `mcp__plugin_flutter_flutter-ultra-runtime__get_runtime_errors` — Check for routing errors (missing routes, redirect loops)
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
> **Attribution:** This skill is vendored from [flutter/skills](https://github.com/flutter/skills) (BSD-3-Clause).
|
|
293
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|
|
@@ -0,0 +1,247 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: setup-localization
|
|
3
|
+
description: Add `flutter_localizations` and `intl` dependencies, enable "generate true" in `pubspec.yaml`, and create an `l10n.yaml` configuration file. Use when initializing localization support for a new Flutter project.
|
|
4
|
+
last_modified: Tue, 21 Apr 2026 21:27:35 GMT
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Internationalizing Flutter Applications
|
|
8
|
+
|
|
9
|
+
## Contents
|
|
10
|
+
|
|
11
|
+
- [Core Concepts](#core-concepts)
|
|
12
|
+
- [Setup Workflow](#setup-workflow)
|
|
13
|
+
- [Implementation Workflow](#implementation-workflow)
|
|
14
|
+
- [Advanced Formatting](#advanced-formatting)
|
|
15
|
+
- [Examples](#examples)
|
|
16
|
+
|
|
17
|
+
## Core Concepts
|
|
18
|
+
|
|
19
|
+
Flutter handles internationalization (i18n) and localization (l10n) via the `flutter_localizations` and `intl` packages. The standard approach uses App Resource Bundle (`.arb`) files to define localized strings, which are then compiled into a generated `AppLocalizations` class for type-safe access within the widget tree.
|
|
20
|
+
|
|
21
|
+
## Setup Workflow
|
|
22
|
+
|
|
23
|
+
Copy and track this checklist when initializing internationalization in a Flutter project:
|
|
24
|
+
|
|
25
|
+
- [ ] **Task Progress**
|
|
26
|
+
- [ ] 1. Add dependencies to `pubspec.yaml`.
|
|
27
|
+
- [ ] 2. Enable the `generate` flag.
|
|
28
|
+
- [ ] 3. Create the `l10n.yaml` configuration file.
|
|
29
|
+
- [ ] 4. Configure `MaterialApp` or `CupertinoApp`.
|
|
30
|
+
|
|
31
|
+
### 1. Add Dependencies
|
|
32
|
+
|
|
33
|
+
Add the required localization packages to the project. Execute the following commands in the terminal:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
flutter pub add flutter_localizations --sdk=flutter
|
|
37
|
+
flutter pub add intl:any
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Verify your `pubspec.yaml` includes the following under `dependencies`:
|
|
41
|
+
|
|
42
|
+
```yaml
|
|
43
|
+
dependencies:
|
|
44
|
+
flutter:
|
|
45
|
+
sdk: flutter
|
|
46
|
+
flutter_localizations:
|
|
47
|
+
sdk: flutter
|
|
48
|
+
intl: any
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### 2. Enable Code Generation
|
|
52
|
+
|
|
53
|
+
Open `pubspec.yaml` and enable the `generate` flag within the `flutter` section to automate localization tasks:
|
|
54
|
+
|
|
55
|
+
```yaml
|
|
56
|
+
flutter:
|
|
57
|
+
generate: true
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 3. Create Configuration File
|
|
61
|
+
|
|
62
|
+
Create a new file named `l10n.yaml` in the root directory of the Flutter project. Define the input directory, template file, and output file:
|
|
63
|
+
|
|
64
|
+
```yaml
|
|
65
|
+
arb-dir: lib/l10n
|
|
66
|
+
template-arb-file: app_en.arb
|
|
67
|
+
output-localization-file: app_localizations.dart
|
|
68
|
+
synthetic-package: true
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 4. Configure the App Entry Point
|
|
72
|
+
|
|
73
|
+
Import the generated localizations and the `flutter_localizations` library in your `main.dart`. Inject the delegates and supported locales into your `MaterialApp` or `CupertinoApp`.
|
|
74
|
+
|
|
75
|
+
```dart
|
|
76
|
+
import 'package:flutter_localizations/flutter_localizations.dart';
|
|
77
|
+
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // Adjust path if synthetic-package is false
|
|
78
|
+
|
|
79
|
+
// ... inside build method
|
|
80
|
+
return MaterialApp(
|
|
81
|
+
localizationsDelegates: const [
|
|
82
|
+
AppLocalizations.delegate,
|
|
83
|
+
GlobalMaterialLocalizations.delegate,
|
|
84
|
+
GlobalWidgetsLocalizations.delegate,
|
|
85
|
+
GlobalCupertinoLocalizations.delegate,
|
|
86
|
+
],
|
|
87
|
+
supportedLocales: const [
|
|
88
|
+
Locale('en'), // English
|
|
89
|
+
Locale('es'), // Spanish
|
|
90
|
+
],
|
|
91
|
+
home: const MyHomePage(),
|
|
92
|
+
);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Implementation Workflow
|
|
96
|
+
|
|
97
|
+
Follow this workflow when adding or modifying localized content.
|
|
98
|
+
|
|
99
|
+
### 1. Define ARB Files
|
|
100
|
+
|
|
101
|
+
- **If creating NEW content:** Add the base string to the template file (`lib/l10n/app_en.arb`). Include a description for context.
|
|
102
|
+
- **If EDITING existing content:** Locate the key in all supported `.arb` files and update the values.
|
|
103
|
+
|
|
104
|
+
```json
|
|
105
|
+
{
|
|
106
|
+
"helloWorld": "Hello World!",
|
|
107
|
+
"@helloWorld": {
|
|
108
|
+
"description": "The conventional newborn programmer greeting"
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Create corresponding files for other locales (e.g., `app_es.arb`):
|
|
114
|
+
|
|
115
|
+
```json
|
|
116
|
+
{
|
|
117
|
+
"helloWorld": "¡Hola Mundo!"
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### 2. Generate Localization Classes
|
|
122
|
+
|
|
123
|
+
Run the following command to trigger code generation:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
flutter pub get
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
_Feedback Loop:_ Run validator -> review terminal output for ARB syntax errors -> fix missing commas or mismatched placeholders -> re-run `flutter pub get`.
|
|
130
|
+
|
|
131
|
+
### 3. Consume Localized Strings
|
|
132
|
+
|
|
133
|
+
Access the localized strings in your widget tree using `AppLocalizations.of(context)`. Ensure the widget calling this is a descendant of `MaterialApp`.
|
|
134
|
+
|
|
135
|
+
```dart
|
|
136
|
+
Text(AppLocalizations.of(context)!.helloWorld)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Advanced Formatting
|
|
140
|
+
|
|
141
|
+
Use placeholders for dynamic data, plurals, and conditional selects.
|
|
142
|
+
|
|
143
|
+
### Placeholders
|
|
144
|
+
|
|
145
|
+
Define parameters within curly braces and specify their type in the metadata object.
|
|
146
|
+
|
|
147
|
+
```json
|
|
148
|
+
"hello": "Hello {userName}",
|
|
149
|
+
"@hello": {
|
|
150
|
+
"description": "A message with a single parameter",
|
|
151
|
+
"placeholders": {
|
|
152
|
+
"userName": {
|
|
153
|
+
"type": "String",
|
|
154
|
+
"example": "Bob"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
### Plurals
|
|
161
|
+
|
|
162
|
+
Use the `plural` syntax to handle quantity-based string variations. The `other` case is mandatory.
|
|
163
|
+
|
|
164
|
+
```json
|
|
165
|
+
"nWombats": "{count, plural, =0{no wombats} =1{1 wombat} other{{count} wombats}}",
|
|
166
|
+
"@nWombats": {
|
|
167
|
+
"description": "A plural message",
|
|
168
|
+
"placeholders": {
|
|
169
|
+
"count": {
|
|
170
|
+
"type": "num",
|
|
171
|
+
"format": "compact"
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### Selects
|
|
178
|
+
|
|
179
|
+
Use the `select` syntax for conditional strings, such as gendered text.
|
|
180
|
+
|
|
181
|
+
```json
|
|
182
|
+
"pronoun": "{gender, select, male{he} female{she} other{they}}",
|
|
183
|
+
"@pronoun": {
|
|
184
|
+
"description": "A gendered message",
|
|
185
|
+
"placeholders": {
|
|
186
|
+
"gender": {
|
|
187
|
+
"type": "String"
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
## Examples
|
|
194
|
+
|
|
195
|
+
### Complete `l10n.yaml`
|
|
196
|
+
|
|
197
|
+
```yaml
|
|
198
|
+
arb-dir: lib/l10n
|
|
199
|
+
template-arb-file: app_en.arb
|
|
200
|
+
output-localization-file: app_localizations.dart
|
|
201
|
+
synthetic-package: true
|
|
202
|
+
use-escaping: true
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Complete Widget Implementation
|
|
206
|
+
|
|
207
|
+
```dart
|
|
208
|
+
import 'package:flutter/material.dart';
|
|
209
|
+
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
210
|
+
|
|
211
|
+
class GreetingWidget extends StatelessWidget {
|
|
212
|
+
final String userName;
|
|
213
|
+
final int notificationCount;
|
|
214
|
+
|
|
215
|
+
const GreetingWidget({
|
|
216
|
+
super.key,
|
|
217
|
+
required this.userName,
|
|
218
|
+
required this.notificationCount,
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
@override
|
|
222
|
+
Widget build(BuildContext context) {
|
|
223
|
+
final l10n = AppLocalizations.of(context)!;
|
|
224
|
+
|
|
225
|
+
return Column(
|
|
226
|
+
children: [
|
|
227
|
+
Text(l10n.hello(userName)),
|
|
228
|
+
Text(l10n.nWombats(notificationCount)),
|
|
229
|
+
],
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Flutter Ultra Integration
|
|
236
|
+
|
|
237
|
+
Generate and validate localization files with these tools:
|
|
238
|
+
|
|
239
|
+
- `mcp__plugin_flutter_flutter-ultra-build__flutter_gen_l10n` — Generate localization Dart code from ARB files
|
|
240
|
+
- `mcp__plugin_flutter_flutter-ultra-build__list_missing_translations` — Find missing translation keys across locales
|
|
241
|
+
- `mcp__plugin_flutter_flutter-ultra-build__arb_add_key` — Add a new translation key to all ARB files
|
|
242
|
+
- `mcp__plugin_flutter_flutter-ultra-build__arb_diff` — Compare ARB files to find drift between locales
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
> **Attribution:** This skill is vendored from [flutter/skills](https://github.com/flutter/skills) (BSD-3-Clause).
|
|
247
|
+
> Synced by `scripts/sync-upstream-skills.mjs`. Do not edit manually — changes will be overwritten on next sync.
|