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 * This simulates a translation process, reading the messages generated | 7 * This simulates a translation process, reading the messages generated |
8 * from extract_message.dart for the files sample_with_messages.dart and | 8 * from extract_message.dart for the files sample_with_messages.dart and |
9 * part_of_sample_with_messages.dart and writing out hard-coded translations for | 9 * part_of_sample_with_messages.dart and writing out hard-coded translations for |
10 * German and French locales. | 10 * German and French locales. |
11 */ | 11 */ |
12 | 12 |
13 import 'dart:io'; | 13 import 'dart:io'; |
14 import 'dart:json' as json; | 14 import 'dart:json' as json; |
15 import 'package:pathos/path.dart' as path; | 15 import 'package:pathos/path.dart' as path; |
16 import 'package:args/args.dart'; | 16 import 'package:args/args.dart'; |
17 import 'package:intl/src/intl_message.dart'; | |
18 import 'package:serialization/serialization.dart'; | |
19 | |
20 get s => new Serialization() | |
21 ..addRuleFor(new VariableSubstitution(0, null), | |
Emily Fortuna
2013/07/03 17:52:33
can we have more descriptive names than s and w he
Alan Knight
2013/07/03 18:41:07
Done.
| |
22 constructorFields: ["index", "parent"]) | |
23 ..addRuleFor(new LiteralString("a", null), | |
24 constructorFields: ["string", "parent"]) | |
25 ..addRuleFor(new CompositeMessage([], null), constructor: "parent", | |
26 constructorFields: ["parent"]); | |
27 var format = const SimpleFlatFormat(); | |
28 get w => s.newWriter(format); | |
17 | 29 |
18 /** A list of the French translations that we will produce. */ | 30 /** A list of the French translations that we will produce. */ |
19 var french = { | 31 var french = { |
20 "types" : r"$a, $b, $c", | 32 "types" : r"$a, $b, $c", |
21 "multiLine" : "Cette message prend plusiers lignes.", | 33 "multiLine" : "Cette message prend plusiers lignes.", |
22 "message2" : r"Un autre message avec un seul paramètre $x", | 34 "message2" : r"Un autre message avec un seul paramètre $x", |
23 "alwaysTranslated" : "Cette chaîne est toujours traduit", | 35 "alwaysTranslated" : "Cette chaîne est toujours traduit", |
24 "message1" : "Il s'agit d'un message", | 36 "message1" : "Il s'agit d'un message", |
25 "leadingQuotes" : "\"Soi-disant\"", | 37 "leadingQuotes" : "\"Soi-disant\"", |
26 "trickyInterpolation" : r"L'interpolation est délicate " | 38 "trickyInterpolation" : r"L'interpolation est délicate " |
27 r"quand elle se termine une phrase comme ${s}.", | 39 r"quand elle se termine une phrase comme ${s}.", |
28 "message3" : "Caractères qui doivent être échapper, par exemple barres \\ " | 40 "message3" : "Caractères qui doivent être échapper, par exemple barres \\ " |
29 "dollars \${ (les accolades sont ok), et xml/html réservés <& et " | 41 "dollars \${ (les accolades sont ok), et xml/html réservés <& et " |
30 "des citations \" " | 42 "des citations \" " |
31 "avec quelques paramètres ainsi \$a, \$b, et \$c", | 43 "avec quelques paramètres ainsi \$a, \$b, et \$c", |
32 "method" : "Cela vient d'une méthode", | 44 "method" : "Cela vient d'une méthode", |
33 "nonLambda" : "Cette méthode n'est pas un lambda", | 45 "nonLambda" : "Cette méthode n'est pas un lambda", |
34 "staticMessage" : "Cela vient d'une méthode statique", | 46 "staticMessage" : "Cela vient d'une méthode statique", |
35 "notAlwaysTranslated" : "Ce manque certaines traductions", | 47 "notAlwaysTranslated" : "Ce manque certaines traductions", |
36 "thisNameIsNotInTheOriginal" : "Could this lead to something malicious?", | 48 "thisNameIsNotInTheOriginal" : "Could this lead to something malicious?", |
37 "originalNotInBMP" : "Anciens caractères grecs jeux du pendu: 𐅆𐅇.", | 49 "originalNotInBMP" : "Anciens caractères grecs jeux du pendu: 𐅆𐅇.", |
38 "plural" : """Une des choses difficiles est \${Intl.plural(num, | 50 "escapable" : "Escapes: \n\r\f\b\t\v.", |
39 { | 51 "plurals" : w.write(new Plural.from("num", |
40 '0' : 'la forme plurielle', | 52 [ |
41 '1' : 'la forme plurielle', | 53 ["zero", "Est-ce que nulle est pluriel?"], |
42 'other' : 'des formes plurielles'})}""", | 54 ["one", "C'est singulier"], |
43 "namedArgs" : "La chose est, \$thing", | 55 ["other", "C'est pluriel (\$num)."] |
44 "escapable" : "Escapes: \n\r\f\b\t\v." | 56 ], null)), |
57 // TODO(alanknight): These are pretty horrible to write out manually. Provide | |
58 // a better way of reading/writing translations. A real format would be good. | |
59 "whereTheyWent" : w.write(new Gender.from("gender", | |
60 [ | |
61 ["male", [0, " est allé à sa ", 2]], | |
62 ["female", [0, " est allée à sa ", 2]], | |
63 ["other", [0, " est allé à sa ", 2]] | |
64 ], null)), | |
65 // Gratuitously different translation for testing. Ignoring gender of place. | |
66 "nestedMessage" : w.write(new Gender.from("combinedGender", | |
67 [ | |
68 ["other", new Plural.from("number", | |
69 [ | |
70 ["zero", "Personne n'avait allé à la \$place"], | |
71 ["one", "\${names} était allé à la \$place"], | |
72 ["other", "\${names} étaient allés à la \$place"], | |
73 ], null) | |
74 ], | |
75 ["female", new Plural.from("number", | |
76 [ | |
77 ["one", "\$names était allée à la \$place"], | |
78 ["other", "\$names étaient allées à la \$place"], | |
79 ], null) | |
80 ] | |
81 ], null | |
82 )) | |
45 }; | 83 }; |
46 | 84 |
47 /** A list of the German translations that we will produce. */ | 85 /** A list of the German translations that we will produce. */ |
48 var german = { | 86 var german = { |
49 "types" : r"$a, $b, $c", | 87 "types" : r"$a, $b, $c", |
50 "multiLine" : "Dieser String erstreckt sich über mehrere Zeilen erstrecken.", | 88 "multiLine" : "Dieser String erstreckt sich über mehrere Zeilen erstrecken.", |
51 "message2" : r"Eine weitere Meldung mit dem Parameter $x", | 89 "message2" : r"Eine weitere Meldung mit dem Parameter $x", |
52 "alwaysTranslated" : "Diese Zeichenkette wird immer übersetzt", | 90 "alwaysTranslated" : "Diese Zeichenkette wird immer übersetzt", |
53 "message1" : "Dies ist eine Nachricht", | 91 "message1" : "Dies ist eine Nachricht", |
54 "leadingQuotes" : "\"Sogenannt\"", | 92 "leadingQuotes" : "\"Sogenannt\"", |
55 "trickyInterpolation" : | 93 "trickyInterpolation" : |
56 r"Interpolation ist schwierig, wenn es einen Satz wie dieser endet ${s}.", | 94 r"Interpolation ist schwierig, wenn es einen Satz wie dieser endet ${s}.", |
57 "message3" : "Zeichen, die Flucht benötigen, zB Schrägstriche \\ Dollar " | 95 "message3" : "Zeichen, die Flucht benötigen, zB Schrägstriche \\ Dollar " |
58 "\${ (geschweiften Klammern sind ok) und xml reservierte Zeichen <& und " | 96 "\${ (geschweiften Klammern sind ok) und xml reservierte Zeichen <& und " |
59 "Zitate \" Parameter \$a, \$b und \$c", | 97 "Zitate \" Parameter \$a, \$b und \$c", |
60 "method" : "Dies ergibt sich aus einer Methode", | 98 "method" : "Dies ergibt sich aus einer Methode", |
61 "nonLambda" : "Diese Methode ist nicht eine Lambda", | 99 "nonLambda" : "Diese Methode ist nicht eine Lambda", |
62 "staticMessage" : "Dies ergibt sich aus einer statischen Methode", | 100 "staticMessage" : "Dies ergibt sich aus einer statischen Methode", |
63 "originalNotInBMP" : "Antike griechische Galgenmännchen Zeichen: 𐅆𐅇", | 101 "originalNotInBMP" : "Antike griechische Galgenmännchen Zeichen: 𐅆𐅇", |
64 "plurals" : """\${Intl.plural(num, | 102 "escapable" : "Escapes: \n\r\f\b\t\v.", |
65 { | 103 "plurals" : w.write(new Plural.from("num", |
66 '0' : 'Einer der knifflige Dinge ist der Plural', | 104 [ |
67 '1' : 'Einer der knifflige Dinge ist der Plural', | 105 ["zero", "Ist Null Plural?"], |
68 'other' : 'Zu den kniffligen Dinge Pluralformen' | 106 ["one", "Dies ist einmalig"], |
69 })}""", | 107 ["other", "Dies ist Plural (\$num)."] |
70 "namedArgs" : "Die Sache ist, \$thing", | 108 ], null)), |
71 "escapable" : "Escapes: \n\r\f\b\t\v." | 109 // TODO(alanknight): These are pretty horrible to write out manually. Provide |
110 // a better way of reading/writing translations. A real format would be good. | |
111 "whereTheyWent" : w.write(new Gender.from("gender", | |
112 [ | |
113 ["male", [0, " ging zu seinem ", 2]], | |
114 ["female", [0, " ging zu ihrem ", 2]], | |
115 ["other", [0, " ging zu seinem ", 2]] | |
116 ], null)), | |
117 //Note that we're only using the gender of the people. The gender of the | |
118 //place also matters, but we're not dealing with that here. | |
119 "nestedMessage" : w.write(new Gender.from("combinedGender", | |
120 [ | |
121 ["other", new Plural.from("number", | |
122 [ | |
123 ["zero", "Niemand ging zu \$place"], | |
124 ["one", "\${names} ging zum \$place"], | |
125 ["other", "\${names} gingen zum \$place"], | |
126 ], null) | |
127 ], | |
128 ["female", new Plural.from("number", | |
129 [ | |
130 ["one", "\$names ging in dem \$place"], | |
131 ["other", "\$names gingen zum \$place"], | |
132 ], null) | |
133 ] | |
134 ], null | |
135 )) | |
72 }; | 136 }; |
73 | 137 |
74 /** The output directory for translated files. */ | 138 /** The output directory for translated files. */ |
75 String targetDir; | 139 String targetDir; |
76 | 140 |
77 /** | 141 /** |
78 * Generate a translated json version from [originals] in [locale] looking | 142 * Generate a translated json version from [originals] in [locale] looking |
79 * up the translations in [translations]. | 143 * up the translations in [translations]. |
80 */ | 144 */ |
81 void translate(List originals, String locale, Map translations) { | 145 void translate(List originals, String locale, Map translations) { |
82 var translated = {"_locale" : locale}; | 146 var translated = {"_locale" : locale}; |
83 for (var each in originals) { | 147 for (var each in originals) { |
84 var name = each["name"]; | 148 var name = each["name"]; |
85 translated[name] = translations[name]; | 149 translated[name] = translations[name]; |
86 } | 150 } |
87 var file = new File(path.join(targetDir, 'translation_$locale.json')); | 151 var file = new File(path.join(targetDir, 'translation_$locale.json')); |
88 file.writeAsStringSync(json.stringify(translated)); | 152 file.writeAsStringSync(json.stringify(translated)); |
89 } | 153 } |
90 | 154 |
91 main() { | 155 main() { |
92 var args = new Options().arguments; | 156 var args = new Options().arguments; |
93 if (args.length == 0) { | 157 if (args.length == 0) { |
94 print('Usage: generate_hardcoded_translation [--output-dir=<dir>] ' | 158 print('Usage: generate_hardcoded_translation [--output-dir=<dir>] ' |
95 '[originalFile.dart]'); | 159 '[originalFile.json]'); |
96 exit(0); | 160 exit(0); |
97 } | 161 } |
98 var parser = new ArgParser(); | 162 var parser = new ArgParser(); |
99 parser.addOption("output-dir", defaultsTo: '.', | 163 parser.addOption("output-dir", defaultsTo: '.', |
100 callback: (value) => targetDir = value); | 164 callback: (value) => targetDir = value); |
101 parser.parse(args); | 165 parser.parse(args); |
102 | 166 |
103 var fileArgs = args.where((x) => x.contains('.json')); | 167 var fileArgs = args.where((x) => x.contains('.json')); |
104 | 168 |
105 var messages = json.parse(new File(fileArgs.first).readAsStringSync()); | 169 var messages = json.parse(new File(fileArgs.first).readAsStringSync()); |
106 translate(messages, "fr", french); | 170 translate(messages, "fr", french); |
107 translate(messages, "de_DE", german); | 171 translate(messages, "de_DE", german); |
108 } | 172 } |
OLD | NEW |