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