diff --git a/pkgs/messages/bin/messages.dart b/pkgs/messages/bin/messages.dart index 13effcc4..f6d3e0ef 100644 --- a/pkgs/messages/bin/messages.dart +++ b/pkgs/messages/bin/messages.dart @@ -1,12 +1,31 @@ import 'dart:io'; +import 'package:messages_builder/builder.dart'; +import 'package:messages_builder/generation_options.dart'; import 'package:messages_builder/message_data_builder.dart'; Future main(List args) async { - await MessagesDataBuilder().run( - inputFolder: Directory.fromUri( - Directory.current.uri.resolve('assets/').resolve('l10n/')), - outputFolder: Directory.fromUri(Directory.current.uri.resolve('assets/')), - libOutput: 'lib/messages.g.dart', - ); + final generationOptions = await _generationOptions(); + final inputFolder = Directory.fromUri( + Directory.current.uri.resolve('assets/').resolve('l10n/')); + final outputFolder = + Directory.fromUri(Directory.current.uri.resolve('assets/')); + + final mapping = await MessageDataFileBuilder( + inputFolder: inputFolder, + outputFolder: outputFolder, + generationOptions: generationOptions, + ).run(); + + await MessageCallingCodeGenerator( + mapping: mapping, + options: generationOptions, + ).build(); +} + +Future _generationOptions() async { + final pubspecUri = Directory.current.uri.resolve('pubspec.yaml'); + final file = File.fromUri(pubspecUri); + final pubspecContents = await file.readAsString(); + return await GenerationOptions.fromPubspec(pubspecContents); } diff --git a/pkgs/messages/example/assets/l10n/testarb.arb b/pkgs/messages/example/assets/l10n/testarb.arb index 6516f400..3b16f132 100644 --- a/pkgs/messages/example/assets/l10n/testarb.arb +++ b/pkgs/messages/example/assets/l10n/testarb.arb @@ -36,4 +36,4 @@ } }, "helloAndWelcome2": "Welcome {firstName} von {lastName}!" -} \ No newline at end of file +} diff --git a/pkgs/messages/example/assets/l10n/testarb_de.arb b/pkgs/messages/example/assets/l10n/testarb_de.arb index 65b07899..1c4c30ba 100644 --- a/pkgs/messages/example/assets/l10n/testarb_de.arb +++ b/pkgs/messages/example/assets/l10n/testarb_de.arb @@ -5,4 +5,4 @@ "helloAndWelcome2": "Willkommen {firstName} von {lastName} 2", "newMessages": "testde {newMessages, plural, =0 {No new messages} =1 {One new message} two{Two new Messages} other {test {newMessages} new messages}}", "newMessages2": "testdse is just a simple message" -} \ No newline at end of file +} diff --git a/pkgs/messages/example/assets/l10n/testarbctx2.arb b/pkgs/messages/example/assets/l10n/testarbctx2.arb index 41fb05bb..25f81957 100644 --- a/pkgs/messages/example/assets/l10n/testarbctx2.arb +++ b/pkgs/messages/example/assets/l10n/testarbctx2.arb @@ -43,4 +43,4 @@ } } } -} \ No newline at end of file +} diff --git a/pkgs/messages/example/assets/l10n/testarbctx2_fr.arb b/pkgs/messages/example/assets/l10n/testarbctx2_fr.arb index cbd6af7d..ec1c77ed 100644 --- a/pkgs/messages/example/assets/l10n/testarbctx2_fr.arb +++ b/pkgs/messages/example/assets/l10n/testarbctx2_fr.arb @@ -1,8 +1,9 @@ { "@@context": "AboutPage", + "@@locale": "fr", "helloAndWelcome": "Welcome {firstName} von {lastName} <", "otherMsg": "other", "aboutMessage": "Sur {websitename}", "newMessages": "test {newMessages, plural, =0 {No new messages} =1 {One new message} two{Two new Messages} other {test {newMessages} new messages}}", "newMessages2": "test {gender, select,male {No new messages} female {One new message} other{Two new Messages} other {test {gender} new messages of type {newVar}}}" -} \ No newline at end of file +} diff --git a/pkgs/messages/example/assets/testarb.arb.json b/pkgs/messages/example/assets/testarb.arb.json new file mode 100644 index 00000000..9a44323d --- /dev/null +++ b/pkgs/messages/example/assets/testarb.arb.json @@ -0,0 +1 @@ +[0,"en","dr9Md951",1,null,["helloAndWelcome","Welcome von !",[8,0],[13,1]],["helloAndWelcome2","Welcome von !",[8,0],[13,1]],[6,"newMessages","test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"newMessages2","test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]]] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarb.json b/pkgs/messages/example/assets/testarb.json deleted file mode 100644 index d46d15af..00000000 --- a/pkgs/messages/example/assets/testarb.json +++ /dev/null @@ -1 +0,0 @@ -[0,"en","dr9Md951",0,null,["Welcome von !",[8,0],[13,1]],["Welcome von !",[8,0],[13,1]],[6,"test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]]] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarb_de.arb.json b/pkgs/messages/example/assets/testarb_de.arb.json new file mode 100644 index 00000000..70e189e6 --- /dev/null +++ b/pkgs/messages/example/assets/testarb_de.arb.json @@ -0,0 +1 @@ +[0,"de","hbDN1MhX",1,null,["helloAndWelcome","Willkommen von ",[11,0],[16,1]],["helloAndWelcome2","Willkommen von 2",[11,0],[16,1]],[6,"newMessages","testde ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],["newMessages2","testdse is just a simple message"]] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarb_de.json b/pkgs/messages/example/assets/testarb_de.json deleted file mode 100644 index 8480d165..00000000 --- a/pkgs/messages/example/assets/testarb_de.json +++ /dev/null @@ -1 +0,0 @@ -[0,"de","hbDN1MhX",0,null,["Willkommen von ",[11,0],[16,1]],["Willkommen von 2",[11,0],[16,1]],[6,"testde ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],"testdse is just a simple message"] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarbctx2.arb.json b/pkgs/messages/example/assets/testarbctx2.arb.json new file mode 100644 index 00000000..5bd68e20 --- /dev/null +++ b/pkgs/messages/example/assets/testarbctx2.arb.json @@ -0,0 +1 @@ +[0,"en","QrwRSsOy",1,null,["aboutMessage","About ",[6,0]],["helloAndWelcome","Welcome von <",[8,0],[13,1]],[6,"newMessages","test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"newMessages2","test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]],["otherMsg","other"]] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarbctx2.json b/pkgs/messages/example/assets/testarbctx2.json deleted file mode 100644 index a56c79c5..00000000 --- a/pkgs/messages/example/assets/testarbctx2.json +++ /dev/null @@ -1 +0,0 @@ -[0,"en","QrwRSsOy",0,null,["About ",[6,0]],["Welcome von <",[8,0],[13,1]],[6,"test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]],"other"] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarbctx2_fr.arb.json b/pkgs/messages/example/assets/testarbctx2_fr.arb.json new file mode 100644 index 00000000..d3895436 --- /dev/null +++ b/pkgs/messages/example/assets/testarbctx2_fr.arb.json @@ -0,0 +1 @@ +[0,"fr","390XWry3",1,null,["aboutMessage","Sur ",[4,0]],["helloAndWelcome","Welcome von <",[8,0],[13,1]],[6,"newMessages","test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"newMessages2","test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]],["otherMsg","other"]] \ No newline at end of file diff --git a/pkgs/messages/example/assets/testarbctx2_fr.json b/pkgs/messages/example/assets/testarbctx2_fr.json deleted file mode 100644 index 61b6c08f..00000000 --- a/pkgs/messages/example/assets/testarbctx2_fr.json +++ /dev/null @@ -1 +0,0 @@ -[0,"fr","EyPjEJJU",0,null,["Sur ",[4,0]],["Welcome von <",[8,0],[13,1]],[6,"test ",[3,0,["test new messages",[5,0]],[0,"No new messages",1,"One new message","w2","Two new Messages"]]],[6,"test ",[4,0,"Two new Messages",{"male":"No new messages","female":"One new message"}]],"other"] \ No newline at end of file diff --git a/pkgs/messages/example/lib/l10n.messages b/pkgs/messages/example/lib/l10n.messages deleted file mode 100644 index e69de29b..00000000 diff --git a/pkgs/messages/example/lib/messages.g.dart b/pkgs/messages/example/lib/messages.g.dart index c7a08f48..659ab734 100644 --- a/pkgs/messages/example/lib/messages.g.dart +++ b/pkgs/messages/example/lib/messages.g.dart @@ -34,14 +34,21 @@ class AboutPageMessages { final Map _messages = {}; static const _dataFiles = { - 'fr': ('package:example/assets/l10n/testarbctx2_fr.json', 'EyPjEJJU'), - 'en': ('package:example/assets/l10n/testarbctx2.json', 'QrwRSsOy') + 'fr': ('package:example/assets/testarbctx2_fr.arb.json', '390XWry3'), + 'en': ('package:example/assets/testarbctx2.arb.json', 'QrwRSsOy') }; String get currentLocale => _currentLocale; MessageList get _currentMessages => _messages[currentLocale]!; + String getById( + String id, [ + List args = const [], + ]) { + return _currentMessages.generateStringAtId(id, args); + } + static Iterable get knownLocales => _dataFiles.keys; Future loadLocale(String locale) async { @@ -99,14 +106,21 @@ class HomePageMessages { final Map _messages = {}; static const _dataFiles = { - 'de': ('package:example/assets/l10n/testarb_de.json', 'hbDN1MhX'), - 'en': ('package:example/assets/l10n/testarb.json', 'dr9Md951') + 'de': ('package:example/assets/testarb_de.arb.json', 'hbDN1MhX'), + 'en': ('package:example/assets/testarb.arb.json', 'dr9Md951') }; String get currentLocale => _currentLocale; MessageList get _currentMessages => _messages[currentLocale]!; + String getById( + String id, [ + List args = const [], + ]) { + return _currentMessages.generateStringAtId(id, args); + } + static Iterable get knownLocales => _dataFiles.keys; Future loadLocale(String locale) async { diff --git a/pkgs/messages/example/pubspec.yaml b/pkgs/messages/example/pubspec.yaml index 432619d9..c6964e9c 100644 --- a/pkgs/messages/example/pubspec.yaml +++ b/pkgs/messages/example/pubspec.yaml @@ -19,7 +19,10 @@ dev_dependencies: package_options: messages_builder: - generateMethods: true - generateFindById: false - generateFindBy: integer - pluralSelector: intl + generate_methods: true + generate_find_by_id: true + generate_find_by: integer + plural_selector: intl + arb_input_folder: assets/l10n/ + message_output_folder: assets/ + generated_code_file: lib/messages.g.dart diff --git a/pkgs/messages/examples/my_application/assets/l10n/messages.json b/pkgs/messages/examples/my_application/assets/messages.arb.json similarity index 100% rename from pkgs/messages/examples/my_application/assets/l10n/messages.json rename to pkgs/messages/examples/my_application/assets/messages.arb.json diff --git a/pkgs/messages/examples/my_application/lib/l10n.messages b/pkgs/messages/examples/my_application/lib/l10n.messages deleted file mode 100644 index e69de29b..00000000 diff --git a/pkgs/messages/examples/my_application/lib/my_application.dart b/pkgs/messages/examples/my_application/lib/my_application.dart index 477ed3ba..5229c388 100644 --- a/pkgs/messages/examples/my_application/lib/my_application.dart +++ b/pkgs/messages/examples/my_application/lib/my_application.dart @@ -1,6 +1,8 @@ +import 'dart:io'; + import 'package:my_shopping_cart/my_shopping_cart.dart'; -import 'messages.g.dart'; +import 'src/messages.g.dart'; Future items() async { var myShoppingCart = MyShoppingCart(); @@ -9,9 +11,10 @@ Future items() async { } Future sale() async { - var myShoppingCart = MyAppMessages(); - await myShoppingCart.loadAllLocales(); - return myShoppingCart.current_sale_name( + var appMessages = MyAppMessages( + (id) => File(id.substring(id.indexOf('/') + 1)).readAsString()); + await appMessages.loadAllLocales(); + return appMessages.current_sale_name( DateTime.now().month < 4 || DateTime.now().month > 10 ? 'winter' : 'summer', ); } diff --git a/pkgs/messages/examples/my_application/lib/messages.g.dart b/pkgs/messages/examples/my_application/lib/src/messages.g.dart similarity index 96% rename from pkgs/messages/examples/my_application/lib/messages.g.dart rename to pkgs/messages/examples/my_application/lib/src/messages.g.dart index bd7a39ed..6819f311 100644 --- a/pkgs/messages/examples/my_application/lib/messages.g.dart +++ b/pkgs/messages/examples/my_application/lib/src/messages.g.dart @@ -34,7 +34,7 @@ class MyAppMessages { final Map _messages = {}; static const _dataFiles = { - 'en_US': ('package:my_application/assets/l10n/messages.json', 'IT21w/eV') + 'en_US': ('package:my_application/assets/messages.arb.json', 'IT21w/eV') }; String get currentLocale => _currentLocale; diff --git a/pkgs/messages/examples/my_shopping_cart/assets/l10n/messages.json b/pkgs/messages/examples/my_shopping_cart/assets/messages.arb.json similarity index 100% rename from pkgs/messages/examples/my_shopping_cart/assets/l10n/messages.json rename to pkgs/messages/examples/my_shopping_cart/assets/messages.arb.json diff --git a/pkgs/messages/examples/my_shopping_cart/lib/src/l10n.messages b/pkgs/messages/examples/my_shopping_cart/lib/src/l10n.messages deleted file mode 100644 index e69de29b..00000000 diff --git a/pkgs/messages/examples/my_shopping_cart/lib/src/messages.g.dart b/pkgs/messages/examples/my_shopping_cart/lib/src/messages.g.dart index 3b8e745c..b5494953 100644 --- a/pkgs/messages/examples/my_shopping_cart/lib/src/messages.g.dart +++ b/pkgs/messages/examples/my_shopping_cart/lib/src/messages.g.dart @@ -34,7 +34,7 @@ class ShoppingCartMessages { final Map _messages = {}; static const _dataFiles = { - 'en_US': ('package:my_shopping_cart/assets/l10n/messages.json', 'Nj229ee7') + 'en_US': ('package:my_shopping_cart/assets/messages.arb.json', 'Nj229ee7') }; String get currentLocale => _currentLocale; diff --git a/pkgs/messages/examples/my_shopping_cart/lib/src/my_shopping_cart_base.dart b/pkgs/messages/examples/my_shopping_cart/lib/src/my_shopping_cart_base.dart index 657cfb4f..85fd6eca 100644 --- a/pkgs/messages/examples/my_shopping_cart/lib/src/my_shopping_cart_base.dart +++ b/pkgs/messages/examples/my_shopping_cart/lib/src/my_shopping_cart_base.dart @@ -1,7 +1,10 @@ +import 'dart:io'; + import 'messages.g.dart'; class MyShoppingCart { - final _messages = ShoppingCartMessages(); + final _messages = ShoppingCartMessages( + (id) => File(id.substring(id.indexOf('/') + 1)).readAsString()); Future loadMessages() async => await _messages.loadAllLocales(); String itemsInCart(int number) => _messages.itemsInCart(number); diff --git a/pkgs/messages/examples/my_shopping_cart/pubspec.yaml b/pkgs/messages/examples/my_shopping_cart/pubspec.yaml index de62f9c3..f8aeb4da 100644 --- a/pkgs/messages/examples/my_shopping_cart/pubspec.yaml +++ b/pkgs/messages/examples/my_shopping_cart/pubspec.yaml @@ -14,3 +14,9 @@ dependencies: dev_dependencies: lints: ^4.0.0 test: ^1.24.0 + +package_options: + messages_builder: + arb_input_folder: assets/l10n/ + message_output_folder: assets/ + generated_code_file: lib/src/messages.g.dart diff --git a/pkgs/messages_builder/lib/builder.dart b/pkgs/messages_builder/lib/builder.dart index a3bfca9c..c151fd99 100644 --- a/pkgs/messages_builder/lib/builder.dart +++ b/pkgs/messages_builder/lib/builder.dart @@ -4,11 +4,10 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; -import 'package:build/build.dart'; import 'package:code_builder/code_builder.dart'; import 'package:collection/collection.dart'; -import 'package:glob/glob.dart'; import 'package:path/path.dart' as path; import 'arb_parser.dart'; @@ -17,44 +16,28 @@ import 'code_generation/library_generation.dart'; import 'generation_options.dart'; import 'message_with_metadata.dart'; -Builder messagesBuilder(BuilderOptions options) => - MessagesBuilder(options.config); - -class MessagesBuilder implements Builder { - final Map config; - - MessagesBuilder(this.config); - - @override - Map> get buildExtensions => { - 'l10n.messages': ['messages.g.dart'], - }; - - @override - Future build(BuildStep buildStep) async { - final s = await GenerationOptions.getPubspecFrom(buildStep); - final generationOptions = await GenerationOptions.fromPubspec(s); - await BuildStepGenerator(buildStep, generationOptions).build(); - } -} - -class BuildStepGenerator { - final BuildStep buildStep; +class MessageCallingCodeGenerator { final GenerationOptions options; + final Map mapping; - BuildStepGenerator(this.buildStep, this.options); + MessageCallingCodeGenerator({ + required this.options, + required this.mapping, + }); Future build() async { final allMessageFiles = await getParsedMessageFiles(); final libraries = []; for (final input in allMessageFiles) { final parentFile = getParentFile(allMessageFiles, input); - final reducedMessageFile = - scrub(input.$2, parentFile.$2.messages.map((e) => e.name).toList()); - if (parentFile.$1 == input.$1) { + final scrubbedMessageFile = scrub( + input.message, + parentFile.message.messages.map((e) => e.name).toList(), + ); + if (parentFile.path == input.path) { final library = await writeDartLibrary( allMessageFiles, - reducedMessageFile, + scrubbedMessageFile, ); libraries.add(library); } @@ -65,13 +48,8 @@ class BuildStepGenerator { libraries: libraries, ).generate(); - await buildStep.writeAsString( - AssetId( - buildStep.inputId.package, - buildStep.inputId.path - .replaceFirst('l10n.messages', 'messages.g.dart')), - code, - ); + await options.generatedCodeFile.create(recursive: true); + await options.generatedCodeFile.writeAsString(code); } } @@ -93,18 +71,18 @@ class BuildStepGenerator { /// format and makes the available to the user in a way specified through the /// `GenerationOptions`. Future writeDartLibrary( - List<(AssetId, MessagesWithMetadata)> assetList, + List assetList, MessagesWithMetadata messageList, ) async { final resourcesInContext = assetList - .where((resource) => resource.$2.context == messageList.context); + .where((resource) => resource.message.context == messageList.context); final localeToResourceInfo = Map.fromEntries(resourcesInContext.map((resource) => MapEntry( - resource.$2.locale ?? inferLocale(resource.$1.path) ?? 'en_US', + resource.message.locale ?? 'en_US', ( - id: 'package:${buildStep.inputId.package}/${resource.$1.changeExtension('.json').path}', - hasch: resource.$2.hash, + id: 'package:${options.packageName}/${resource.path}', + hasch: resource.message.hash, ), ))); @@ -118,29 +96,27 @@ class BuildStepGenerator { ).generate(); } - Future> getParsedMessageFiles() async => - buildStep - .findAssets(Glob('**.arb')) - .asyncMap((assetId) async => ( - assetId, - await parseMessageFile(await getArbfile(assetId), options) + Future> getParsedMessageFiles() async => + Future.wait(mapping.entries + .map((p) async => ParsedMessageFile( + path: path.relative(p.value, from: Directory.current.path), + message: + await parseMessageFile(await getArbfile(p.key), options), )) - .toList(); + .toList()); - Future getArbfile(AssetId assetId) async { - final arbFile = await buildStep.readAsString(assetId); - return arbFile; - } + Future getArbfile(String path) async => + await File(path).readAsString(); /// Either get the referenced parent file, or try to infer which it might be. - static (AssetId, MessagesWithMetadata) getParentFile( - List<(AssetId, MessagesWithMetadata)> arbResources, - (AssetId, MessagesWithMetadata) arb, + static ParsedMessageFile getParentFile( + List arbFiles, + ParsedMessageFile currentFile, ) { /// If the reference file is explicitly named, return that. - if (arb.$2.referencePath != null) { - final reference = arbResources - .where((element) => element.$1.path == arb.$2.referencePath) + if (currentFile.message.referencePath != null) { + final reference = arbFiles + .where((element) => element.path == currentFile.message.referencePath) .firstOrNull; if (reference != null) { return reference; @@ -148,23 +124,23 @@ class BuildStepGenerator { } /// If the current file is a reference for others, return the current file. - final references = arbResources - .where((resource) => resource.$2.referencePath == arb.$1.path); - if (references.contains(arb)) { - return arb; + final references = arbFiles.where( + (resource) => resource.message.referencePath == currentFile.path); + if (references.contains(currentFile)) { + return currentFile; } /// Try to infer by looking at which files contain metadata, which is a sign /// they might be the references for others in the same context. final contextLeads = - arbResources.groupListsBy((resource) => resource.$2.context); - final contextWithMetadata = contextLeads[arb.$2.context]! - .firstWhereOrNull((element) => element.$2.hasMetadata); + arbFiles.groupListsBy((resource) => resource.message.context); + final contextWithMetadata = contextLeads[currentFile.message.context]! + .firstWhereOrNull((element) => element.message.hasMetadata); if (contextWithMetadata != null) { return contextWithMetadata; } - return arb; + return currentFile; } /// Display a notification to the user to include the newly generated files @@ -193,10 +169,9 @@ Future parseMessageFile( return ArbParser(options.findById).parseMessageFile(arb); } -String? inferLocale(String localPath) { - final skip = path.basenameWithoutExtension(localPath).split('_').skip(1); - if (skip.isEmpty) { - return null; - } - return skip.join('_'); +class ParsedMessageFile { + final String path; + final MessagesWithMetadata message; + + ParsedMessageFile({required this.path, required this.message}); } diff --git a/pkgs/messages_builder/lib/generation_options.dart b/pkgs/messages_builder/lib/generation_options.dart index 15943807..54b484c4 100644 --- a/pkgs/messages_builder/lib/generation_options.dart +++ b/pkgs/messages_builder/lib/generation_options.dart @@ -2,8 +2,9 @@ // 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 'package:build/build.dart'; -import 'package:glob/glob.dart'; +import 'dart:io'; + +import 'package:collection/collection.dart'; import 'package:yaml/yaml.dart'; /// Options for the message data file and code generation. @@ -42,6 +43,36 @@ class GenerationOptions { /// The origin of the algorithm for determining which plural case to use. final PluralSelectorType pluralSelector; + /// Where the arb files are located. + final Directory arbFolder; + + /// Where to write the message data files to. + final Directory messageFolder; + + final File generatedCodeFile; + + final String packageName; + + static const _generateMethodsKey = 'generate_methods'; + static const _generateFindByIdKey = 'generate_find_by_id'; + static const _generateFindByKey = 'generate_find_by'; + static const _headerKey = 'header'; + static const _pluralSelectorKey = 'plural_selector'; + static const _arbInputFolderKey = 'arb_input_folder'; + static const _messageOutputFolderKey = 'message_output_folder'; + static const _generatedCodeFileKey = 'generated_code_file'; + + static List get validKeys => [ + _generateMethodsKey, + _generateFindByIdKey, + _generateFindByKey, + _pluralSelectorKey, + _headerKey, + _arbInputFolderKey, + _messageOutputFolderKey, + _generatedCodeFileKey, + ]; + GenerationOptions({ required this.serialization, required this.deserialization, @@ -50,33 +81,44 @@ class GenerationOptions { required this.indexType, required this.header, required this.pluralSelector, + required this.packageName, + required this.arbFolder, + required this.messageFolder, + required this.generatedCodeFile, }); static Future fromPubspec(String pubspecData) async { final pubspec = loadYaml(pubspecData) as YamlMap; final packageOptions = pubspec['package_options'] as YamlMap?; final messagesOptions = packageOptions?['messages_builder'] as YamlMap?; + final illegalKey = messagesOptions?.keys + .firstWhereOrNull((key) => !validKeys.contains(key)); + if (illegalKey != null) { + throw ArgumentError( + 'The message options contain the illegal key $illegalKey'); + } final generationOptions = GenerationOptions( - serialization: SerializationType.json, - deserialization: DeserializationType.web, - messageCalls: (messagesOptions?['generateMethods'] as bool?) ?? true, - findById: (messagesOptions?['generateFindById'] as bool?) ?? false, - indexType: _indexType(messagesOptions), - header: messagesOptions?['header'] as String? ?? - 'Generated by package:messages_builder.', - pluralSelector: _pluralSelector(messagesOptions), - ); + serialization: SerializationType.json, + deserialization: DeserializationType.web, + messageCalls: (messagesOptions?[_generateMethodsKey] as bool?) ?? true, + findById: (messagesOptions?[_generateFindByIdKey] as bool?) ?? false, + indexType: _indexType(messagesOptions), + header: messagesOptions?[_headerKey] as String? ?? + 'Generated by package:messages_builder.', + pluralSelector: _pluralSelector(messagesOptions), + packageName: pubspec['name'] as String, + arbFolder: Directory( + messagesOptions?[_arbInputFolderKey] as String? ?? 'assets/l10n/'), + messageFolder: Directory( + messagesOptions?[_messageOutputFolderKey] as String? ?? 'assets/'), + generatedCodeFile: File( + messagesOptions?[_generatedCodeFileKey] as String? ?? + 'lib/src/messages.g.dart')); return generationOptions; } - static Future getPubspecFrom(BuildStep buildStep) async { - final pubspecId = await buildStep.findAssets(Glob('pubspec.yaml')).first; - final pubspecData = await buildStep.readAsString(pubspecId); - return pubspecData; - } - static IndexType _indexType(YamlMap? messagesOptions) { - final generateFindString = messagesOptions?['generateFindBy'] as String?; + final generateFindString = messagesOptions?[_generateFindByKey] as String?; return generateFindString != null ? IndexType.values .where((type) => type.name == generateFindString) @@ -85,7 +127,8 @@ class GenerationOptions { } static PluralSelectorType _pluralSelector(YamlMap? messagesOptions) { - final pluralSelectorString = messagesOptions?['pluralSelector'] as String?; + final pluralSelectorString = + messagesOptions?[_pluralSelectorKey] as String?; return pluralSelectorString != null ? PluralSelectorType.values .where((type) => type.name == pluralSelectorString) diff --git a/pkgs/messages_builder/lib/message_data_builder.dart b/pkgs/messages_builder/lib/message_data_builder.dart index 243e3089..213166e1 100644 --- a/pkgs/messages_builder/lib/message_data_builder.dart +++ b/pkgs/messages_builder/lib/message_data_builder.dart @@ -11,15 +11,18 @@ import 'builder.dart'; import 'generation_options.dart'; import 'message_with_metadata.dart'; -class MessagesDataBuilder { - //TODO allow arbs from other locations than package root subfolders - MessagesDataBuilder(); +class MessageDataFileBuilder { + final Directory inputFolder; + final Directory outputFolder; + final GenerationOptions generationOptions; - Future run({ - required Directory inputFolder, - required Directory outputFolder, - required String libOutput, - }) async { + MessageDataFileBuilder({ + required this.inputFolder, + required this.outputFolder, + required this.generationOptions, + }); + + Future> run() async { print('Starting to add arb files from $inputFolder to $outputFolder'); final arbFiles = await inputFolder .list() @@ -27,11 +30,12 @@ class MessagesDataBuilder { .map((file) => file.path) .where((path) => p.extension(path) == '.arb') .toList(); + final mapping = {}; + for (final arbFilePath in arbFiles) { print('Generating $arbFilePath, bundle this in your assets.'); final arbFileUri = Uri.file(arbFilePath); final arbFileContents = await File.fromUri(arbFileUri).readAsString(); - final generationOptions = await _generationOptions(); final messageBundle = await parseMessageFile( arbFileContents, generationOptions, @@ -41,13 +45,18 @@ class MessagesDataBuilder { final data = _arbToData(messageBundle, arbFilePath, serializer); - final assetName = - p.setExtension(p.basename(arbFilePath), serializer.extension); + final assetName = p.setExtension( + p.basename(arbFilePath), + '.arb${serializer.extension}', + ); - final dataFile = File.fromUri(outputFolder.uri.resolve(assetName)); + final outputDataPath = outputFolder.uri.resolve(assetName); + final dataFile = File.fromUri(outputDataPath); await dataFile.create(); await dataFile.writeAsString(data); + mapping[arbFilePath] = outputDataPath.path; } + return mapping; } String _arbToData( @@ -62,10 +71,4 @@ class MessagesDataBuilder { messageBundle.messages.map((e) => e.message).toList(), ) .data; - - Future _generationOptions() async { - final pubspecUri = Directory.current.uri.resolve('pubspec.yaml'); - final file = File.fromUri(pubspecUri); - return GenerationOptions.fromPubspec(await file.readAsString()); - } } diff --git a/pkgs/messages_builder/lib/message_with_metadata.dart b/pkgs/messages_builder/lib/message_with_metadata.dart index 1518153d..fe4a0acb 100644 --- a/pkgs/messages_builder/lib/message_with_metadata.dart +++ b/pkgs/messages_builder/lib/message_with_metadata.dart @@ -2,7 +2,6 @@ // 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 'package:build/build.dart'; import 'package:messages/messages.dart'; class MessageWithMetadata { @@ -41,7 +40,6 @@ class MessagesWithMetadata { String? referencePath, String? hash, bool? hasMetadata, - AssetId? assetId, }) { return MessagesWithMetadata( messages ?? this.messages, diff --git a/pkgs/messages_builder/pubspec.yaml b/pkgs/messages_builder/pubspec.yaml index 7bbd008a..2d364a5e 100644 --- a/pkgs/messages_builder/pubspec.yaml +++ b/pkgs/messages_builder/pubspec.yaml @@ -9,21 +9,16 @@ environment: publish_to: none dependencies: - build: ^2.3.1 - build_runner: ^2.0.0 - build_web_compilers: ^4.0.10 code_builder: ^4.3.0 collection: ^1.18.0 crypto: ^3.0.3 dart_style: ^2.2.4 - glob: ^2.1.1 intl: ^0.19.0 logging: ^1.2.0 messages: path: ../messages messages_serializer: path: ../messages_serializer - native_assets_cli: ^0.8.0 path: ^1.8.2 yaml: ^3.1.1 diff --git a/pkgs/messages_serializer/pubspec.yaml b/pkgs/messages_serializer/pubspec.yaml index 766b8e23..15285a31 100644 --- a/pkgs/messages_serializer/pubspec.yaml +++ b/pkgs/messages_serializer/pubspec.yaml @@ -14,5 +14,4 @@ dependencies: dev_dependencies: dart_flutter_team_lints: ^3.0.0 - intl: ^0.18.1 test: ^1.21.0