blob: 8c8c0ec90801e214907cb30d1c4a58ca81caab14 [file]
// Copyright (c) 2026, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'dart:io';
import 'package:data_assets/data_assets.dart';
import 'package:hooks/hooks.dart';
import 'package:record_use/record_use.dart';
void main(List<String> args) async {
await link(args, (input, output) async {
final translationAsset = _findTranslationAsset(input);
if (translationAsset == null) return;
// ignore: experimental_member_use
final recordedUsagesFile = input.recordedUsagesFile;
if (recordedUsagesFile == null) {
output.assets.data.add(translationAsset.asDataAsset);
return;
}
final recordings = await _loadRecordings(recordedUsagesFile);
final usedPhrases = _extractUsedPhrases(recordings);
final allTranslations = await _loadTranslations(translationAsset);
final filteredTranslations = _filterTranslations(
allTranslations,
usedPhrases,
);
await _writeOutputAsset(input, output, filteredTranslations);
});
}
EncodedAsset? _findTranslationAsset(LinkInput input) => input
.assets
.encodedAssets
.where(
(a) =>
a.isDataAsset &&
a.asDataAsset.id == 'package:pirate_speak/translations',
)
.firstOrNull;
Future<Recordings> _loadRecordings(Uri file) async {
final content = await File.fromUri(file).readAsString();
return Recordings.fromJson(jsonDecode(content) as Map<String, Object?>);
}
Set<String> _extractUsedPhrases(Recordings recordings) {
final usedPhrases = <String>{};
const pirateSpeakDef = Method(
'pirateSpeak',
Library('package:pirate_speak/src/definitions.dart'),
);
for (final call in recordings.calls[pirateSpeakDef] ?? const []) {
switch (call) {
case CallWithArguments(
positionalArguments: [StringConstant(:final value), ...],
):
usedPhrases.add(value);
case _:
throw UnsupportedError('Cannot determine which translations are used.');
}
}
return usedPhrases;
}
Future<Map<String, dynamic>> _loadTranslations(EncodedAsset asset) async {
final file = asset.asDataAsset.file;
return jsonDecode(await File.fromUri(file).readAsString())
as Map<String, dynamic>;
}
Map<String, dynamic> _filterTranslations(
Map<String, dynamic> allTranslations,
Set<String> usedPhrases,
) => {
for (final entry in allTranslations.entries)
if (usedPhrases.contains(entry.key)) entry.key: entry.value,
};
Future<void> _writeOutputAsset(
LinkInput input,
LinkOutputBuilder output,
Map<String, dynamic> content,
) async {
final filteredFile = input.outputDirectory.resolve(
'filtered_translations.json',
);
await File.fromUri(filteredFile).writeAsString(jsonEncode(content));
output.assets.data.add(
DataAsset(
package: input.packageName,
name: 'translations',
file: filteredFile,
),
);
}