Skip to content

Commit

Permalink
fix: analyze command should ignore unused translations that are linked
Browse files Browse the repository at this point in the history
  • Loading branch information
Tienisto committed Oct 21, 2024
1 parent 116d01e commit 1462961
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 5 deletions.
47 changes: 42 additions & 5 deletions slang/lib/src/runner/analyze.dart
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ void runAnalyzeTranslations({
result: missingTranslationsResult,
);

final unusedTranslationsResult = _getUnusedTranslations(
final unusedTranslationsResult = getUnusedTranslations(
rawConfig: rawConfig,
translations: translationModelList,
full: full,
Expand Down Expand Up @@ -121,14 +121,15 @@ Map<I18nLocale, Map<String, dynamic>> getMissingTranslations({
curr: currTranslations.root,
resultMap: resultMap,
handleOutdated: true,
ignorePaths: const {},
);
result[currTranslations.locale] = resultMap;
}

return result;
}

Map<I18nLocale, Map<String, dynamic>> _getUnusedTranslations({
Map<I18nLocale, Map<String, dynamic>> getUnusedTranslations({
required RawConfig rawConfig,
required List<I18nData> translations,
required bool full,
Expand All @@ -150,11 +151,16 @@ Map<I18nLocale, Map<String, dynamic>> _getUnusedTranslations({
}

final resultMap = <String, dynamic>{};
final linkedPaths = <String>{};
_getReferredPaths(localeData.root, linkedPaths);

// { } = localeData - baseTranslations
_getMissingTranslationsForOneLocaleRecursive(
baseNode: localeData.root,
curr: baseTranslations.root,
resultMap: resultMap,
handleOutdated: false,
ignorePaths: linkedPaths,
);
result[localeData.locale] = resultMap;
}
Expand All @@ -169,17 +175,21 @@ void _getMissingTranslationsForOneLocaleRecursive({
required ObjectNode curr,
required Map<String, dynamic> resultMap,
required bool handleOutdated,
required Set<String> ignorePaths,
}) {
for (final baseEntry in baseNode.entries.entries) {
final baseChild = baseEntry.value;
if (baseChild.modifiers.containsKey(NodeModifiers.ignoreMissing)) {
if (baseChild.modifiers.containsKey(NodeModifiers.ignoreMissing) ||
ignorePaths.contains(baseChild.path)) {
continue;
}

final currChild = curr.entries[baseEntry.key];
final isOutdated = handleOutdated &&
currChild?.modifiers.containsKey(NodeModifiers.outdated) == true;
if (isOutdated || !_checkEquality(baseChild, currChild)) {
if (isOutdated ||
currChild == null ||
!_checkEquality(baseChild, currChild)) {
if (baseChild is ContextNode && currChild is ContextNode) {
// Only add missing enums
for (final baseEnum in baseChild.entries.keys) {
Expand Down Expand Up @@ -208,6 +218,7 @@ void _getMissingTranslationsForOneLocaleRecursive({
curr: currChild as ObjectNode,
resultMap: resultMap,
handleOutdated: handleOutdated,
ignorePaths: ignorePaths,
);
}
}
Expand Down Expand Up @@ -287,7 +298,7 @@ void _addNodeRecursive({

/// Both nodes are considered the same
/// when they have the same type and the same parameters.
bool _checkEquality(Node? a, Node? b) {
bool _checkEquality(Node a, Node b) {
if (a.runtimeType != b.runtimeType) {
return false;
}
Expand Down Expand Up @@ -402,6 +413,32 @@ I18nData _findBaseTranslations(RawConfig rawConfig, List<I18nData> i18nData) {
return baseTranslations;
}

/// Populates [paths] with all paths that are referred in
/// linked translations.
void _getReferredPaths(ObjectNode root, Set<String> paths) {
for (final entry in root.entries.entries) {
final child = entry.value;
switch (child) {
case ObjectNode() when !child.isMap:
_getReferredPaths(child, paths);
break;
case PluralNode():
for (final quantity in child.quantities.values) {
paths.addAll(quantity.links);
}
break;
case ContextNode():
for (final context in child.entries.values) {
paths.addAll(context.links);
}
break;
case TextNode():
paths.addAll(child.links);
break;
}
}
}

void _writeMap({
required String outDir,
required String fileNamePrefix,
Expand Down
55 changes: 55 additions & 0 deletions slang/test/unit/runner/analyze_test.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
import 'package:slang/src/builder/builder/translation_model_list_builder.dart';
import 'package:slang/src/builder/model/i18n_locale.dart';
import 'package:slang/src/builder/model/raw_config.dart';
import 'package:slang/src/builder/model/translation_map.dart';
import 'package:slang/src/runner/analyze.dart';
import 'package:test/test.dart';

Expand Down Expand Up @@ -53,4 +57,55 @@ void main() {
expect(result, 'ADEG');
});
});

group('getUnusedTranslations', () {
test('Should find unused but translations', () {
final result = _getUnusedTranslations({
'en': {
'a': 'A',
},
'de': {
'a': 'A',
'b': 'B',
},
});

expect(result[I18nLocale(language: 'de')], {'b': 'B'});
});

test('Should ignore unused but linked translations', () {
final result = _getUnusedTranslations({
'en': {
'a': 'A',
},
'de': {
'a': 'A @:b',
'b': 'B',
},
});

expect(result[I18nLocale(language: 'de')], isEmpty);
});
});
}

Map<I18nLocale, Map<String, dynamic>> _getUnusedTranslations(
Map<String, Map<String, dynamic>> translations,
) {
final map = TranslationMap();
for (final entry in translations.entries) {
map.addTranslations(
locale: I18nLocale(language: entry.key),
translations: entry.value,
);
}

return getUnusedTranslations(
rawConfig: RawConfig.defaultConfig,
translations: TranslationModelListBuilder.build(
RawConfig.defaultConfig,
map,
),
full: false,
);
}

0 comments on commit 1462961

Please sign in to comment.