Unverified Commit fae84f67 authored by Tarekk Mohamed Abdalla's avatar Tarekk Mohamed Abdalla Committed by GitHub

[gen_l10n] Add support for adding placeholders inside select (#92753)

parent 31ee09f6
...@@ -177,6 +177,59 @@ String generateNumberFormattingLogic(Message message) { ...@@ -177,6 +177,59 @@ String generateNumberFormattingLogic(Message message) {
return formatStatements.isEmpty ? '@(none)' : formatStatements.join(); return formatStatements.isEmpty ? '@(none)' : formatStatements.join();
} }
/// To make it easier to parse plurals or select messages, temporarily replace
/// each "{placeholder}" parameter with "#placeholder#" for example.
String _replacePlaceholdersBraces(
String translationForMessage,
Iterable<Placeholder> placeholders,
String replacementBraces,
) {
assert(replacementBraces.length == 2);
String easyMessage = translationForMessage;
for (final Placeholder placeholder in placeholders) {
easyMessage = easyMessage.replaceAll(
'{${placeholder.name}}',
'${replacementBraces[0]}${placeholder.name}${replacementBraces[1]}',
);
}
return easyMessage;
}
/// Replaces message with the interpolated variable name of the given placeholders
/// with the ability to change braces to something other than {...}.
///
/// Examples:
///
/// * Replacing `{userName}`.
/// ```dart
/// final message = 'Hello my name is {userName}';
/// final transformed = _replacePlaceholdersWithVariables(message, placeholders);
/// // transformed == 'Hello my name is $userName'
/// ```
/// * Replacing `#choice#`.
/// ```dart
/// final message = 'I would like to have some #choice#';
/// final transformed = _replacePlaceholdersWithVariables(message, placeholders, '##');
/// transformed == 'I would like to have some $choice'
/// ```
String _replacePlaceholdersWithVariables(String message, Iterable<Placeholder> placeholders, [String braces = '{}']) {
assert(braces.length == 2);
String messageWithValues = message;
for (final Placeholder placeholder in placeholders) {
String variable = placeholder.name;
if (placeholder.requiresFormatting) {
variable += 'String';
}
messageWithValues = messageWithValues.replaceAll(
'${braces[0]}${placeholder.name}${braces[1]}',
_needsCurlyBracketStringInterpolation(messageWithValues, placeholder.name)
? '\${$variable}'
: '\$$variable'
);
}
return messageWithValues;
}
String _generatePluralMethod(Message message, String translationForMessage) { String _generatePluralMethod(Message message, String translationForMessage) {
if (message.placeholders.isEmpty) { if (message.placeholders.isEmpty) {
throw L10nException( throw L10nException(
...@@ -186,12 +239,7 @@ String _generatePluralMethod(Message message, String translationForMessage) { ...@@ -186,12 +239,7 @@ String _generatePluralMethod(Message message, String translationForMessage) {
); );
} }
// To make it easier to parse the plurals message, temporarily replace each final String easyMessage = _replacePlaceholdersBraces(translationForMessage, message.placeholders, '##');
// "{placeholder}" parameter with "#placeholder#".
String easyMessage = translationForMessage;
for (final Placeholder placeholder in message.placeholders) {
easyMessage = easyMessage.replaceAll('{${placeholder.name}}', '#${placeholder.name}#');
}
final Placeholder countPlaceholder = message.getCountPlaceholder(); final Placeholder countPlaceholder = message.getCountPlaceholder();
const Map<String, String> pluralIds = <String, String>{ const Map<String, String> pluralIds = <String, String>{
...@@ -208,19 +256,7 @@ String _generatePluralMethod(Message message, String translationForMessage) { ...@@ -208,19 +256,7 @@ String _generatePluralMethod(Message message, String translationForMessage) {
final RegExp expRE = RegExp('($pluralKey)\\s*{([^}]+)}'); final RegExp expRE = RegExp('($pluralKey)\\s*{([^}]+)}');
final RegExpMatch? match = expRE.firstMatch(easyMessage); final RegExpMatch? match = expRE.firstMatch(easyMessage);
if (match != null && match.groupCount == 2) { if (match != null && match.groupCount == 2) {
String argValue = generateString(match.group(2)!); final String argValue = _replacePlaceholdersWithVariables(generateString(match.group(2)!), message.placeholders, '##');
for (final Placeholder placeholder in message.placeholders) {
String variable = placeholder.name;
if (placeholder.requiresFormatting) {
variable += 'String';
}
argValue = argValue.replaceAll(
'#${placeholder.name}#',
_needsCurlyBracketStringInterpolation(argValue, placeholder.name)
? '\${$variable}'
: '\$$variable'
);
}
pluralLogicArgs.add(' ${pluralIds[pluralKey]}: $argValue'); pluralLogicArgs.add(' ${pluralIds[pluralKey]}: $argValue');
} }
} }
...@@ -281,10 +317,11 @@ String _generateSelectMethod(Message message, String translationForMessage) { ...@@ -281,10 +317,11 @@ String _generateSelectMethod(Message message, String translationForMessage) {
); );
} }
final String easyMessage = _replacePlaceholdersBraces(translationForMessage, message.placeholders, '##');
final List<String> cases = <String>[]; final List<String> cases = <String>[];
final RegExpMatch? selectMatch = final RegExpMatch? selectMatch = LocalizationsGenerator._selectRE.firstMatch(easyMessage);
LocalizationsGenerator._selectRE.firstMatch(translationForMessage);
String? choice; String? choice;
if (selectMatch != null && selectMatch.groupCount == 2) { if (selectMatch != null && selectMatch.groupCount == 2) {
choice = selectMatch.group(1); choice = selectMatch.group(1);
...@@ -292,9 +329,10 @@ String _generateSelectMethod(Message message, String translationForMessage) { ...@@ -292,9 +329,10 @@ String _generateSelectMethod(Message message, String translationForMessage) {
final RegExp patternRE = RegExp(r'\s*([\w\d]+)\s*\{(.*?)\}'); final RegExp patternRE = RegExp(r'\s*([\w\d]+)\s*\{(.*?)\}');
for (final RegExpMatch patternMatch in patternRE.allMatches(pattern)) { for (final RegExpMatch patternMatch in patternRE.allMatches(pattern)) {
if (patternMatch.groupCount == 2) { if (patternMatch.groupCount == 2) {
final String value = patternMatch.group(2)! String value = patternMatch.group(2)!
.replaceAll("'", r"\'") .replaceAll("'", r"\'")
.replaceAll('"', r'\"'); .replaceAll('"', r'\"');
value = _replacePlaceholdersWithVariables(value, message.placeholders, '##');
cases.add( cases.add(
" '${patternMatch.group(1)}': '$value'", " '${patternMatch.group(1)}': '$value'",
); );
...@@ -374,21 +412,7 @@ bool _needsCurlyBracketStringInterpolation(String messageString, String placehol ...@@ -374,21 +412,7 @@ bool _needsCurlyBracketStringInterpolation(String messageString, String placehol
String _generateMethod(Message message, String translationForMessage) { String _generateMethod(Message message, String translationForMessage) {
String generateMessage() { String generateMessage() {
String messageValue = generateString(translationForMessage); return _replacePlaceholdersWithVariables(generateString(translationForMessage), message.placeholders);
for (final Placeholder placeholder in message.placeholders) {
String variable = placeholder.name;
if (placeholder.requiresFormatting) {
variable += 'String';
}
messageValue = messageValue.replaceAll(
'{${placeholder.name}}',
_needsCurlyBracketStringInterpolation(messageValue, placeholder.name)
? '\${$variable}'
: '\$$variable'
);
}
return messageValue;
} }
if (message.isPlural) { if (message.isPlural) {
......
...@@ -123,45 +123,47 @@ void main() { ...@@ -123,45 +123,47 @@ void main() {
'#l10n 68 (Cabriolet has "acceleration")\n' '#l10n 68 (Cabriolet has "acceleration")\n'
'#l10n 69 (Oh, she found 1 item!)\n' '#l10n 69 (Oh, she found 1 item!)\n'
'#l10n 70 (Indeed, they like Flutter!)\n' '#l10n 70 (Indeed, they like Flutter!)\n'
'#l10n 71 (--- es ---)\n' '#l10n 71 (Indeed, he likes ice cream!)\n'
'#l10n 72 (ES - Hello world)\n' '#l10n 72 (Indeed, she likes chocolate!)\n'
'#l10n 73 (ES - Hello _NEWLINE_ World)\n' '#l10n 73 (--- es ---)\n'
'#l10n 74 (ES - Hola \$ Mundo)\n' '#l10n 74 (ES - Hello world)\n'
'#l10n 75 (ES - Hello Mundo)\n' '#l10n 75 (ES - Hello _NEWLINE_ World)\n'
'#l10n 76 (ES - Hola Mundo)\n' '#l10n 76 (ES - Hola \$ Mundo)\n'
'#l10n 77 (ES - Hello World on viernes, 1 de enero de 1960)\n' '#l10n 77 (ES - Hello Mundo)\n'
'#l10n 78 (ES - Hello world argument on 1/1/1960 at 0:00)\n' '#l10n 78 (ES - Hola Mundo)\n'
'#l10n 79 (ES - Hello World from 1960 to 2020)\n' '#l10n 79 (ES - Hello World on viernes, 1 de enero de 1960)\n'
'#l10n 80 (ES - Hello for 123)\n' '#l10n 80 (ES - Hello world argument on 1/1/1960 at 0:00)\n'
'#l10n 81 (ES - Hello)\n' '#l10n 81 (ES - Hello World from 1960 to 2020)\n'
'#l10n 82 (ES - Hello World)\n' '#l10n 82 (ES - Hello for 123)\n'
'#l10n 83 (ES - Hello two worlds)\n' '#l10n 83 (ES - Hello)\n'
'#l10n 84 (ES - Hello)\n' '#l10n 84 (ES - Hello World)\n'
'#l10n 85 (ES - Hello nuevo World)\n' '#l10n 85 (ES - Hello two worlds)\n'
'#l10n 86 (ES - Hello two nuevo worlds)\n' '#l10n 86 (ES - Hello)\n'
'#l10n 87 (ES - Hello on viernes, 1 de enero de 1960)\n' '#l10n 87 (ES - Hello nuevo World)\n'
'#l10n 88 (ES - Hello World, on viernes, 1 de enero de 1960)\n' '#l10n 88 (ES - Hello two nuevo worlds)\n'
'#l10n 89 (ES - Hello two worlds, on viernes, 1 de enero de 1960)\n' '#l10n 89 (ES - Hello on viernes, 1 de enero de 1960)\n'
'#l10n 90 (ES - Hello other 0 worlds, with a total of 100 citizens)\n' '#l10n 90 (ES - Hello World, on viernes, 1 de enero de 1960)\n'
'#l10n 91 (ES - Hello World of 101 citizens)\n' '#l10n 91 (ES - Hello two worlds, on viernes, 1 de enero de 1960)\n'
'#l10n 92 (ES - Hello two worlds with 102 total citizens)\n' '#l10n 92 (ES - Hello other 0 worlds, with a total of 100 citizens)\n'
'#l10n 93 (ES - [Hola] -Mundo- #123#)\n' '#l10n 93 (ES - Hello World of 101 citizens)\n'
'#l10n 94 (ES - \$!)\n' '#l10n 94 (ES - Hello two worlds with 102 total citizens)\n'
'#l10n 95 (ES - One \$)\n' '#l10n 95 (ES - [Hola] -Mundo- #123#)\n'
"#l10n 96 (ES - Flutter's amazing!)\n" '#l10n 96 (ES - \$!)\n'
"#l10n 97 (ES - Flutter's amazing, times 2!)\n" '#l10n 97 (ES - One \$)\n'
'#l10n 98 (ES - Flutter is "amazing"!)\n' "#l10n 98 (ES - Flutter's amazing!)\n"
'#l10n 99 (ES - Flutter is "amazing", times 2!)\n' "#l10n 99 (ES - Flutter's amazing, times 2!)\n"
'#l10n 100 (ES - 16 wheel truck)\n' '#l10n 100 (ES - Flutter is "amazing"!)\n'
"#l10n 101 (ES - Sedan's elegance)\n" '#l10n 101 (ES - Flutter is "amazing", times 2!)\n'
'#l10n 102 (ES - Cabriolet has "acceleration")\n' '#l10n 102 (ES - 16 wheel truck)\n'
'#l10n 103 (ES - Oh, she found ES - 1 itemES - !)\n' "#l10n 103 (ES - Sedan's elegance)\n"
'#l10n 104 (ES - Indeed, ES - they like ES - Flutter!)\n' '#l10n 104 (ES - Cabriolet has "acceleration")\n'
'#l10n 105 (--- es_419 ---)\n' '#l10n 105 (ES - Oh, she found ES - 1 itemES - !)\n'
'#l10n 106 (ES 419 - Hello World)\n' '#l10n 106 (ES - Indeed, ES - they like ES - Flutter!)\n'
'#l10n 107 (ES 419 - Hello)\n' '#l10n 107 (--- es_419 ---)\n'
'#l10n 108 (ES 419 - Hello World)\n' '#l10n 108 (ES 419 - Hello World)\n'
'#l10n 109 (ES 419 - Hello two worlds)\n' '#l10n 109 (ES 419 - Hello)\n'
'#l10n 110 (ES 419 - Hello World)\n'
'#l10n 111 (ES 419 - Hello two worlds)\n'
'#l10n END\n' '#l10n END\n'
); );
} }
......
...@@ -227,6 +227,8 @@ class Home extends StatelessWidget { ...@@ -227,6 +227,8 @@ class Home extends StatelessWidget {
"${localizations.doubleQuoteSelect('cabriolet')}", "${localizations.doubleQuoteSelect('cabriolet')}",
"${localizations.pluralInString(1)}", "${localizations.pluralInString(1)}",
"${localizations.selectInString('he')}", "${localizations.selectInString('he')}",
"${localizations.selectWithPlaceholder('male', 'ice cream')}",
"${localizations.selectWithPlaceholder('female', 'chocolate')}",
]); ]);
}, },
), ),
...@@ -655,6 +657,15 @@ void main() { ...@@ -655,6 +657,15 @@ void main() {
"placeholders": { "placeholders": {
"gender": {} "gender": {}
} }
},
"selectWithPlaceholder": "Indeed, {gender, select, male {he likes {preference}} female {she likes {preference}} other {they like {preference}}}!",
"@selectWithPlaceholder": {
"description": "A select message with prefix, suffix strings, and a placeholder.",
"placeholders": {
"gender": {},
"preference": {}
}
} }
} }
'''; ''';
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment