CupertinoTabBar requires Localizations parent
Summary
#
Instances of CupertinoTabBar must have a
Localizationsparent in order to provide a localized
Semantics hint. Trying to instantiate a
CupertinoTabBar without localizations
results in an assertion such as the following:
CupertinoTabBar requires a Localizations parent in order to provide an appropriate Semantics hint
for tab indexing. A CupertinoApp provides the DefaultCupertinoLocalizations, or you can
instantiate your own Localizations.
'package:flutter/src/cupertino/bottom_tab_bar.dart':
Failed assertion: line 213 pos 7: 'localizations != null'
Context
#
To support localized semantics information,
the CupertinoTabBar requires localizations.
Before this change, the Semantics hint provided
to the CupertinoTabBar was a hard-coded String,
'tab, $index of $total'. The content of the semantics
hint was also updated from this original
String to 'Tab $index of $total' in English.
If your CupertinoTabBar is within the scope
of a CupertinoApp, the DefaultCupertinoLocalizations
is already instantiated and may suit your
needs without having to make a change to your existing code.
If your CupertinoTabBar is not within a CupertinoApp,
you may provide the localizations of
your choosing using the Localizations widget.
Migration guide
#
If you are seeing a 'localizations != null' assertion error,
make sure locale information is being
provided to your CupertinoTabBar.
Code before migration:
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MediaQuery(
data: const MediaQueryData(),
child: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
);
}
}
Code after migration (Providing localizations via the CupertinoApp):
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return CupertinoApp(
home: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
);
}
}
Code after migration (Providing localizations by using
the Localizations widget):
import 'package:flutter/cupertino.dart';
void main() => runApp(Foo());
class Foo extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Localizations(
locale: const Locale('en', 'US'),
delegates: <LocalizationsDelegate<dynamic>>[
DefaultWidgetsLocalizations.delegate,
DefaultCupertinoLocalizations.delegate,
],
child: MediaQuery(
data: const MediaQueryData(),
child: CupertinoTabBar(
items: const <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled),
label: 'Tab 1',
),
BottomNavigationBarItem(
icon: Icon(CupertinoIcons.add_circled_solid),
label: 'Tab 2',
),
],
currentIndex: 1,
),
),
);
}
}
Timeline
#
Landed in version: 1.18.0-9.0.pre
In stable release: 1.20.0
References
#API documentation:
-
CupertinoTabBar -
Localizations -
DefaultCupertinoLocalizations Semantics-
CupertinoApp - Internationalizing Flutter Apps
Relevant PR:
Unless stated otherwise, the documentation on this site reflects Flutter 3.35.5. Page last updated on 2025-10-28. View source or report an issue.