OLD | NEW |
| (Empty) |
1 #!/usr/bin/env dart | |
2 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | |
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. | |
5 | |
6 /** | |
7 * This script uses the extract_messages.dart library to find the Intl.message | |
8 * calls in the target dart files and produces ARB format output. See | |
9 * https://code.google.com/p/arb/wiki/ApplicationResourceBundleSpecification | |
10 */ | |
11 library extract_to_arb; | |
12 | |
13 import 'dart:convert'; | |
14 import 'dart:io'; | |
15 import 'package:intl/extract_messages.dart'; | |
16 import 'package:path/path.dart' as path; | |
17 import 'package:intl/src/intl_message.dart'; | |
18 import 'package:args/args.dart'; | |
19 | |
20 main(List<String> args) { | |
21 var targetDir; | |
22 var parser = new ArgParser(); | |
23 parser.addFlag("suppress-warnings", | |
24 defaultsTo: false, | |
25 callback: (x) => suppressWarnings = x, | |
26 help: 'Suppress printing of warnings.'); | |
27 parser.addFlag("warnings-are-errors", | |
28 defaultsTo: false, | |
29 callback: (x) => warningsAreErrors = x, | |
30 help: 'Treat all warnings as errors, stop processing '); | |
31 parser.addFlag("embedded-plurals", | |
32 defaultsTo: true, | |
33 callback: (x) => allowEmbeddedPluralsAndGenders = x, | |
34 help: 'Allow plurals and genders to be embedded as part of a larger ' | |
35 'string, otherwise they must be at the top level.'); | |
36 | |
37 parser.addOption("output-dir", | |
38 defaultsTo: '.', | |
39 callback: (value) => targetDir = value, | |
40 help: 'Specify the output directory.'); | |
41 parser.parse(args); | |
42 if (args.length == 0) { | |
43 print('Accepts Dart files and produces intl_messages.json'); | |
44 print('Usage: extract_to_arb [options] [files.dart]'); | |
45 print(parser.usage); | |
46 exit(0); | |
47 } | |
48 var allMessages = {}; | |
49 for (var arg in args.where((x) => x.contains(".dart"))) { | |
50 var messages = parseFile(new File(arg)); | |
51 messages.forEach((k, v) => allMessages.addAll(toARB(v))); | |
52 } | |
53 var file = new File(path.join(targetDir, 'intl_messages.arb')); | |
54 file.writeAsStringSync(JSON.encode(allMessages)); | |
55 if (hasWarnings && warningsAreErrors) { | |
56 exit(1); | |
57 } | |
58 } | |
59 | |
60 /** | |
61 * This is a placeholder for transforming a parameter substitution from | |
62 * the translation file format into a Dart interpolation. In our case we | |
63 * store it to the file in Dart interpolation syntax, so the transformation | |
64 * is trivial. | |
65 */ | |
66 String leaveTheInterpolationsInDartForm(MainMessage msg, chunk) { | |
67 if (chunk is String) return chunk; | |
68 if (chunk is int) return "\$${msg.arguments[chunk]}"; | |
69 return chunk.toCode(); | |
70 } | |
71 | |
72 /** | |
73 * Convert the [MainMessage] to a trivial JSON format. | |
74 */ | |
75 Map toARB(MainMessage message) { | |
76 if (message.messagePieces.isEmpty) return null; | |
77 var out = {}; | |
78 out[message.name] = icuForm(message); | |
79 out["@${message.name}"] = arbMetadata(message); | |
80 return out; | |
81 } | |
82 | |
83 Map arbMetadata(MainMessage message) { | |
84 var out = {}; | |
85 var desc = message.description; | |
86 if (desc != null) { | |
87 out["description"] = desc; | |
88 } | |
89 out["type"] = "text"; | |
90 var placeholders = {}; | |
91 for (var arg in message.arguments) { | |
92 addArgumentFor(message, arg, placeholders); | |
93 } | |
94 out["placeholders"] = placeholders; | |
95 return out; | |
96 } | |
97 | |
98 void addArgumentFor(MainMessage message, String arg, Map result) { | |
99 var extraInfo = {}; | |
100 if (message.examples != null && message.examples[arg] != null) { | |
101 extraInfo["example"] = message.examples[arg]; | |
102 } | |
103 result[arg] = extraInfo; | |
104 } | |
105 | |
106 /** | |
107 * Return a version of the message string with | |
108 * with ICU parameters "{variable}" rather than Dart interpolations "$variable". | |
109 */ | |
110 String icuForm(MainMessage message) => | |
111 message.expanded(turnInterpolationIntoICUForm); | |
112 | |
113 String turnInterpolationIntoICUForm(Message message, chunk, | |
114 {bool shouldEscapeICU: false}) { | |
115 if (chunk is String) { | |
116 return shouldEscapeICU ? escape(chunk) : chunk; | |
117 } | |
118 if (chunk is int && chunk >= 0 && chunk < message.arguments.length) { | |
119 return "{${message.arguments[chunk]}}"; | |
120 } | |
121 if (chunk is SubMessage) { | |
122 return chunk.expanded((message, chunk) => | |
123 turnInterpolationIntoICUForm(message, chunk, shouldEscapeICU: true)); | |
124 } | |
125 if (chunk is Message) { | |
126 return chunk.expanded((message, chunk) => turnInterpolationIntoICUForm( | |
127 message, chunk, shouldEscapeICU: shouldEscapeICU)); | |
128 } | |
129 throw new FormatException("Illegal interpolation: $chunk"); | |
130 } | |
131 | |
132 String escape(String s) { | |
133 return s.replaceAll("'", "''").replaceAll("{", "'{'").replaceAll("}", "'}'"); | |
134 } | |
OLD | NEW |