Flutter中如何将Intl的select配置转为Dart列表?
Flutter本地化中读取YouTube视频ID列表失败的解决方法
问题场景
在Flutter应用中使用youtube_player_iframe插件展示多语言YouTube视频,通过intl插件将视频ID存入.arb本地化文件的select结构中。尝试读取该内容并通过正则转为Dart列表时,获取到的结果是闭包描述字符串,而非预期的本地化内容。
相关代码与配置
.arb文件配置:
"youtubeVideo": "{choice, select, 1{W6wIEp-M4tg} 2{bXOr0G7v-9Q} 3{zFWdTv6-7ws} 4{z8oSo6qTmqk} 5{_d29LTKgCEA} 6{PH8Mmxxhq_E} other{}}", "@youtubeVideo": { "placeholders": { "choice": {} } }
错误的读取代码:
RegExp exp = RegExp(r'^[\w\W]+$'); String str = AppLocalizations.of(context)!.youtubeVideo.toString(); RegExpMatch? match = exp.firstMatch(str);
错误结果:
Closure: (String) => String from Function 'youtubeVideo':.
原因分析
intl插件会将.arb中的select类型字段生成为带参数的函数(例如String youtubeVideo(String choice)),而非直接的字符串。直接调用youtubeVideo而不传参数,得到的是函数对象,调用toString()自然会输出闭包的描述信息。
解决方案
方案一:直接读取arb文件提取所有视频ID
如果需要提取所有语言对应的视频ID列表,可以直接读取.arb文件内容,再用正则匹配提取:
- 在pubspec.yaml中添加arb文件为资产:
flutter: assets: - assets/l10n/app_en.arb # 替换为你的英文arb路径 - assets/l10n/app_zh.arb # 替换为你的中文arb路径
- 读取文件并提取ID的代码:
import 'package:flutter/services.dart'; import 'dart:convert'; import 'package:flutter/widgets.dart'; Future<List<String>> getYoutubeVideoIds(BuildContext context) async { // 获取当前语言代码 String localeCode = Localizations.localeOf(context).languageCode; // 拼接对应语言的arb文件路径 String arbPath = 'assets/l10n/app_$localeCode.arb'; // 读取arb文件内容 String arbContent = await rootBundle.loadString(arbPath); Map<String, dynamic> arbData = jsonDecode(arbContent); String videoSelectStr = arbData['youtubeVideo'] as String; // 正则匹配所有数字标记后的视频ID RegExp idRegex = RegExp(r'\d+\{([a-zA-Z0-9_-]+)\}'); Iterable<RegExpMatch> matches = idRegex.allMatches(videoSelectStr); // 提取并返回ID列表 return matches.map((match) => match.group(1)!).toList(); }
方案二:优化arb存储结构(更推荐)
放弃select结构,直接用分隔符分隔的字符串存储视频ID,简化读取逻辑:
- 修改arb文件配置:
"youtubeVideos": "W6wIEp-M4tg,bXOr0G7v-9Q,zFWdTv6-7ws,z8oSo6qTmqk,_d29LTKgCEA,PH8Mmxxhq_E", "@youtubeVideos": { "description": "Comma-separated list of YouTube video IDs" }
- 读取并转为列表的代码:
List<String> videoIds = AppLocalizations.of(context)!.youtubeVideos.split(',');
如果需要同时支持根据索引获取单个视频ID,可以直接通过列表索引访问:
String getVideoByIdx(int idx) { List<String> ids = AppLocalizations.of(context)!.youtubeVideos.split(','); return idx >= 0 && idx < ids.length ? ids[idx] : ''; }
内容的提问来源于stack exchange,提问作者Giulia Santoiemma
相关产品推荐
相关产品推荐

