You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用flutter_intl本地化Flutter中OnBoardingViewModel静态列表字符串

解决OnBoardingViewModel静态列表本地化的方案

方案1:ViewModel存储本地化Key,Widget层完成文本转换

ViewModel只维护本地化对应的标识(用枚举避免硬编码字符串),在有context的Widget中完成文本的本地化转换:

  1. 定义枚举对应本地化项:
enum OnBoardingLocalKey {
  title1,
  subtitle1,
  title2,
  subtitle2,
}
  1. 修改ViewModel,存储图片和本地化标识:
class OnBoardingViewModel with ChangeNotifier {
  final List<Map<String, dynamic>> onBoardingRawData = [
    {
      'image': ImageManager.onBoardingImage1,
      'titleKey': OnBoardingLocalKey.title1,
      'subtitleKey': OnBoardingLocalKey.subtitle1,
    },
    {
      'image': ImageManager.onBoardingImage2,
      'titleKey': OnBoardingLocalKey.title2,
      'subtitleKey': OnBoardingLocalKey.subtitle2,
    }
  ];
  // 其他代码...
}
  1. 在Widget的build方法中借助context生成最终的页面内容列表:
@override
Widget build(BuildContext context) {
  final viewModel = Provider.of<OnBoardingViewModel>(context);
  final localizedPages = viewModel.onBoardingRawData.map((rawData) {
    final titleKey = rawData['titleKey'] as OnBoardingLocalKey;
    final subtitleKey = rawData['subtitleKey'] as OnBoardingLocalKey;

    String getTitle() {
      switch(titleKey) {
        case OnBoardingLocalKey.title1:
          return S.of(context).onBoardingTitle1;
        case OnBoardingLocalKey.title2:
          return S.of(context).onBoardingTitle2;
        default:
          return '';
      }
    }

    String getSubtitle() {
      switch(subtitleKey) {
        case OnBoardingLocalKey.subtitle1:
          return S.of(context).onBoardingSubTitle1;
        case OnBoardingLocalKey.subtitle2:
          return S.of(context).onBoardingSubTitle2;
        default:
          return '';
      }
    }

    return OnBoardingPageContent(
      image: rawData['image'],
      title: getTitle(),
      subtitle: getSubtitle(),
    );
  }).toList();

  // 使用localizedPages构建UI
  return ...;
}

方案2:ViewModel提供生成本地化列表的方法,依赖Widget传入context

让ViewModel不直接存储静态列表,而是提供一个接收context的方法,在Widget层调用生成本地化后的列表:

class OnBoardingViewModel with ChangeNotifier {
  List<OnBoardingPageContent> generateLocalizedPages(BuildContext context) {
    return [
      OnBoardingPageContent(
        image: ImageManager.onBoardingImage1,
        title: S.of(context).onBoardingTitle1,
        subtitle: S.of(context).onBoardingSubTitle1,
      ),
      OnBoardingPageContent(
        image: ImageManager.onBoardingImage2,
        title: S.of(context).onBoardingTitle2,
        subtitle: S.of(context).onBoardingSubTitle2,
      )
    ];
  }
  // 其他代码...
}

在Widget中调用:

@override
Widget build(BuildContext context) {
  final viewModel = Provider.of<OnBoardingViewModel>(context);
  final onBoardingPages = viewModel.generateLocalizedPages(context);
  // 构建UI
  return ...;
}

方案3:监听语言变化,ViewModel动态更新列表(进阶)

如果需要语言切换时自动刷新列表,可以通过监听系统locale变化,让ViewModel动态更新内容(ViewModel不持有context):

  1. ViewModel中添加locale管理和列表更新逻辑:
class OnBoardingViewModel with ChangeNotifier {
  late Locale _currentLocale;
  List<OnBoardingPageContent> _onBoardingPages = [];

  List<OnBoardingPageContent> get onBoardingPages => _onBoardingPages;

  OnBoardingViewModel(Locale initialLocale) {
    _currentLocale = initialLocale;
    _refreshPages();
  }

  void updateLocale(Locale newLocale) {
    if (_currentLocale != newLocale) {
      _currentLocale = newLocale;
      _refreshPages();
      notifyListeners();
    }
  }

  void _refreshPages() async {
    // 通过flutter_intl的delegate加载对应locale的本地化资源
    final localizedStrings = await S.delegate.load(_currentLocale);
    _onBoardingPages = [
      OnBoardingPageContent(
        image: ImageManager.onBoardingImage1,
        title: localizedStrings.onBoardingTitle1,
        subtitle: localizedStrings.onBoardingSubTitle1,
      ),
      OnBoardingPageContent(
        image: ImageManager.onBoardingImage2,
        title: localizedStrings.onBoardingTitle2,
        subtitle: localizedStrings.onBoardingSubTitle2,
      )
    ];
  }
}
  1. 在Widget中监听locale变化并通知ViewModel:
class MyOnBoardingScreen extends StatefulWidget {
  const MyOnBoardingScreen({super.key});

  @override
  State<MyOnBoardingScreen> createState() => _MyOnBoardingScreenState();
}

class _MyOnBoardingScreenState extends State<MyOnBoardingScreen> {
  late OnBoardingViewModel _viewModel;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
    final currentLocale = Localizations.localeOf(context);
    _viewModel = Provider.of<OnBoardingViewModel>(context, listen: false);
    _viewModel.updateLocale(currentLocale);
  }

  @override
  Widget build(BuildContext context) {
    final onBoardingPages = Provider.of<OnBoardingViewModel>(context).onBoardingPages;
    // 构建UI
    return ...;
  }
}

为什么之前的方法不可行?

  • 直接传key字符串调用S.of(context)[key]:flutter_intl生成的S类是强类型结构,没有下标运算符,这种写法不符合语法规范。
  • ViewModel持有context:ViewModel属于业务逻辑层,不应该依赖UI层的BuildContext,且静态列表初始化时context可能尚未完成初始化,会导致空指针异常。

内容的提问来源于stack exchange,提问作者Basheer AL-MOMANI

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 08:15:37