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

Flutter实现双商店本地化字符串切换方案咨询

解决Flutter多门店本地化切换的方案

方案一:生成不同类名的本地化实例,通过状态管理切换

这是最直接且无需修改intl包的方案,步骤如下:

  1. 配置两套本地化生成规则
    在lib/l10n和lib/l10n_2目录下分别创建l10n.yaml,指定不同的生成类名:

    • lib/l10n/l10n.yaml:
      arb-dir: .
      template-arb-file: app_en.arb
      output-localization-file: app_localizations.dart
      class-name: Shop1Localizations
      
    • lib/l10n_2/l10n.yaml:
      arb-dir: .
      template-arb-file: app_en.arb
      output-localization-file: app_localizations_2.dart
      class-name: Shop2Localizations
      

    执行flutter gen-l10n后,会生成Shop1Localizations和Shop2Localizations两个独立类,各自对应一套字符串表。

  2. 全局维护门店切换状态
    创建一个简单的状态管理类(基于ChangeNotifier):

    import 'package:flutter/foundation.dart';
    import 'package:your_project/l10n/app_localizations.dart';
    import 'package:your_project/l10n_2/app_localizations_2.dart';
    import 'package:flutter/material.dart';
    
    class ShopLocalizationProvider extends ChangeNotifier {
      bool _isShop1 = true;
    
      bool get isShop1 => _isShop1;
    
      void toggleShop() {
        _isShop1 = !_isShop1;
        notifyListeners();
      }
    
      dynamic getCurrentLocalizations(BuildContext context) {
        return _isShop1 ? Shop1Localizations.of(context) : Shop2Localizations.of(context);
      }
    }
    

    在main.dart中用ChangeNotifierProvider包裹根Widget,让全局能访问这个状态。

  3. 业务代码中复用调用逻辑
    在需要展示字符串的Widget中,通过状态获取当前本地化实例,直接调用相同键名的方法:

    final provider = Provider.of<ShopLocalizationProvider>(context);
    final localizations = provider.getCurrentLocalizations(context);
    // 示例:调用相同键名的字符串
    Text(localizations.homeTitle)
    

    点击切换按钮时,调用provider.toggleShop()即可触发所有使用本地化的Widget刷新。

方案二:自定义LocalizationsDelegate动态加载资源

如果不想生成两个类,可以自定义Delegate手动加载不同目录的资源文件:

  1. 创建通用本地化类

    class AppLocalizations {
      final Map<String, String> _strings;
    
      AppLocalizations(this._strings);
    
      static AppLocalizations? of(BuildContext context) {
        return Localizations.of<AppLocalizations>(context, AppLocalizations);
      }
    
      String get homeTitle => _strings['home_title'] ?? '';
      // 其他字符串键...
    }
    
  2. 实现可切换资源的Delegate

    import 'dart:convert';
    import 'package:flutter/services.dart';
    import 'package:flutter/widgets.dart';
    
    class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
      final String resourceDir; // 传入l10n或l10n_2目录路径
    
      AppLocalizationsDelegate(this.resourceDir);
    
      @override
      bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);
    
      @override
      Future<AppLocalizations> load(Locale locale) async {
        final jsonString = await rootBundle.loadString(
          '$resourceDir/app_${locale.languageCode}.arb',
        );
        final Map<String, dynamic> jsonMap = json.decode(jsonString);
        final strings = jsonMap.map((key, value) => MapEntry(key, value.toString()));
        return AppLocalizations(strings);
      }
    
      @override
      bool shouldReload(AppLocalizationsDelegate old) => old.resourceDir != resourceDir;
    }
    
  3. 动态切换Delegate
    在状态类中维护当前资源目录,然后在MaterialApp的localizationsDelegates中动态传入对应Delegate:

    // 状态类中
    String _currentResourceDir = 'lib/l10n';
    
    void toggleShop() {
      _currentResourceDir = _currentResourceDir == 'lib/l10n' ? 'lib/l10n_2' : 'lib/l10n';
      notifyListeners();
    }
    
    // MaterialApp配置中
    localizationsDelegates: [
      AppLocalizationsDelegate(provider.currentResourceDir),
      GlobalMaterialLocalizations.delegate,
      GlobalWidgetsLocalizations.delegate,
      GlobalCupertinoLocalizations.delegate,
    ],
    

    切换门店时调用toggleShop(),MaterialApp会自动重新加载对应目录的本地化资源。

关于依赖冲突的说明

不要尝试修改intl包的本地依赖,flutter_localizations本身依赖官方托管的intl包,强行替换必然导致版本冲突。上面的两个方案完全基于官方API实现,无需修改intl包,可规避依赖问题。

内容的提问来源于stack exchange,提问作者timyau

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 23:27:43