Skip to content

Commit 90db15f

Browse files
committed
Merge branch 'feat/add-linked-files' into develop
2 parents 74e6432 + ed4d755 commit 90db15f

File tree

1 file changed

+51
-13
lines changed

1 file changed

+51
-13
lines changed

lib/src/asset_loader.dart

Lines changed: 51 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ abstract class AssetLoader {
2424
/// default used is RootBundleAssetLoader which uses flutter's assetloader
2525
///
2626
class 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,58 @@ 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)));
65+
final Map<String, dynamic> linkedJson =
66+
json.decode(await rootBundle.loadString(linkedAssetPath)) as Map<String, dynamic>;
67+
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+
}
5583
}
5684

5785
if (value is Map<String, dynamic>) {
58-
fullJson[key] =
59-
await _getLinkedTranslationFileDataFromBaseJson(basePath, locale, value, fileLoaded: fileLoaded);
86+
fullJson[key] = await _getLinkedTranslationFileDataFromBaseJson(
87+
basePath,
88+
locale,
89+
value,
90+
visited: visited,
91+
depth: depth + 1,
92+
);
6093
}
6194
}
6295

@@ -69,6 +102,11 @@ class RootBundleAssetLoader extends AssetLoader {
69102
EasyLocalization.logger.debug('Load asset from $path');
70103

71104
Map<String, dynamic> baseJson = json.decode(await rootBundle.loadString(localePath));
72-
return await _getLinkedTranslationFileDataFromBaseJson(path, locale, baseJson);
105+
return await _getLinkedTranslationFileDataFromBaseJson(
106+
path,
107+
locale,
108+
baseJson,
109+
visited: <String>{},
110+
);
73111
}
74112
}

0 commit comments

Comments
 (0)