From nextc-flutter
Extract user-facing strings from Flutter code into ARB locale files. Use when moving hardcoded strings to AppLocalizations, updating ARB files, or as part of the l10n pipeline. Incremental — only new/changed keys.
How this skill is triggered — by the user, by Claude, or both
Slash command
/nextc-flutter:flutter-l10n-extractThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
You extract user-facing strings from Flutter source code into ARB files and
You extract user-facing strings from Flutter source code into ARB files and
replace hardcoded strings with AppLocalizations references.
/flutter-l10n extract/flutter-l10n pipeline (step 3, after audit and harmonize)lib/l10n/app_en.arb if it exists (preserve existing keys)l10n.yaml for configuration (create if missing)docs/glossary.md for canonical termsIf l10n.yaml does not exist, create it:
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-class: AppLocalizations
preferred-supported-locales:
- en
nullable-getter: false
For each string to extract, generate a camelCase key name:
Naming conventions:
taskCardTitle, settingsScreenHeader<action><object>Button → createTaskButton, saveChangesButton<context>Error → networkError, loginFailedError<context>EmptyState → noteListEmptyState<field>Hint → emailFieldHint, searchHint<dialog><part> → deleteConfirmTitle, deleteConfirmBody<element>Label → closeButtonLabel, profileImageLabelAvoid:
text1, label2, message3settingsText)For each string:
x-translated: false
in ALL locale files for this key (triggers re-translation){
"keyName": "The user-facing string",
"@keyName": {
"description": "Context: where/why this text appears",
"x-translated": false,
"x-source": "lib/path/to/file.dart:lineNumber"
}
}
For parameterized strings:
{
"itemCount": "{count, plural, one{1 item} other{{count} items}}",
"@itemCount": {
"description": "Item count shown on dashboard",
"placeholders": {
"count": {
"type": "int",
"example": "5"
}
},
"x-translated": false,
"x-source": "lib/features/profile/profile_screen.dart:23"
}
}
Important: app_en.arb keys are always "x-translated": true for English
(since English IS the source). The x-translated: false in app_en.arb metadata
means "this key has NOT been translated into other locales yet."
Actually, to keep it simple: in app_en.arb, x-translated is not needed.
The x-translated flag only matters in non-en locale files.
For each supported locale file (app_vi.arb, app_ja.arb, etc.):
"x-translated": false"x-translated": false
(marks it for re-translation)For each extracted string, replace it in the source code:
Before:
Text('My Tasks')
After:
Text(AppLocalizations.of(context)!.myTasksTitle)
Ensure imports:
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
Handle edge cases:
const widgets → remove const keyword if adding localizationBuildContext) → flag for manual reviewTutorialContent as functions (not widgets):
change signature to accept BuildContext? context, get l10n from context
when available, fall back to English hardcoded strings when context is null.
Update all call sites to pass context.errorMessage: '...' in StateNotifiers):
these have no BuildContext. Keep hardcoded English strings and add
// TODO(l10n): map to AppLocalizations at UI layer comment. The UI layer
should map error codes to localized strings where context is available.Semantics(label: 'X. $var.')):
these need parameterized ICU keys. Flag for manual review if complex.package:<app_name>/l10n/app_localizations.dart (NOT
package:flutter_gen/gen_l10n/...) when l10n.yaml generates into lib/l10n/.flutter gen-l10n
If it fails, analyze the error and fix the ARB file (usually missing placeholders or invalid ICU syntax).
## Extraction Report
**Keys in app_en.arb:** 142 (75 new, 2 updated, 65 unchanged)
**Locale files updated:** 20
**Dart files modified:** 34
**Keys needing translation:** 77 across 19 locales
Run `/flutter-l10n translate --all` to translate new keys.
Run `/flutter-l10n status` to see coverage.
This skill is designed to be run repeatedly:
Text("...") in code → re-running extract picks up only the new stringsAfter replacing strings in all files, run a verification scan:
Text('...' with alphabetic contenthintText: '...', label: '...', title: '...' patternsSnackBar(content: Text('...' patternsAppLocalizations import vs files that had stringsReport any missed files. Common misses:
Keys in ARB files are ordered alphabetically by key name. Each key's @key
metadata block immediately follows the key. Global metadata (@@locale,
@@last_modified) comes first.
If existing translations are poor and the user wants to start over:
app_*.arb filesAppLocalizations.of(context)!.keyName calls back to hardcoded
English strings using the key→value mapping from the old app_en.arb
(recover from git if deleted)AppLocalizations imports and local variable declarationsAppLocalizations parameter from function signaturesAppLocalizations as an argumentlib/l10n/app_localizations*.dart filesflutter analyze to verify clean statenpx claudepluginhub nextc/nextc-claude --plugin nextc-flutterGuides Flutter i18n/l10n using ARB files, flutter_localizations, and BuildContext extensions. Useful for adding translations, setting up locales, or handling RTL layout.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.