Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mosuem committed Jan 13, 2025
1 parent 0b79236 commit b0f7c44
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 63 deletions.
45 changes: 28 additions & 17 deletions pkgs/messages_builder/lib/arb_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@ class ArbParser {
final context = arb['@@context'] as String?;
final messages = arb.keys
.where((key) => !key.startsWith('@'))
.map((key) => parseMessage(
arb[key] as String,
arb['@$key'] as Map<String, dynamic>?,
key,
'${context}_$locale',
))
.map(
(key) => parseMessage(
arb[key] as String,
arb['@$key'] as Map<String, dynamic>?,
key,
'${context}_$locale',
),
)
.toList();
messages.sort((a, b) => a.name.compareTo(b.name));
return MessageFile(
Expand All @@ -47,23 +49,32 @@ class ArbParser {
String name,
String debugString,
) {
final message = MessageParser.parse(
final (message, arguments) = MessageParser.parse(
debugString,
messageContent,
name,
);
final meaning = metadata?['meaning'] as String?;
final description = metadata?['description'] as String?;

final placeholdersMap = metadata?['placeholders'] as Map<String, dynamic>?;
final placeholdersWithMetadata = placeholdersMap?.map(
(name, metadata) {
final type = (metadata as Map<String, dynamic>)['type'] as String?;
return MapEntry(name, Placeholder(name, type ?? 'String'));
},
) ??
final placeholdersWithMetadata = placeholdersMap?.map((name, metadata) {
final type = (metadata as Map<String, dynamic>)['type'] as String?;
final example = metadata['example'] as String?;
return MapEntry(name, Placeholder(name, type ?? 'String', example));
}) ??
<String, Placeholder>{};

final placeholders = message.placeholders
.map((p) => placeholdersWithMetadata[p.name] ?? p)
.toList();
return ParameterizedMessage(message.message, message.name, placeholders);
return ParameterizedMessage(
message: message,
name: name,
meaning: meaning,
description: description,
placeholders: arguments
.map(
(name) => placeholdersWithMetadata[name] ?? Placeholder(name),
)
.toList(),
);
}
}
85 changes: 42 additions & 43 deletions pkgs/messages_builder/lib/message_parser/message_parser.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,24 @@

import 'package:messages/messages.dart';

import '../parameterized_message.dart';
import '../placeholder.dart';
import 'icu_message_parser.dart';
import 'plural_parser.dart';
import 'select_parser.dart';

class MessageParser {
static ParameterizedMessage parse(
static (Message, List<String>) parse(
String debugString,
String fileContents,
String name,
) {
final node = Parser(name, debugString, fileContents).parse();
final arguments = <String>[];
final message = parseNode(node, arguments, name) ?? StringMessage('');
final placeholders = arguments.map(Placeholder.new).toList();
return ParameterizedMessage(message, name, placeholders);
return (message, arguments);
}

static Message? parseNode(
Node node,
List<String> arguments, [
String? name,
]) {
static Message? parseNode(Node node, List<String> arguments, [String? name]) {
final submessages = <Message>[];
final placeholders = <({int argIndex, int afterStringMessage})>[];
for (var child in node.children) {
switch (child.type) {
case ST.string:
Expand All @@ -45,10 +37,14 @@ class MessageParser {
if (!arguments.contains(identifier)) {
arguments.add(identifier);
}
placeholders.add((
argIndex: arguments.indexOf(identifier),
afterStringMessage: submessages.length,
));
submessages.add(
StringMessage(
'',
argPositions: [
(argIndex: arguments.indexOf(identifier), stringIndex: 0),
],
),
);
break;
case ST.selectExpr:
submessages.add(SelectParser().parse(child, arguments));
Expand All @@ -57,37 +53,40 @@ class MessageParser {
break;
}
}
if (submessages.isEmpty && placeholders.isEmpty) {
if (submessages.isEmpty) {
return null;
} else if (submessages.length == 1 && placeholders.isEmpty) {
return submessages.first;
} else if (submessages.every((message) => message is StringMessage)) {
return combineStringsAndPlaceholders(
submessages.whereType<StringMessage>().toList(),
placeholders,
);
} else {
return CombinedMessage(submessages);
}
}

static StringMessage combineStringsAndPlaceholders(
List<StringMessage> submessages,
List<({int afterStringMessage, int argIndex})> placeholders,
) {
final argPositions = <({int argIndex, int stringIndex})>[];
final s = StringBuffer();
for (var i = 0; i < submessages.length + 1; i++) {
placeholders
.where((element) => element.afterStringMessage == i)
.forEach((element) {
argPositions.add((argIndex: element.argIndex, stringIndex: s.length));
});
if (i < submessages.length) {
final submessage = submessages[i];
s.write(submessage.value);
final fold = submessages.fold(<Message>[], (messages, message) {
if (messages.isNotEmpty &&
message is StringMessage &&
messages.last is StringMessage) {
final last = messages.removeLast() as StringMessage;
return [...messages, combineStringMessages(last, message)];
} else {
return [...messages, message];
}
});
if (fold.length == 1) {
return fold.first;
} else {
return CombinedMessage(fold);
}
return StringMessage(s.toString(), argPositions: argPositions);
}

static StringMessage combineStringMessages(
StringMessage message1,
StringMessage message2,
) =>
StringMessage(
message1.value + message2.value,
argPositions: [
...message1.argPositions,
...message2.argPositions.map(
(e) => (
argIndex: e.argIndex,
stringIndex: e.stringIndex + message1.value.length,
),
),
],
);
}
11 changes: 10 additions & 1 deletion pkgs/messages_builder/lib/parameterized_message.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.

import 'package:messages/messages.dart';

import 'placeholder.dart';

/// A wrapper class around a [Message], adding its [placeholders] and a [name].
Expand All @@ -26,11 +27,19 @@ import 'placeholder.dart';
class ParameterizedMessage {
final Message message;
final String name;
final String? meaning;
final String? description;
final List<Placeholder> placeholders;

static final RegExp _dartName = RegExp(r'^[a-zA-Z][a-zA-Z_0-9]*$');

ParameterizedMessage(this.message, this.name, this.placeholders);
ParameterizedMessage({
required this.message,
required this.name,
this.meaning,
this.description,
this.placeholders = const [],
});

bool get nameIsDartConform => _dartName.hasMatch(name);
}
3 changes: 2 additions & 1 deletion pkgs/messages_builder/lib/placeholder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@
class Placeholder {
final String name;
final String? type;
final String? example;

Placeholder(this.name, [this.type]);
Placeholder(this.name, [this.type, this.example]);

@override
String toString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Message intlPluralSelector(
void main() {
test('generateMessageFile from Object json', () {
final message = StringMessage('Hello World');
final message1 = ParameterizedMessage(message, 'helloWorld', []);
final message1 = ParameterizedMessage(message: message, name: 'helloWorld');
final messageList = <ParameterizedMessage>[message1];
final buffer = JsonSerializer()
.serialize('', '', messageList.map((e) => e.message).toList())
Expand Down

0 comments on commit b0f7c44

Please sign in to comment.