dart 镖/扑动:无法完全访问本地化

ffscu2ro  于 2022-12-06  发布在  其他
关注(0)|答案(4)|浏览(155)

我在使用Flutter + dart构建的网页中添加了本地化支持。我可以看到使用www.example.com属性可以正确显示标题S.current.name,但是当构建到小部件时,它失败了,并出现以下错误:

Assertion failed: file:///C:/dev/Adri/lib/generated/l10n.dart:21:12
_current != null
"No instance of S was loaded. Try to initialize the S delegate before accessing S.current."

我的main()和HomePage看起来像这样:

void main() {
  runApp(const HomeScreen());
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({super.key});

  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider<LanguageChangeProvider>(
      create: (context) => LanguageChangeProvider(),
      child: Builder(
        builder: (context) => MaterialApp(
            debugShowCheckedModeBanner: false,
            locale: Provider.of<LanguageChangeProvider>(context, listen: true)
                .currentLocale,
            localizationsDelegates: const [
              S.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate
            ],
            supportedLocales: S.delegate.supportedLocales,
            //title: S.current.name,
            home: MyHomePage(title: S.current.name,)),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});
  
  final String title;

  @override
  State<StatefulWidget> createState() => _MyHomePageState();
}

正如您所看到的,S.current.name可以成功地作为网站的标题传递下去:

但似乎HomeScreen的其余部分由于某种原因无法访问此S:

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          actions: [
            IconButton(
                tooltip: SELECT_LANG_HU,
                onPressed: () {
                  languageChangeProcess(context, LOCALE_HU);
                },
                icon: const Icon(Icons.language)),
            IconButton(
                tooltip: SELECT_LANG_EN,
                onPressed: () {
                  languageChangeProcess(context, LOCALE_EN);
                },
                icon: const Icon(Icons.change_circle))
          ],
          iconTheme: const IconThemeData(color: Colors.grey),
          title: Text(
            S.current.name,
            style: TextStyle(color: Colors.grey.shade600),
          ),
          flexibleSpace: Container(
            decoration: BoxDecoration(
                gradient: LinearGradient(colors: <Color>[
              Colors.teal.shade50,
              Colors.teal.shade100,
            ])),
          ),
        ),
        body: Row(
          children: [Expanded(flex: 1, child: Container())],
        ),
        drawer: Drawer(
          child: ListView(
            children: [
              DrawerHeader(
                  decoration: BoxDecoration(
                      gradient: LinearGradient(colors: <Color>[
                    Colors.teal.shade50,
                    Colors.teal.shade100
                  ])),
                  padding:
                      const EdgeInsets.only(left: 2.0, right: 2.0, top: 4.0),
                  child: const ContactCard()),
              MenuElement(Icons.person, S.current.introduction, () => {}),
              MenuElement(Icons.school, S.current.education, () => {}),
              MenuElement(
                  Icons.workspace_premium, S.current.publications, () => {}),
              MenuElement(Icons.work, S.current.workExperience, () => {}),
            ],
          ),
        ));
  }

我是不是漏掉了什么明显的东西?
在pubsec.yaml中,我添加了以下依赖项:

flutter_localizations:
    sdk: flutter
  provider: ^5.0.0
xcitsw88

xcitsw881#

  • 您是否将下面的代码添加到pubspec.yaml?
flutter:
  generate: true

如果您还没有添加它,您可以在这里查看它。fluttter.dev

ehxuflar

ehxuflar2#

I seem to have found a solution for my problem, if I initialize the localization inside main(), it will work (except for the title, but that's the least of issues).

void main() {
  runApp(ChangeNotifierProvider<LanguageChangeProvider>(
    create: (context) => LanguageChangeProvider(),
    child: Builder(
        builder: (context) => MaterialApp(
              localizationsDelegates: const [
                S.delegate,
                GlobalMaterialLocalizations.delegate,
                GlobalWidgetsLocalizations.delegate,
                GlobalCupertinoLocalizations.delegate
              ],
              debugShowCheckedModeBanner: false,
              locale: Provider.of<LanguageChangeProvider>(context, listen: true)
                  .currentLocale,
              supportedLocales: S.delegate.supportedLocales,
              home: HomeScreen(),
            )),
  ));
}

class HomeScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MyHomePage();
  }
}

Swapping between localizations works now like a charm.

6yjfywim

6yjfywim3#

Flutter Intl文档中没有提到它。本地化的字符串文件需要在主类中初始化,如下所示:

await S.load(Locale.fromSubtags(languageCode: 'en')); // You need this before everything else

然后这个:

MaterialApp(
      debugShowCheckedModeBanner: false,
      localizationsDelegates: [
        S.delegate,
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      supportedLocales: S.delegate.supportedLocales,

之后,您可以像这样使用而不需要上下文:

title: S.current.appName // Less efficient than using with context so avoid as much as possible

任何地方都有背景:

S.of(context).yourStringKey
6ljaweal

6ljaweal4#

顺便说一下,您必须从本地化文件中调用字符串,如下所示:For example: S.of(context)!.title
建议:而不是打电话

localizationsDelegates: const [
              S.delegate,
              GlobalMaterialLocalizations.delegate,
              GlobalWidgetsLocalizations.delegate,
              GlobalCupertinoLocalizations.delegate
            ],

你可以称之为:

localizationsDelegates: S.localizationsDelegates,

这是调用localizationsDelegates的简短版本

相关问题