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

Flutter通过API获取本地化资源,如何基于Intl类包实现(禁止本地存储)

Flutter 远程API获取本地化资源的实现方案(无需本地arb文件)

方案1:基于Intl包扩展自定义LocalizationsDelegate

Intl包不强制依赖arb文件,你可以通过自定义LocalizationsDelegate对接远程API,核心是在load方法中发起网络请求获取翻译资源,再封装成Intl兼容的类。

示例代码:

// 自定义本地化类,提供翻译方法
class ApiIntlLocalizations {
  final Map<String, String> translations;

  ApiIntlLocalizations(this.translations);

  static ApiIntlLocalizations of(BuildContext context) {
    return Localizations.of<ApiIntlLocalizations>(context, ApiIntlLocalizations)!;
  }

  String translate(String key) {
    return translations[key] ?? key;
  }
}

// 自定义Delegate,负责加载远程资源
class ApiIntlLocalizationsDelegate extends LocalizationsDelegate<ApiIntlLocalizations> {
  @override
  bool isSupported(Locale locale) {
    // 配置支持的语言列表
    return ['en', 'zh', 'es'].contains(locale.languageCode);
  }

  @override
  Future<ApiIntlLocalizations> load(Locale locale) async {
    // 发起API请求获取对应语言的翻译资源
    final response = await http.get(Uri.parse('https://your-api.com/localization/${locale.languageCode}'));
    if (response.statusCode == 200) {
      final translations = json.decode(response.body) as Map<String, String>;
      return ApiIntlLocalizations(translations);
    } else {
      // 加载失败返回默认空资源,或预设的默认语言翻译
      return ApiIntlLocalizations({});
    }
  }

  @override
  bool shouldReload(covariant LocalizationsDelegate<ApiIntlLocalizations> old) => false;
}

在MaterialApp中配置:

MaterialApp(
  localizationsDelegates: [
    ApiIntlLocalizationsDelegate(),
    GlobalMaterialLocalizations.delegate,
    GlobalWidgetsLocalizations.delegate,
    GlobalCupertinoLocalizations.delegate,
  ],
  supportedLocales: const [
    Locale('en'),
    Locale('zh'),
  ],
  // 其他配置
)

使用方式:

Text(ApiIntlLocalizations.of(context).translate('welcome_message'))

方案2:基于Flutter官方Localizations框架直接实现

无需依赖Intl,直接利用Flutter原生的LocalizationsDelegate机制,在load阶段拉取远程资源,用内存Map存储翻译键值对。

示例代码:

class RemoteLocalizations {
  final Map<String, String> _strings;

  RemoteLocalizations(this._strings);

  static RemoteLocalizations of(BuildContext context) {
    return Localizations.of<RemoteLocalizations>(context, RemoteLocalizations)!;
  }

  String getString(String key) => _strings[key] ?? key;
}

class RemoteLocalizationsDelegate extends LocalizationsDelegate<RemoteLocalizations> {
  @override
  bool isSupported(Locale locale) => ['en', 'zh'].contains(locale.languageCode);

  @override
  Future<RemoteLocalizations> load(Locale locale) async {
    // 调用API获取翻译数据
    final client = HttpClient();
    final uri = Uri.parse('https://your-api.com/i18n/${locale.languageCode}');
    final request = await client.getUrl(uri);
    final response = await request.close();
    final responseBody = await response.transform(utf8.decoder).join();
    final strings = json.decode(responseBody) as Map<String, String>;
    return RemoteLocalizations(strings);
  }

  @override
  bool shouldReload(covariant LocalizationsDelegate<RemoteLocalizations> old) => false;
}

配置和使用逻辑与方案1一致,调用时用RemoteLocalizations.of(context).getString('key')。

方案3:利用第三方库简化实现(如easy_localization)

部分第三方本地化库支持远程资源加载,比如easy_localization,你可以自定义AssetLoader从API拉取数据,无需本地arb文件:

class ApiAssetLoader extends AssetLoader {
  @override
  Future<Map<String, dynamic>> load(String path, Locale locale) async {
    final response = await http.get(Uri.parse('https://your-api.com/localization/${locale.languageCode}'));
    return json.decode(response.body) as Map<String, dynamic>;
  }
}

初始化EasyLocalization:

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await EasyLocalization.ensureInitialized();

  runApp(
    EasyLocalization(
      supportedLocales: const [Locale('en'), Locale('zh')],
      path: '', // 无需本地路径
      assetLoader: ApiAssetLoader(),
      child: const MyApp(),
    ),
  );
}

使用时直接调用库的tr('key')方法即可。

关键注意事项

  • 加载状态处理:API请求是异步的,资源加载完成前建议显示加载占位符(如CircularProgressIndicator),避免界面出现未翻译的key。
  • 内存缓存:禁止本地存储的情况下,可在内存中缓存已加载的语言资源,减少重复API请求。
  • 错误降级:API请求失败时,要切换到默认语言(如英文),避免界面崩溃。
  • 语言切换触发:切换语言时,需触发Localizations重新加载,比如调用EasyLocalization.of(context)?.setLocale(newLocale),或通过StatefulWidget更新Locale。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 16:35:28