OLD | NEW |
1 #!/usr/bin/env dart | 1 #!/usr/bin/env dart |
2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 2 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 /** | 6 /** |
7 * A main program that takes as input a source Dart file and a number | 7 * A main program that takes as input a source Dart file and a number |
8 * of JSON files representing translations of messages from the corresponding | 8 * of JSON files representing translations of messages from the corresponding |
9 * Dart file. See extract_to_json.dart and make_hardcoded_translation.dart. | 9 * Dart file. See extract_to_json.dart and make_hardcoded_translation.dart. |
10 * | 10 * |
11 * This produces a series of files named | 11 * This produces a series of files named |
12 * "messages_<locale>.dart" containing messages for a particular locale | 12 * "messages_<locale>.dart" containing messages for a particular locale |
13 * and a main import file named "messages_all.dart" which has imports all of | 13 * and a main import file named "messages_all.dart" which has imports all of |
14 * them and provides an initializeMessages function. | 14 * them and provides an initializeMessages function. |
15 */ | 15 */ |
16 library generate_from_json; | 16 library generate_from_json; |
17 | 17 |
18 import 'dart:io'; | 18 import 'dart:io'; |
19 import 'package:intl/extract_messages.dart'; | 19 import 'package:intl/extract_messages.dart'; |
20 import 'package:intl/src/intl_message.dart'; | 20 import 'package:intl/src/intl_message.dart'; |
21 import 'extract_to_json.dart'; | 21 import 'extract_to_json.dart'; |
22 import 'package:intl/generate_localized.dart'; | 22 import 'package:intl/generate_localized.dart'; |
23 import 'dart:json' as json; | 23 import 'dart:json' as json; |
24 import 'package:pathos/path.dart' as path; | 24 import 'package:pathos/path.dart' as path; |
25 import 'package:args/args.dart'; | 25 import 'package:args/args.dart'; |
| 26 import 'package:serialization/serialization.dart'; |
26 | 27 |
27 /** | 28 /** |
28 * Keeps track of all the messages we have processed so far, keyed by message | 29 * Keeps track of all the messages we have processed so far, keyed by message |
29 * name. | 30 * name. |
30 */ | 31 */ |
31 Map<String, IntlMessage> messages; | 32 Map<String, MainMessage> messages; |
32 | 33 |
33 main() { | 34 main() { |
34 var targetDir; | 35 var targetDir; |
35 var args = new Options().arguments; | 36 var args = new Options().arguments; |
36 var parser = new ArgParser(); | 37 var parser = new ArgParser(); |
37 parser.addFlag("suppress-warnings", defaultsTo: false, | 38 parser.addFlag("suppress-warnings", defaultsTo: false, |
38 callback: (x) => suppressWarnings = x); | 39 callback: (x) => suppressWarnings = x); |
39 parser.addOption("output-dir", defaultsTo: '.', | 40 parser.addOption("output-dir", defaultsTo: '.', |
40 callback: (x) => targetDir = x); | 41 callback: (x) => targetDir = x); |
41 parser.addOption("generated-file-prefix", defaultsTo: '', | 42 parser.addOption("generated-file-prefix", defaultsTo: '', |
42 callback: (x) => generatedFilePrefix = x); | 43 callback: (x) => generatedFilePrefix = x); |
43 parser.parse(args); | 44 parser.parse(args); |
44 if (args.length == 0) { | 45 var dartFiles = args.where((x) => x.endsWith("dart")).toList(); |
| 46 var jsonFiles = args.where((x) => x.endsWith(".json")).toList(); |
| 47 if (dartFiles.length == 0 || jsonFiles.length == 0) { |
45 print('Usage: generate_from_json [--output-dir=<dir>]' | 48 print('Usage: generate_from_json [--output-dir=<dir>]' |
46 ' [--generated-file-prefix=<prefix>] file1.dart file2.dart ...' | 49 ' [--generated-file-prefix=<prefix>] file1.dart file2.dart ...' |
47 ' translation1.json translation2.json ...'); | 50 ' translation1.json translation2.json ...'); |
48 exit(0); | 51 exit(0); |
49 } | 52 } |
50 | 53 |
51 var dartFiles = args.where((x) => x.endsWith("dart")).toList(); | |
52 var jsonFiles = args.where((x) => x.endsWith(".json")).toList(); | |
53 | |
54 // We're re-parsing the original files to find the corresponding messages, | 54 // We're re-parsing the original files to find the corresponding messages, |
55 // so if there are warnings extracting the messages, suppress them. | 55 // so if there are warnings extracting the messages, suppress them. |
56 suppressWarnings = true; | 56 suppressWarnings = true; |
57 var allMessages = dartFiles.map((each) => parseFile(new File(each))); | 57 var allMessages = dartFiles.map((each) => parseFile(new File(each))); |
58 | 58 |
59 messages = new Map(); | 59 messages = new Map(); |
60 for (var eachMap in allMessages) { | 60 for (var eachMap in allMessages) { |
61 eachMap.forEach((key, value) => messages[key] = value); | 61 eachMap.forEach((key, value) => messages[key] = value); |
62 } | 62 } |
63 for (var arg in jsonFiles) { | 63 for (var arg in jsonFiles) { |
64 var file = new File(arg); | 64 var file = new File(arg); |
65 generateLocaleFile(file, targetDir); | 65 generateLocaleFile(file, targetDir); |
66 } | 66 } |
67 | 67 |
68 var mainImportFile = new File(path.join(targetDir, | 68 var mainImportFile = new File(path.join(targetDir, |
69 '${generatedFilePrefix}messages_all.dart')); | 69 '${generatedFilePrefix}messages_all.dart')); |
70 mainImportFile.writeAsStringSync(generateMainImportFile()); | 70 mainImportFile.writeAsStringSync(generateMainImportFile()); |
71 } | 71 } |
72 | 72 |
| 73 var s = new Serialization(); |
| 74 var format = const SimpleFlatFormat(); |
| 75 var r = s.newReader(format); |
| 76 |
| 77 recreateIntlObjects(key, value) { |
| 78 if (value == null) return null; |
| 79 if (value is String || value is int) return Message.from(value, null); |
| 80 if (value is List) { |
| 81 var newThing = r.read(value); |
| 82 return newThing; |
| 83 } |
| 84 throw new FormatException("Invalid input data $value"); |
| 85 } |
| 86 |
73 /** | 87 /** |
74 * Create the file of generated code for a particular locale. We read the json | 88 * Create the file of generated code for a particular locale. We read the json |
75 * data and create [BasicTranslatedMessage] instances from everything, | 89 * data and create [BasicTranslatedMessage] instances from everything, |
76 * excluding only the special _locale attribute that we use to indicate the | 90 * excluding only the special _locale attribute that we use to indicate the |
77 * locale. | 91 * locale. |
78 */ | 92 */ |
79 void generateLocaleFile(File file, String targetDir) { | 93 void generateLocaleFile(File file, String targetDir) { |
80 var src = file.readAsStringSync(); | 94 var src = file.readAsStringSync(); |
81 var data = json.parse(src); | 95 var data = json.parse(src); |
82 var locale = data["_locale"]; | 96 data.forEach((k, v) => data[k] = recreateIntlObjects(k, v)); |
| 97 var locale = data["_locale"].string; |
83 allLocales.add(locale); | 98 allLocales.add(locale); |
84 | 99 |
85 var translations = []; | 100 var translations = []; |
86 data.forEach((key, value) { | 101 data.forEach((key, value) { |
87 if (key[0] != "_") { | 102 if (key[0] != "_") { |
88 translations.add(new BasicTranslatedMessage(key, value)); | 103 translations.add(new BasicTranslatedMessage(key, value)); |
89 } | 104 } |
90 }); | 105 }); |
91 generateIndividualMessageFile(locale, translations, targetDir); | 106 generateIndividualMessageFile(locale, translations, targetDir); |
92 } | 107 } |
93 | 108 |
94 /** | 109 /** |
95 * A TranslatedMessage that just uses the name as the id and knows how to look | 110 * A TranslatedMessage that just uses the name as the id and knows how to look |
96 * up its original message in our [messages]. | 111 * up its original message in our [messages]. |
97 */ | 112 */ |
98 class BasicTranslatedMessage extends TranslatedMessage { | 113 class BasicTranslatedMessage extends TranslatedMessage { |
99 BasicTranslatedMessage(String name, String translated) : | 114 BasicTranslatedMessage(String name, translated) : |
100 super(name, translated); | 115 super(name, translated); |
101 | 116 |
102 IntlMessage get originalMessage => | 117 MainMessage get originalMessage => |
103 (super.originalMessage == null) ? _findOriginal() : super.originalMessage; | 118 (super.originalMessage == null) ? _findOriginal() : super.originalMessage; |
104 | 119 |
105 // We know that our [id] is the name of the message, which is used as the | 120 // We know that our [id] is the name of the message, which is used as the |
106 //key in [messages]. | 121 //key in [messages]. |
107 IntlMessage _findOriginal() => originalMessage = messages[id]; | 122 MainMessage _findOriginal() => originalMessage = messages[id]; |
108 } | 123 } |
OLD | NEW |