Fix handling of literal dollar sign followed by a number in Intl messages
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=121323209
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 0d6af5d..2b54da3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,8 @@
* Add a NumberFormat.simpleCurrency constructor which will attempt to
automatically determine the currency symbol. Very simple implementation but
can be expanded to be per-locale.
+ * Fix a problem where, in a message, a literal dollar sign followed by a number
+ was seen as a valid identifier, resulting in invalid code being generated.
## 0.12.7+1
* Change the signature for args and examples in Intl.plural/gender/select to
diff --git a/lib/src/intl_message.dart b/lib/src/intl_message.dart
index 7ff41f2..ebc83d5 100644
--- a/lib/src/intl_message.dart
+++ b/lib/src/intl_message.dart
@@ -159,11 +159,7 @@
/// code.
String toCode();
- /// Escape the string for use in generated Dart code and
- /// optionally validate that it
- /// doesn't doesn't contain any illegal interpolations. We only allow
- /// simple variables ("$foo", but not "${foo}") and Intl.gender/plural
- /// calls.
+ /// Escape the string for use in generated Dart code.
String escapeAndValidateString(String value) {
const Map<String, String> escapes = const {
r"\": r"\\",
@@ -175,30 +171,13 @@
"\t": r"\t",
"\v": r"\v",
"'": r"\'",
+ r"$" : r"\$"
};
- String _escape(String s) => (escapes[s] == null) ? s : escapes[s];
+ String _escape(String s) => escapes[s] ?? s;
var escaped = value.splitMapJoin("", onNonMatch: _escape);
- return disallowInvalidInterpolations(escaped);
- }
-
- /// Disallow ${} expressions, only allow $variable so as to avoid malicious
- /// code. Disallow any usage of "${". If that makes a false positive
- /// on a translation that legitimately contains "\\${" or other variations,
- /// we'll live with that rather than risk a false negative.
- String disallowInvalidInterpolations(String input) {
- var validInterpolations = new RegExp(r"(\$\w+)|(\${\w+})");
- var validMatches = validInterpolations.allMatches(input);
- String escapeInvalidMatches(Match m) {
- var valid = validMatches.any((x) => x.start == m.start);
- if (valid) {
- return m.group(0);
- } else {
- return "\\${m.group(0)}";
- }
- }
- return input.replaceAllMapped("\$", escapeInvalidMatches);
+ return escaped;
}
/// Expand this string out into a printed form. The function [f] will be
diff --git a/test/message_extraction/make_hardcoded_translation.dart b/test/message_extraction/make_hardcoded_translation.dart
index a813c18..ff9d7d2 100644
--- a/test/message_extraction/make_hardcoded_translation.dart
+++ b/test/message_extraction/make_hardcoded_translation.dart
@@ -71,7 +71,8 @@
"=1{{amount} dollar Canadien}"
"other{{amount} dollars Canadiens}}}"
"other{N'importe quoi}"
- "}}"
+ "}}",
+ "literalDollar": "Cinq sous est US\$0.05"
};
/// A list of the German translations that we will produce.
@@ -130,7 +131,8 @@
"=1{{amount} Kanadischer dollar}"
"other{{amount} Kanadischen dollar}}}"
"other{whatever}"
- "}"
+ "}",
+ "literalDollar": "Fünf Cent US \$ 0.05"
};
/// The output directory for translated files.
diff --git a/test/message_extraction/sample_with_messages.dart b/test/message_extraction/sample_with_messages.dart
index 3d365b9..590daea 100644
--- a/test/message_extraction/sample_with_messages.dart
+++ b/test/message_extraction/sample_with_messages.dart
@@ -143,6 +143,9 @@
meaning: 'rent as a verb',
desc: "The action of renting, as in rent a car");
+literalDollar() => Intl.message("Five cents is US\$0.05",
+ name: "literalDollar", desc: "Literal dollar sign with valid number");
+
printStuff(Intl locale) {
// Use a name that's not a literal so this will get skipped. Then we have
// a name that's not in the original but we include it in the French
@@ -228,6 +231,7 @@
printOut(sameContentsDifferentName());
printOut(rentAsVerb());
printOut(rentToBePaid());
+ printOut(literalDollar());
});
}
diff --git a/test/message_extraction/verify_messages.dart b/test/message_extraction/verify_messages.dart
index 712dc12..f9bacc1 100644
--- a/test/message_extraction/verify_messages.dart
+++ b/test/message_extraction/verify_messages.dart
@@ -73,6 +73,7 @@
verify('Hello World');
verify('rent');
verify('rent');
+ verify('Five cents is US\$0.05');
var fr_lines =
expanded.skip(1).skipWhile((line) => !line.contains('----')).toList();
@@ -137,6 +138,8 @@
verify('Bonjour tout le monde');
verify('louer');
verify('loyer');
+ // Using a non-French format for the currency to test interpolation.
+ verify('Cinq sous est US\$0.05');
var de_lines =
fr_lines.skip(1).skipWhile((line) => !line.contains('----')).toList();
@@ -202,4 +205,5 @@
verify('Hallo Welt');
verify('mieten');
verify('Miete');
+ verify('Fünf Cent US \$ 0.05');
}