@@ -24,6 +24,9 @@ abstract class AssetLoader {
2424/// default used is RootBundleAssetLoader which uses flutter's assetloader
2525///
2626class RootBundleAssetLoader extends AssetLoader {
27+ // Place inside class RootBundleAssetLoader
28+ static const int _maxLinkedDepth = 32 ;
29+
2730 const RootBundleAssetLoader ();
2831
2932 String getLocalePath (String basePath, Locale locale) {
@@ -35,28 +38,48 @@ class RootBundleAssetLoader extends AssetLoader {
3538 }
3639
3740 Future <Map <String , dynamic >> _getLinkedTranslationFileDataFromBaseJson (
38- String basePath, Locale locale, Map <String , dynamic > baseJson,
39- {List <String > fileLoaded = const []}) async {
40- Map <String , dynamic > fullJson = Map <String , dynamic >.from (baseJson);
41+ String basePath,
42+ Locale locale,
43+ Map <String , dynamic > baseJson, {
44+ required Set <String > visited,
45+ int depth = 0 ,
46+ }) async {
47+ if (depth > _maxLinkedDepth) {
48+ throw StateError ('Maximum linked files depth ($_maxLinkedDepth ) exceeded for $locale at $basePath .' );
49+ }
50+
51+ final Map <String , dynamic > fullJson = Map <String , dynamic >.from (baseJson);
4152
42- for (var entry in baseJson.entries) {
43- var key = entry.key;
53+ for (final entry in baseJson.entries) {
54+ final key = entry.key;
4455 var value = entry.value;
4556
4657 if (value is String && value.startsWith (':/' )) {
47- String filePath = value.substring (2 );
58+ final rawPath = value.substring (2 ).trim ();
59+ final linkedAssetPath = _getLinkedLocalePath (basePath, rawPath, locale);
4860
49- if (fileLoaded .contains (filePath )) {
50- throw Exception ( 'Circular reference detected: $ filePath is loaded multiple times ' );
61+ if (visited .contains (linkedAssetPath )) {
62+ throw StateError ( 'Cyclic linked files detected at "$ linkedAssetPath " (key: "$ key "). ' );
5163 }
5264
53- fileLoaded.add (filePath);
54- value = json.decode (await rootBundle.loadString (_getLinkedLocalePath (basePath, filePath, locale)));
55- }
65+ final Map <String , dynamic > linkedJson =
66+ json.decode (await rootBundle.loadString (linkedAssetPath)) as Map <String , dynamic >;
5667
57- if (value is Map <String , dynamic >) {
58- fullJson[key] =
59- await _getLinkedTranslationFileDataFromBaseJson (basePath, locale, value, fileLoaded: fileLoaded);
68+ visited.add (linkedAssetPath);
69+ try {
70+ final resolved = await _getLinkedTranslationFileDataFromBaseJson (
71+ basePath,
72+ locale,
73+ linkedJson,
74+ visited: visited,
75+ depth: depth + 1 ,
76+ );
77+ fullJson[key] = resolved;
78+ } catch (e) {
79+ throw StateError (
80+ 'Error resolving linked file "$linkedAssetPath " for key "$key ": $e ' ,
81+ );
82+ }
6083 }
6184 }
6285
@@ -69,6 +92,11 @@ class RootBundleAssetLoader extends AssetLoader {
6992 EasyLocalization .logger.debug ('Load asset from $path ' );
7093
7194 Map <String , dynamic > baseJson = json.decode (await rootBundle.loadString (localePath));
72- return await _getLinkedTranslationFileDataFromBaseJson (path, locale, baseJson);
95+ return await _getLinkedTranslationFileDataFromBaseJson (
96+ path,
97+ locale,
98+ baseJson,
99+ visited: < String > {},
100+ );
73101 }
74102}
0 commit comments