Skip to content

Commit

Permalink
fix: duplicate keys when there are modifiers
Browse files Browse the repository at this point in the history
  • Loading branch information
Tienisto committed Mar 3, 2024
1 parent 7e189ee commit 5b89f82
Show file tree
Hide file tree
Showing 8 changed files with 50 additions and 12 deletions.
4 changes: 4 additions & 0 deletions slang/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.30.1

- fix: applying translations with `dart run slang apply` should use only modifiers from the base locale (#192)

## 3.30.0

- feat: add parameter types (e.g. `Hello {name: String}, you are {age: int} years old`); is `Object` by default @Tienisto
Expand Down
6 changes: 5 additions & 1 deletion slang/lib/src/builder/utils/node_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,11 @@ class NodePathInfo {
extension StringModifierExt on String {
/// Returns the key without modifiers.
String get withoutModifiers {
return split('(').first;
final index = indexOf('(');
if (index == -1) {
return this;
}
return substring(0, index);
}

String withModifier(String modifierKey, [String? modifierValue]) {
Expand Down
11 changes: 8 additions & 3 deletions slang/lib/src/runner/apply.dart
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ Map<String, dynamic> applyMapRecursive({
required bool verbose,
}) {
final resultMap = <String, dynamic>{};
final resultKeys = <String>{}; // keys without modifiers

// Keys that have been applied.
// They do not have modifiers in their path.
Expand All @@ -234,7 +235,8 @@ Map<String, dynamic> applyMapRecursive({
// Add keys according to the order in base map.
// Prefer new map over old map.
for (final key in baseMap.keys) {
final newEntry = newMap[key.withoutModifiers];
final keyWithoutModifiers = key.withoutModifiers;
final newEntry = newMap[keyWithoutModifiers];
dynamic actualValue = newEntry ?? oldMap[key];
if (actualValue == null) {
continue;
Expand All @@ -261,12 +263,14 @@ Map<String, dynamic> applyMapRecursive({
}
}
resultMap[key] = actualValue;
resultKeys.add(keyWithoutModifiers);
}

// Add keys from old map that are unknown in base locale.
// It may contain the OUTDATED modifier.
for (final key in oldMap.keys) {
if (resultMap.containsKey(key)) {
final keyWithoutModifiers = key.withoutModifiers;
if (resultKeys.contains(keyWithoutModifiers)) {
continue;
}

Expand Down Expand Up @@ -296,12 +300,13 @@ Map<String, dynamic> applyMapRecursive({
_printAdding(currPath, actualValue);
}
resultMap[key] = actualValue;
resultKeys.add(keyWithoutModifiers);
}

// Add remaining new keys that are not in base locale and not in old map.
for (final entry in newMap.entries) {
final keyWithoutModifiers = entry.key.withoutModifiers;
if (resultMap.containsKey(keyWithoutModifiers)) {
if (resultKeys.contains(keyWithoutModifiers)) {
continue;
}

Expand Down
2 changes: 1 addition & 1 deletion slang/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: slang
description: Localization / Internationalization (i18n) solution. Use JSON, YAML, CSV, or ARB files to create typesafe translations via source generation.
version: 3.30.0
version: 3.30.1
repository: https://github.com/slang-i18n/slang
topics:
- i18n
Expand Down
30 changes: 25 additions & 5 deletions slang/test/unit/runner/apply_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ void main() {
group('applyMapRecursive', () {
test('ignore strings in baseMap if not applied', () {
final result = applyMapRecursive(
baseMap: {'c': 'C'},
newMap: {'a': 'A'},
oldMap: {'b': 'B'},
baseMap: {'base': 'BB'},
newMap: {'new': 'NN'},
oldMap: {'old': 'OO'},
verbose: false,
);
expect(result, {'b': 'B', 'a': 'A'});
expect(result.keys.toList(), ['b', 'a']);
expect(result, {'new': 'NN', 'old': 'OO'});
expect(result.keys.toList(), ['old', 'new']);
});

test('handle empty newMap', () {
Expand Down Expand Up @@ -145,5 +145,25 @@ void main() {
expect(result.keys.toList(), ['c', 'a', 'b']);
expect((result['a'] as Map).keys.toList(), ['y', 'x', 'z', '0']);
});

test('ignore new modifier', () {
final result = applyMapRecursive(
baseMap: {},
newMap: {'a(param=arg0)': 'A'},
oldMap: {},
verbose: false,
);
expect(result, {'a': 'A'});
});

test('apply modifier of base map', () {
final result = applyMapRecursive(
baseMap: {'a(param=arg0)': 'base'},
newMap: {'a': 'new'},
oldMap: {'a': 'old'},
verbose: false,
);
expect(result, {'a(param=arg0)': 'new'});
});
});
}
5 changes: 5 additions & 0 deletions slang_gpt/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 0.10.1

- deps: bump slang to 3.30.1
- fix: duplicate keys when there are modifiers #192

## 0.10.0

- deps: bump slang to 3.25.0
Expand Down
2 changes: 1 addition & 1 deletion slang_gpt/lib/util/maps.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import 'package:slang/src/builder/utils/node_utils.dart';

const ignoreGpt = 'ignoreGpt';

/// Remove all entries from [map] that have the "ignoreMissing" modifier.
/// Remove all entries from [map] that have the "ignoreGpt" modifier.
/// This method removes the entries in-place.
void removeIgnoreGpt({
required Map<String, dynamic> map,
Expand Down
2 changes: 1 addition & 1 deletion slang_gpt/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ environment:
dependencies:
collection: ^1.15.0
http: '>=0.13.0 <2.0.0'
slang: ^3.25.0
slang: ^3.30.1

dev_dependencies:
lints: ^2.0.0
Expand Down

0 comments on commit 5b89f82

Please sign in to comment.