Unverified Commit f568d929 authored by Ahmed Ashour's avatar Ahmed Ashour Committed by GitHub

[gen_l10n] Support plurals and selects inside string (#86167)

parent b6419e8e
...@@ -229,15 +229,102 @@ String _generatePluralMethod(Message message, String translationForMessage) { ...@@ -229,15 +229,102 @@ String _generatePluralMethod(Message message, String translationForMessage) {
final String comment = message.description ?? 'No description provided in @${message.resourceId}'; final String comment = message.description ?? 'No description provided in @${message.resourceId}';
return pluralMethodTemplate if (translationForMessage.startsWith('{') && translationForMessage.endsWith('}')) {
return pluralMethodTemplate
.replaceAll('@(comment)', comment)
.replaceAll('@(name)', message.resourceId)
.replaceAll('@(dateFormatting)', generateDateFormattingLogic(message))
.replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message))
.replaceAll('@(parameters)', parameters.join(', '))
.replaceAll('@(count)', countPlaceholder.name)
.replaceAll('@(pluralLogicArgs)', pluralLogicArgs.join(',\n'))
.replaceAll('@(none)\n', '');
}
const String variable = 'pluralString';
final String string = _replaceWithVariable(translationForMessage, variable);
return pluralMethodTemplateInString
.replaceAll('@(comment)', comment) .replaceAll('@(comment)', comment)
.replaceAll('@(name)', message.resourceId) .replaceAll('@(name)', message.resourceId)
.replaceAll('@(parameters)', parameters.join(', '))
.replaceAll('@(dateFormatting)', generateDateFormattingLogic(message)) .replaceAll('@(dateFormatting)', generateDateFormattingLogic(message))
.replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message)) .replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message))
.replaceAll('@(parameters)', parameters.join(', '))
.replaceAll('@(variable)', variable)
.replaceAll('@(count)', countPlaceholder.name) .replaceAll('@(count)', countPlaceholder.name)
.replaceAll('@(pluralLogicArgs)', pluralLogicArgs.join(',\n')) .replaceAll('@(pluralLogicArgs)', pluralLogicArgs.join(',\n'))
.replaceAll('@(none)\n', ''); .replaceAll('@(none)\n', '')
.replaceAll('@(string)', string);
}
String _replaceWithVariable(String translation, String variable) {
String prefix = generateString(translation.substring(0, translation.indexOf('{')));
prefix = prefix.substring(0, prefix.length - 1);
String suffix = generateString(translation.substring(translation.lastIndexOf('}') + 1));
suffix = suffix.substring(1);
// escape variable when the suffix can be combined with the variable
if (suffix.isNotEmpty && !suffix.startsWith(' ')) {
variable = '{$variable}';
}
return prefix + r'$' + variable + suffix;
}
String _generateSelectMethod(Message message, String translationForMessage) {
if (message.placeholders.isEmpty) {
throw L10nException(
'Unable to find placeholders for the select message: ${message.resourceId}.\n'
'Check to see if the select message is in the proper ICU syntax format '
'and ensure that placeholders are properly specified.'
);
}
final List<String> cases = <String>[];
final RegExpMatch? selectMatch =
LocalizationsGenerator._selectRE.firstMatch(translationForMessage);
String? choice;
if (selectMatch != null && selectMatch.groupCount == 2) {
choice = selectMatch.group(1);
final String pattern = selectMatch.group(2)!;
final RegExp patternRE = RegExp(r'\s*([\w\d]+)\s*\{(.*?)\}');
for (final RegExpMatch patternMatch in patternRE.allMatches(pattern)) {
if (patternMatch.groupCount == 2) {
final String value = patternMatch.group(2)!
.replaceAll("'", r"\'")
.replaceAll('"', r'\"');
cases.add(
" '${patternMatch.group(1)}': '$value'",
);
}
}
}
final List<String> parameters = message.placeholders.map((Placeholder placeholder) {
final String placeholderType = placeholder.type ?? 'object';
return '$placeholderType ${placeholder.name}';
}).toList();
final String description = message.description ?? 'No description provided in @${message.resourceId}';
if (translationForMessage.startsWith('{') && translationForMessage.endsWith('}')) {
return selectMethodTemplate
.replaceAll('@(name)', message.resourceId)
.replaceAll('@(parameters)', parameters.join(', '))
.replaceAll('@(choice)', choice!)
.replaceAll('@(cases)', cases.join(',\n').trim())
.replaceAll('@(description)', description);
}
const String variable = 'selectString';
final String string = _replaceWithVariable(translationForMessage, variable);
return selectMethodTemplateInString
.replaceAll('@(name)', message.resourceId)
.replaceAll('@(parameters)', parameters.join(', '))
.replaceAll('@(variable)', variable)
.replaceAll('@(choice)', choice!)
.replaceAll('@(cases)', cases.join(',\n').trim())
.replaceAll('@(description)', description)
.replaceAll('@(string)', string);
} }
bool _needsCurlyBracketStringInterpolation(String messageString, String placeholder) { bool _needsCurlyBracketStringInterpolation(String messageString, String placeholder) {
...@@ -305,6 +392,10 @@ String _generateMethod(Message message, String translationForMessage) { ...@@ -305,6 +392,10 @@ String _generateMethod(Message message, String translationForMessage) {
return _generatePluralMethod(message, translationForMessage); return _generatePluralMethod(message, translationForMessage);
} }
if (message.isSelect) {
return _generateSelectMethod(message, translationForMessage);
}
if (message.placeholdersRequireFormatting) { if (message.placeholdersRequireFormatting) {
return formatMethodTemplate return formatMethodTemplate
.replaceAll('@(name)', message.resourceId) .replaceAll('@(name)', message.resourceId)
...@@ -741,6 +832,8 @@ class LocalizationsGenerator { ...@@ -741,6 +832,8 @@ class LocalizationsGenerator {
@visibleForTesting @visibleForTesting
final bool areResourceAttributesRequired; final bool areResourceAttributesRequired;
static final RegExp _selectRE = RegExp(r'\{([\w\s,]*),\s*select\s*,\s*([\w\d]+\s*\{.*\})+\s*\}');
static bool _isNotReadable(FileStat fileStat) { static bool _isNotReadable(FileStat fileStat) {
final String rawStatString = fileStat.modeString(); final String rawStatString = fileStat.modeString();
// Removes potential prepended permission bits, such as '(suid)' and '(guid)'. // Removes potential prepended permission bits, such as '(suid)' and '(guid)'.
...@@ -1168,7 +1261,11 @@ class LocalizationsGenerator { ...@@ -1168,7 +1261,11 @@ class LocalizationsGenerator {
.replaceAll('\n\n\n', '\n\n'); .replaceAll('\n\n\n', '\n\n');
} }
bool _requiresIntlImport() => _allMessages.any((Message message) => message.isPlural || message.placeholdersRequireFormatting); bool _requiresIntlImport() => _allMessages.any((Message message) {
return message.isPlural
|| message.isSelect
|| message.placeholdersRequireFormatting;
});
void writeOutputFiles(Logger logger, { bool isFromYaml = false }) { void writeOutputFiles(Logger logger, { bool isFromYaml = false }) {
// First, generate the string contents of all necessary files. // First, generate the string contents of all necessary files.
......
...@@ -156,6 +156,46 @@ const String pluralMethodTemplate = ''' ...@@ -156,6 +156,46 @@ const String pluralMethodTemplate = '''
); );
}'''; }''';
const String pluralMethodTemplateInString = '''
@override
String @(name)(@(parameters)) {
@(dateFormatting)
@(numberFormatting)
final String @(variable) = intl.Intl.pluralLogic(
@(count),
locale: localeName,
@(pluralLogicArgs),
);
return @(string);
}''';
const String selectMethodTemplate = '''
@override
String @(name)(@(parameters)) {
return intl.Intl.select(
@(choice),
{
@(cases)
},
desc: '@(description)'
);
}''';
const String selectMethodTemplateInString = '''
@override
String @(name)(@(parameters)) {
final String @(variable) = intl.Intl.select(
@(choice),
{
@(cases)
},
desc: '@(description)'
);
return @(string);
}''';
const String classFileTemplate = ''' const String classFileTemplate = '''
@(header) @(header)
......
...@@ -273,17 +273,21 @@ class Message { ...@@ -273,17 +273,21 @@ class Message {
value = _value(bundle, resourceId), value = _value(bundle, resourceId),
description = _description(bundle, resourceId, isResourceAttributeRequired), description = _description(bundle, resourceId, isResourceAttributeRequired),
placeholders = _placeholders(bundle, resourceId, isResourceAttributeRequired), placeholders = _placeholders(bundle, resourceId, isResourceAttributeRequired),
_pluralMatch = _pluralRE.firstMatch(_value(bundle, resourceId)); _pluralMatch = _pluralRE.firstMatch(_value(bundle, resourceId)),
_selectMatch = _selectRE.firstMatch(_value(bundle, resourceId));
static final RegExp _pluralRE = RegExp(r'\s*\{([\w\s,]*),\s*plural\s*,'); static final RegExp _pluralRE = RegExp(r'\s*\{([\w\s,]*),\s*plural\s*,');
static final RegExp _selectRE = RegExp(r'\s*\{([\w\s,]*),\s*select\s*,');
final String resourceId; final String resourceId;
final String value; final String value;
final String? description; final String? description;
final List<Placeholder> placeholders; final List<Placeholder> placeholders;
final RegExpMatch? _pluralMatch; final RegExpMatch? _pluralMatch;
final RegExpMatch? _selectMatch;
bool get isPlural => _pluralMatch != null && _pluralMatch!.groupCount == 1; bool get isPlural => _pluralMatch != null && _pluralMatch!.groupCount == 1;
bool get isSelect => _selectMatch != null && _selectMatch!.groupCount == 1;
bool get placeholdersRequireFormatting => placeholders.any((Placeholder p) => p.requiresFormatting); bool get placeholdersRequireFormatting => placeholders.any((Placeholder p) => p.requiresFormatting);
...@@ -331,13 +335,21 @@ class Message { ...@@ -331,13 +335,21 @@ class Message {
); );
} }
final RegExpMatch? pluralRegExp = _pluralRE.firstMatch(_value(bundle, resourceId)); if (attributes == null) {
final bool isPlural = pluralRegExp != null && pluralRegExp.groupCount == 1;
if (attributes == null && isPlural) { void _throwEmptyAttributes(final RegExp regExp, final String type) {
throw L10nException( final RegExpMatch? match = regExp.firstMatch(_value(bundle, resourceId));
'Resource attribute "@$resourceId" was not found. Please ' final bool isMatch = match != null && match.groupCount == 1;
'ensure that plural resources have a corresponding @resource.' if (isMatch) {
); throw L10nException(
'Resource attribute "@$resourceId" was not found. Please '
'ensure that $type resources have a corresponding @resource.'
);
}
}
_throwEmptyAttributes(_pluralRE, 'plural');
_throwEmptyAttributes(_selectRE, 'select');
} }
return attributes as Map<String, Object?>?; return attributes as Map<String, Object?>?;
......
...@@ -120,23 +120,17 @@ void main() { ...@@ -120,23 +120,17 @@ void main() {
// Run localizations generator in specified absolute path. // Run localizations generator in specified absolute path.
final String flutterProjectPath = fs.path.join('absolute', 'path', 'to', 'flutter_project'); final String flutterProjectPath = fs.path.join('absolute', 'path', 'to', 'flutter_project');
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, projectPathString: flutterProjectPath,
projectPathString: flutterProjectPath, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
throw TestFailure('Unexpected failure during test setup: ${e.message}');
} on Exception catch (e) {
throw TestFailure('Unexpected failure during test setup: $e');
}
// Output files should be generated in the provided absolute path. // Output files should be generated in the provided absolute path.
expect( expect(
...@@ -245,20 +239,15 @@ void main() { ...@@ -245,20 +239,15 @@ void main() {
testWithoutContext('correctly adds a headerString when it is set', () { testWithoutContext('correctly adds a headerString when it is set', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, headerString: '/// Sample header',
classNameString: defaultClassNameString, );
headerString: '/// Sample header',
);
} on L10nException catch (e) {
fail('Setting a header through a String should not fail: \n${e.message}');
}
expect(generator.header, '/// Sample header'); expect(generator.header, '/// Sample header');
}); });
...@@ -270,20 +259,15 @@ void main() { ...@@ -270,20 +259,15 @@ void main() {
..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString) ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString)
..childFile('header.txt').writeAsStringSync('/// Sample header in a text file'); ..childFile('header.txt').writeAsStringSync('/// Sample header in a text file');
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, headerFile: 'header.txt',
classNameString: defaultClassNameString, );
headerFile: 'header.txt',
);
} on L10nException catch (e) {
fail('Setting a header through a file should not fail: \n${e.message}');
}
expect(generator.header, '/// Sample header in a text file'); expect(generator.header, '/// Sample header in a text file');
}); });
...@@ -295,19 +279,15 @@ void main() { ...@@ -295,19 +279,15 @@ void main() {
.writeAsStringSync(singleMessageArbFileString); .writeAsStringSync(singleMessageArbFileString);
l10nDirectory.childFile('app_localizations_es.arb') l10nDirectory.childFile('app_localizations_es.arb')
.writeAsStringSync(singleEsMessageArbFileString); .writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: 'app_localizations_en.arb',
templateArbFileName: 'app_localizations_en.arb', outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory(syntheticL10nPackagePath); final Directory outputDirectory = fs.directory(syntheticL10nPackagePath);
expect(outputDirectory.childFile('output-localization-file.dart').existsSync(), isTrue); expect(outputDirectory.childFile('output-localization-file.dart').existsSync(), isTrue);
...@@ -346,21 +326,17 @@ void main() { ...@@ -346,21 +326,17 @@ void main() {
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString); ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'), )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final File unimplementedOutputFile = fs.file( final File unimplementedOutputFile = fs.file(
fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'), fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
...@@ -382,22 +358,18 @@ void main() { ...@@ -382,22 +358,18 @@ void main() {
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString); ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'), )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final File unimplementedOutputFile = fs.file( final File unimplementedOutputFile = fs.file(
fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'), fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
...@@ -423,21 +395,17 @@ void main() { ...@@ -423,21 +395,17 @@ void main() {
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString); ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(testLogger);
..writeOutputFiles(testLogger);
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
expect( expect(
testLogger.statusText, testLogger.statusText,
...@@ -460,19 +428,15 @@ void main() { ...@@ -460,19 +428,15 @@ void main() {
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString); ..childFile(esArbFileName).writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(testLogger, isFromYaml: true);
..writeOutputFiles(testLogger, isFromYaml: true);
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
expect( expect(
testLogger.statusText, testLogger.statusText,
...@@ -495,43 +459,35 @@ void main() { ...@@ -495,43 +459,35 @@ void main() {
..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(twoMessageArbFileString)
..childFile(esArbFileName).writeAsStringSync(twoMessageArbFileString); ..childFile(esArbFileName).writeAsStringSync(twoMessageArbFileString);
try {
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(testLogger);
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
expect(testLogger.statusText, '');
},
);
testWithoutContext('untranslated messages file included in generated JSON list of outputs', () {
_standardFlutterDirectoryL10nSetup(fs);
try {
LocalizationsGenerator( LocalizationsGenerator(
fileSystem: fs, fileSystem: fs,
inputPathString: defaultL10nPathString, inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName, templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString, outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString, classNameString: defaultClassNameString,
inputsAndOutputsListPath: syntheticL10nPackagePath,
untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
) )
..loadResources() ..loadResources()
..writeOutputFiles(BufferLogger.test()); ..writeOutputFiles(testLogger);
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}'); expect(testLogger.statusText, '');
} },
);
testWithoutContext('untranslated messages file included in generated JSON list of outputs', () {
_standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
inputsAndOutputsListPath: syntheticL10nPackagePath,
untranslatedMessagesFile: fs.path.join('lib', 'l10n', 'unimplemented_message_translations.json'),
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
final File inputsAndOutputsList = fs.file( final File inputsAndOutputsList = fs.file(
fs.path.join(syntheticL10nPackagePath, 'gen_l10n_inputs_and_outputs.json'), fs.path.join(syntheticL10nPackagePath, 'gen_l10n_inputs_and_outputs.json'),
...@@ -550,21 +506,17 @@ void main() { ...@@ -550,21 +506,17 @@ void main() {
'null while not using the synthetic package option', 'null while not using the synthetic package option',
() { () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, // outputPathString is intentionally not defined
// outputPathString is intentionally not defined templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory('lib').childDirectory('l10n'); final Directory outputDirectory = fs.directory('lib').childDirectory('l10n');
expect(outputDirectory.childFile('output-localization-file.dart').existsSync(), isTrue); expect(outputDirectory.childFile('output-localization-file.dart').existsSync(), isTrue);
...@@ -591,21 +543,17 @@ void main() { ...@@ -591,21 +543,17 @@ void main() {
.childFile(esArbFileName) .childFile(esArbFileName)
.writeAsStringSync(singleEsMessageArbFileString); .writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: fs.path.join('lib', 'l10n', 'output'),
outputPathString: fs.path.join('lib', 'l10n', 'output'), templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output'); final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output');
expect(outputDirectory.existsSync(), isTrue); expect(outputDirectory.existsSync(), isTrue);
...@@ -621,21 +569,17 @@ void main() { ...@@ -621,21 +569,17 @@ void main() {
() { () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: fs.path.join('lib', 'l10n', 'output'),
outputPathString: fs.path.join('lib', 'l10n', 'output'), templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output'); final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output');
expect(outputDirectory.existsSync(), isTrue); expect(outputDirectory.existsSync(), isTrue);
...@@ -651,21 +595,17 @@ void main() { ...@@ -651,21 +595,17 @@ void main() {
() { () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: fs.path.join('lib', 'l10n', 'output'),
outputPathString: fs.path.join('lib', 'l10n', 'output'), templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output'); final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output');
expect(outputDirectory.existsSync(), isTrue); expect(outputDirectory.existsSync(), isTrue);
...@@ -686,22 +626,18 @@ void main() { ...@@ -686,22 +626,18 @@ void main() {
() { () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: fs.path.join('lib', 'l10n', 'output'),
outputPathString: fs.path.join('lib', 'l10n', 'output'), templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useSyntheticPackage: false,
useSyntheticPackage: false, usesNullableGetter: false,
usesNullableGetter: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output'); final Directory outputDirectory = fs.directory('lib').childDirectory('l10n').childDirectory('output');
expect(outputDirectory.existsSync(), isTrue); expect(outputDirectory.existsSync(), isTrue);
...@@ -720,20 +656,16 @@ void main() { ...@@ -720,20 +656,16 @@ void main() {
testWithoutContext('creates list of inputs and outputs when file path is specified', () { testWithoutContext('creates list of inputs and outputs when file path is specified', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, inputsAndOutputsListPath: syntheticL10nPackagePath,
inputsAndOutputsListPath: syntheticL10nPackagePath, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final File inputsAndOutputsList = fs.file( final File inputsAndOutputsList = fs.file(
fs.path.join(syntheticL10nPackagePath, 'gen_l10n_inputs_and_outputs.json'), fs.path.join(syntheticL10nPackagePath, 'gen_l10n_inputs_and_outputs.json'),
...@@ -915,19 +847,15 @@ flutter: ...@@ -915,19 +847,15 @@ flutter:
testWithoutContext('correctly initializes supportedLocales and supportedLanguageCodes properties', () { testWithoutContext('correctly initializes supportedLocales and supportedLanguageCodes properties', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, )
classNameString: defaultClassNameString, ..loadResources();
)..loadResources();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n${e.message}');
}
expect(generator.supportedLocales.contains(LocaleInfo.fromString('en')), true); expect(generator.supportedLocales.contains(LocaleInfo.fromString('en')), true);
expect(generator.supportedLocales.contains(LocaleInfo.fromString('es')), true); expect(generator.supportedLocales.contains(LocaleInfo.fromString('es')), true);
...@@ -944,20 +872,15 @@ flutter: ...@@ -944,20 +872,15 @@ flutter:
l10nDirectory.childFile('app_en.arb') l10nDirectory.childFile('app_en.arb')
.writeAsStringSync(singleMessageArbFileString); .writeAsStringSync(singleMessageArbFileString);
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, )
classNameString: defaultClassNameString, ..loadResources();
);
generator.loadResources();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n${e.message}');
}
expect(generator.supportedLocales.first, LocaleInfo.fromString('en')); expect(generator.supportedLocales.first, LocaleInfo.fromString('en'));
expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es')); expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es'));
...@@ -975,21 +898,16 @@ flutter: ...@@ -975,21 +898,16 @@ flutter:
.writeAsStringSync(singleZhMessageArbFileString); .writeAsStringSync(singleZhMessageArbFileString);
const List<String> preferredSupportedLocale = <String>['zh', 'es']; const List<String> preferredSupportedLocale = <String>['zh', 'es'];
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, preferredSupportedLocales: preferredSupportedLocale,
classNameString: defaultClassNameString, )
preferredSupportedLocales: preferredSupportedLocale, ..loadResources();
);
generator.loadResources();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n${e.message}');
}
expect(generator.supportedLocales.first, LocaleInfo.fromString('zh')); expect(generator.supportedLocales.first, LocaleInfo.fromString('zh'));
expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es')); expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es'));
...@@ -1043,20 +961,15 @@ flutter: ...@@ -1043,20 +961,15 @@ flutter:
l10nDirectory.childFile('app_en.arb') l10nDirectory.childFile('app_en.arb')
.writeAsStringSync(singleMessageArbFileString); .writeAsStringSync(singleMessageArbFileString);
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: defaultTemplateArbFileName, classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, )
classNameString: defaultClassNameString, ..loadResources();
);
generator.loadResources();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n${e.message}');
}
expect(generator.arbPathStrings.first, fs.path.join('lib', 'l10n', 'app_en.arb')); expect(generator.arbPathStrings.first, fs.path.join('lib', 'l10n', 'app_en.arb'));
expect(generator.arbPathStrings.elementAt(1), fs.path.join('lib', 'l10n', 'app_es.arb')); expect(generator.arbPathStrings.elementAt(1), fs.path.join('lib', 'l10n', 'app_es.arb'));
...@@ -1089,20 +1002,15 @@ flutter: ...@@ -1089,20 +1002,15 @@ flutter:
l10nDirectory.childFile('second_file.arb') l10nDirectory.childFile('second_file.arb')
.writeAsStringSync(arbFileWithZhLocale); .writeAsStringSync(arbFileWithZhLocale);
LocalizationsGenerator generator; final LocalizationsGenerator generator = LocalizationsGenerator(
try { fileSystem: fs,
generator = LocalizationsGenerator( inputPathString: defaultL10nPathString,
fileSystem: fs, outputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: 'first_file.arb',
outputPathString: defaultL10nPathString, outputFileString: defaultOutputFileString,
templateArbFileName: 'first_file.arb', classNameString: defaultClassNameString,
outputFileString: defaultOutputFileString, )
classNameString: defaultClassNameString, ..loadResources();
);
generator.loadResources();
} on L10nException catch (e) {
fail('Setting language and locales should not fail: \n${e.message}');
}
expect(generator.supportedLocales.contains(LocaleInfo.fromString('en')), true); expect(generator.supportedLocales.contains(LocaleInfo.fromString('en')), true);
expect(generator.supportedLocales.contains(LocaleInfo.fromString('zh')), true); expect(generator.supportedLocales.contains(LocaleInfo.fromString('zh')), true);
...@@ -1241,20 +1149,16 @@ flutter: ...@@ -1241,20 +1149,16 @@ flutter:
testWithoutContext('message without placeholders - should generate code comment with description and template message translation', () { testWithoutContext('message without placeholders - should generate code comment with description and template message translation', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
final BufferLogger testLogger = BufferLogger.test(); final BufferLogger testLogger = BufferLogger.test();
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(testLogger);
..writeOutputFiles(testLogger);
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final File baseLocalizationsFile = fs.file( final File baseLocalizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart') fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart')
...@@ -1286,20 +1190,16 @@ flutter: ...@@ -1286,20 +1190,16 @@ flutter:
final BufferLogger testLogger = BufferLogger.test(); final BufferLogger testLogger = BufferLogger.test();
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(testLogger);
..writeOutputFiles(testLogger);
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final File baseLocalizationsFile = fs.file( final File baseLocalizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart') fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart')
...@@ -1339,22 +1239,16 @@ flutter: ...@@ -1339,22 +1239,16 @@ flutter:
}'''); }''');
final BufferLogger testLogger = BufferLogger.test(); final BufferLogger testLogger = BufferLogger.test();
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(testLogger);
..writeOutputFiles(testLogger);
} on Exception catch (e) {
final L10nException exception = e as L10nException;
print(exception.message);
fail('Generating output files should not fail: $e');
}
final File baseLocalizationsFile = fs.file( final File baseLocalizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart') fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart')
...@@ -1379,20 +1273,16 @@ flutter: ...@@ -1379,20 +1273,16 @@ flutter:
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_en_CA.arb').writeAsStringSync(singleEnCaMessageArbFileString); ..childFile('app_en_CA.arb').writeAsStringSync(singleEnCaMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
expect(fs.isFileSync(fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en.dart')), true); expect(fs.isFileSync(fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en.dart')), true);
expect(fs.isFileSync(fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en_US.dart')), false); expect(fs.isFileSync(fs.path.join(syntheticL10nPackagePath, 'output-localization-file_en_US.dart')), false);
...@@ -1411,21 +1301,17 @@ flutter: ...@@ -1411,21 +1301,17 @@ flutter:
..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString); ..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString);
const List<String> preferredSupportedLocale = <String>['zh']; const List<String> preferredSupportedLocale = <String>['zh'];
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, preferredSupportedLocales: preferredSupportedLocale,
preferredSupportedLocales: preferredSupportedLocale, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, defaultOutputFileString), fs.path.join(syntheticL10nPackagePath, defaultOutputFileString),
...@@ -1442,20 +1328,16 @@ import 'output-localization-file_zh.dart'; ...@@ -1442,20 +1328,16 @@ import 'output-localization-file_zh.dart';
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true) fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString); ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useDeferredLoading: true,
useDeferredLoading: true, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, defaultOutputFileString), fs.path.join(syntheticL10nPackagePath, defaultOutputFileString),
...@@ -1641,7 +1523,151 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1641,7 +1523,151 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName) l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(singleDateMessageArbFileString); .writeAsStringSync(singleDateMessageArbFileString);
expect(
() {
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
},
throwsA(isA<L10nException>().having(
(L10nException e) => e.message,
'message',
allOf(
contains('asdf'),
contains('progress'),
contains('does not have a corresponding NumberFormat'),
),
)),
);
});
});
group('plural messages', () {
testWithoutContext('should throw attempting to generate a plural message without placeholders', () {
const String pluralMessageWithoutPlaceholdersAttribute = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
"@helloWorlds": {
"description": "Improperly formatted since it has no placeholder attribute."
}
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithoutPlaceholdersAttribute);
expect(
() {
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
},
throwsA(isA<L10nException>().having(
(L10nException e) => e.message,
'message',
contains('Check to see if the plural message is in the proper ICU syntax format'),
)),
);
});
testWithoutContext('should throw attempting to generate a plural message with an empty placeholders map', () {
const String pluralMessageWithEmptyPlaceholdersMap = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
"@helloWorlds": {
"description": "Improperly formatted since it has no placeholder attribute.",
"placeholders": {}
}
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithEmptyPlaceholdersMap);
expect(
() {
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
},
throwsA(isA<L10nException>().having(
(L10nException e) => e.message,
'message',
contains('Check to see if the plural message is in the proper ICU syntax format'),
)),
);
});
testWithoutContext('should throw attempting to generate a plural message with no resource attributes', () {
const String pluralMessageWithoutResourceAttributes = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}"
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithoutResourceAttributes);
expect(
() {
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
},
throwsA(isA<L10nException>().having(
(L10nException e) => e.message,
'message',
contains('Resource attribute "@helloWorlds" was not found'),
)),
);
});
testWithoutContext('should throw attempting to generate a plural message with incorrect format for placeholders', () {
const String pluralMessageWithIncorrectPlaceholderFormat = '''
{
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}",
"@helloWorlds": {
"placeholders": "Incorrectly a string, should be a map."
}
}''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithIncorrectPlaceholderFormat);
expect( expect(
() { () {
...@@ -1660,21 +1686,20 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1660,21 +1686,20 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
(L10nException e) => e.message, (L10nException e) => e.message,
'message', 'message',
allOf( allOf(
contains('asdf'), contains('is not properly formatted'),
contains('progress'), contains('Ensure that it is a map with string valued keys'),
contains('does not have a corresponding NumberFormat'),
), ),
)), )),
); );
}); });
}); });
group('plural messages', () { group('select messages', () {
testWithoutContext('should throw attempting to generate a plural message without placeholders', () { testWithoutContext('should throw attempting to generate a select message without placeholders', () {
const String pluralMessageWithoutPlaceholdersAttribute = ''' const String selectMessageWithoutPlaceholdersAttribute = '''
{ {
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}", "genderSelect": "{gender, select, female {She} male {He} other {they} }",
"@helloWorlds": { "@genderSelect": {
"description": "Improperly formatted since it has no placeholder attribute." "description": "Improperly formatted since it has no placeholder attribute."
} }
}'''; }''';
...@@ -1682,7 +1707,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1682,7 +1707,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName) l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithoutPlaceholdersAttribute); .writeAsStringSync(selectMessageWithoutPlaceholdersAttribute);
expect( expect(
() { () {
...@@ -1700,16 +1725,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1700,16 +1725,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
throwsA(isA<L10nException>().having( throwsA(isA<L10nException>().having(
(L10nException e) => e.message, (L10nException e) => e.message,
'message', 'message',
contains('Check to see if the plural message is in the proper ICU syntax format'), contains('Check to see if the select message is in the proper ICU syntax format'),
)), )),
); );
}); });
testWithoutContext('should throw attempting to generate a plural message with an empty placeholders map', () { testWithoutContext('should throw attempting to generate a select message with an empty placeholders map', () {
const String pluralMessageWithEmptyPlaceholdersMap = ''' const String selectMessageWithEmptyPlaceholdersMap = '''
{ {
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}", "genderSelect": "{gender, select, female {She} male {He} other {they} }",
"@helloWorlds": { "@genderSelect": {
"description": "Improperly formatted since it has no placeholder attribute.", "description": "Improperly formatted since it has no placeholder attribute.",
"placeholders": {} "placeholders": {}
} }
...@@ -1718,7 +1743,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1718,7 +1743,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName) l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithEmptyPlaceholdersMap); .writeAsStringSync(selectMessageWithEmptyPlaceholdersMap);
expect( expect(
() { () {
...@@ -1736,21 +1761,21 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1736,21 +1761,21 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
throwsA(isA<L10nException>().having( throwsA(isA<L10nException>().having(
(L10nException e) => e.message, (L10nException e) => e.message,
'message', 'message',
contains('Check to see if the plural message is in the proper ICU syntax format'), contains('Check to see if the select message is in the proper ICU syntax format'),
)), )),
); );
}); });
testWithoutContext('should throw attempting to generate a plural message with no resource attributes', () { testWithoutContext('should throw attempting to generate a select message with no resource attributes', () {
const String pluralMessageWithoutResourceAttributes = ''' const String selectMessageWithoutResourceAttributes = '''
{ {
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}" "genderSelect": "{gender, select, female {She} male {He} other {they} }"
}'''; }''';
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName) l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithoutResourceAttributes); .writeAsStringSync(selectMessageWithoutResourceAttributes);
expect( expect(
() { () {
...@@ -1768,16 +1793,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1768,16 +1793,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
throwsA(isA<L10nException>().having( throwsA(isA<L10nException>().having(
(L10nException e) => e.message, (L10nException e) => e.message,
'message', 'message',
contains('Resource attribute "@helloWorlds" was not found'), contains('Resource attribute "@genderSelect" was not found'),
)), )),
); );
}); });
testWithoutContext('should throw attempting to generate a plural message with incorrect format for placeholders', () { testWithoutContext('should throw attempting to generate a select message with incorrect format for placeholders', () {
const String pluralMessageWithIncorrectPlaceholderFormat = ''' const String selectMessageWithIncorrectPlaceholderFormat = '''
{ {
"helloWorlds": "{count,plural, =0{Hello}=1{Hello World}=2{Hello two worlds}few{Hello {count} worlds}many{Hello all {count} worlds}other{Hello other {count} worlds}}", "genderSelect": "{gender, select, female {She} male {He} other {they} }",
"@helloWorlds": { "@genderSelect": {
"placeholders": "Incorrectly a string, should be a map." "placeholders": "Incorrectly a string, should be a map."
} }
}'''; }''';
...@@ -1785,7 +1810,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1785,7 +1810,7 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n') final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
..createSync(recursive: true); ..createSync(recursive: true);
l10nDirectory.childFile(defaultTemplateArbFileName) l10nDirectory.childFile(defaultTemplateArbFileName)
.writeAsStringSync(pluralMessageWithIncorrectPlaceholderFormat); .writeAsStringSync(selectMessageWithIncorrectPlaceholderFormat);
expect( expect(
() { () {
...@@ -1817,20 +1842,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1817,20 +1842,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString); ..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'),
...@@ -1861,20 +1882,56 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1861,20 +1882,56 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(pluralMessageArb) ..childFile(defaultTemplateArbFileName).writeAsStringSync(pluralMessageArb)
..childFile('app_es.arb').writeAsStringSync(pluralMessageEsArb); ..childFile('app_es.arb').writeAsStringSync(pluralMessageEsArb);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) { final String localizationsFile = fs.file(
fail('Generating output files should not fail: $e'); fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'),
} ).readAsStringSync();
expect(localizationsFile, contains(intlImportDartCode));
});
testWithoutContext('intl package import should be kept in subclass files when select is included', () {
const String selectMessageArb = '''
{
"genderSelect": "{gender, select, female {She} male {He} other {they} }",
"@genderSelect": {
"description": "A select message",
"placeholders": {
"gender": {}
}
}
}
''';
const String selectMessageEsArb = '''
{
"genderSelect": "{gender, select, female {ES - She} male {ES - He} other {ES - they} }"
}
''';
fs.currentDirectory.childDirectory('lib').childDirectory('l10n')..createSync(recursive: true)
..childFile(defaultTemplateArbFileName).writeAsStringSync(selectMessageArb)
..childFile('app_es.arb').writeAsStringSync(selectMessageEsArb);
LocalizationsGenerator(
fileSystem: fs,
inputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString,
templateArbFileName: defaultTemplateArbFileName,
outputFileString: defaultOutputFileString,
classNameString: defaultClassNameString,
)
..loadResources()
..writeOutputFiles(BufferLogger.test());
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'),
...@@ -1885,21 +1942,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1885,21 +1942,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
testWithoutContext('check indentation on generated files', () { testWithoutContext('check indentation on generated files', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useDeferredLoading: false,
useDeferredLoading: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'),
...@@ -1923,21 +1976,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1923,21 +1976,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString); ..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useDeferredLoading: true,
useDeferredLoading: true, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'),
...@@ -1950,21 +1999,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -1950,21 +1999,17 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString) ..childFile(defaultTemplateArbFileName).writeAsStringSync(singleMessageArbFileString)
..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString); ..childFile('app_es.arb').writeAsStringSync(singleEsMessageArbFileString);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, useDeferredLoading: false,
useDeferredLoading: false, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file.dart'),
...@@ -2079,23 +2124,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -2079,23 +2124,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(enArbCheckList) ..childFile(defaultTemplateArbFileName).writeAsStringSync(enArbCheckList)
..childFile('app_es.arb').writeAsStringSync(esArbCheckList); ..childFile('app_es.arb').writeAsStringSync(esArbCheckList);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
if (e is L10nException) {
print(e.message);
}
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'),
...@@ -2145,23 +2183,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -2145,23 +2183,16 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..childFile(defaultTemplateArbFileName).writeAsStringSync(enArbCheckList) ..childFile(defaultTemplateArbFileName).writeAsStringSync(enArbCheckList)
..childFile('app_es.arb').writeAsStringSync(esArbCheckList); ..childFile('app_es.arb').writeAsStringSync(esArbCheckList);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, outputPathString: defaultL10nPathString,
outputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on Exception catch (e) {
if (e is L10nException) {
print(e.message);
}
fail('Generating output files should not fail: $e');
}
final String localizationsFile = fs.file( final String localizationsFile = fs.file(
fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'), fs.path.join(syntheticL10nPackagePath, 'output-localization-file_es.dart'),
...@@ -2357,19 +2388,15 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -2357,19 +2388,15 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
testWithoutContext('should generate a valid pubspec.yaml file when using synthetic package if it does not already exist', () { testWithoutContext('should generate a valid pubspec.yaml file when using synthetic package if it does not already exist', () {
_standardFlutterDirectoryL10nSetup(fs); _standardFlutterDirectoryL10nSetup(fs);
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
final Directory outputDirectory = fs.directory(syntheticPackagePath); final Directory outputDirectory = fs.directory(syntheticPackagePath);
final File pubspecFile = outputDirectory.childFile('pubspec.yaml'); final File pubspecFile = outputDirectory.childFile('pubspec.yaml');
...@@ -2391,19 +2418,15 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e ...@@ -2391,19 +2418,15 @@ import 'output-localization-file_en.dart' deferred as output-localization-file_e
..createSync(recursive: true) ..createSync(recursive: true)
..writeAsStringSync('abcd'); ..writeAsStringSync('abcd');
try { LocalizationsGenerator(
LocalizationsGenerator( fileSystem: fs,
fileSystem: fs, inputPathString: defaultL10nPathString,
inputPathString: defaultL10nPathString, templateArbFileName: defaultTemplateArbFileName,
templateArbFileName: defaultTemplateArbFileName, outputFileString: defaultOutputFileString,
outputFileString: defaultOutputFileString, classNameString: defaultClassNameString,
classNameString: defaultClassNameString, )
) ..loadResources()
..loadResources() ..writeOutputFiles(BufferLogger.test());
..writeOutputFiles(BufferLogger.test());
} on L10nException catch (e) {
fail('Generating output should not fail: \n${e.message}');
}
// The original pubspec file should not be overwritten. // The original pubspec file should not be overwritten.
expect(pubspecFile.readAsStringSync(), 'abcd'); expect(pubspecFile.readAsStringSync(), 'abcd');
......
...@@ -118,40 +118,50 @@ void main() { ...@@ -118,40 +118,50 @@ void main() {
"#l10n 63 (Flutter's amazing, times 2!)\n" "#l10n 63 (Flutter's amazing, times 2!)\n"
'#l10n 64 (Flutter is "amazing"!)\n' '#l10n 64 (Flutter is "amazing"!)\n'
'#l10n 65 (Flutter is "amazing", times 2!)\n' '#l10n 65 (Flutter is "amazing", times 2!)\n'
'#l10n 66 (--- es ---)\n' '#l10n 66 (16 wheel truck)\n'
'#l10n 67 (ES - Hello world)\n' "#l10n 67 (Sedan's elegance)\n"
'#l10n 68 (ES - Hello _NEWLINE_ World)\n' '#l10n 68 (Cabriolet has "acceleration")\n'
'#l10n 69 (ES - Hola \$ Mundo)\n' '#l10n 69 (Oh, she found 1 item!)\n'
'#l10n 70 (ES - Hello Mundo)\n' '#l10n 70 (Indeed, they like Flutter!)\n'
'#l10n 71 (ES - Hola Mundo)\n' '#l10n 71 (--- es ---)\n'
'#l10n 72 (ES - Hello World on viernes, 1 de enero de 1960)\n' '#l10n 72 (ES - Hello world)\n'
'#l10n 73 (ES - Hello world argument on 1/1/1960 at 0:00)\n' '#l10n 73 (ES - Hello _NEWLINE_ World)\n'
'#l10n 74 (ES - Hello World from 1960 to 2020)\n' '#l10n 74 (ES - Hola \$ Mundo)\n'
'#l10n 75 (ES - Hello for 123)\n' '#l10n 75 (ES - Hello Mundo)\n'
'#l10n 76 (ES - Hello)\n' '#l10n 76 (ES - Hola Mundo)\n'
'#l10n 77 (ES - Hello World)\n' '#l10n 77 (ES - Hello World on viernes, 1 de enero de 1960)\n'
'#l10n 78 (ES - Hello two worlds)\n' '#l10n 78 (ES - Hello world argument on 1/1/1960 at 0:00)\n'
'#l10n 79 (ES - Hello)\n' '#l10n 79 (ES - Hello World from 1960 to 2020)\n'
'#l10n 80 (ES - Hello nuevo World)\n' '#l10n 80 (ES - Hello for 123)\n'
'#l10n 81 (ES - Hello two nuevo worlds)\n' '#l10n 81 (ES - Hello)\n'
'#l10n 82 (ES - Hello on viernes, 1 de enero de 1960)\n' '#l10n 82 (ES - Hello World)\n'
'#l10n 83 (ES - Hello World, on viernes, 1 de enero de 1960)\n' '#l10n 83 (ES - Hello two worlds)\n'
'#l10n 84 (ES - Hello two worlds, on viernes, 1 de enero de 1960)\n' '#l10n 84 (ES - Hello)\n'
'#l10n 85 (ES - Hello other 0 worlds, with a total of 100 citizens)\n' '#l10n 85 (ES - Hello nuevo World)\n'
'#l10n 86 (ES - Hello World of 101 citizens)\n' '#l10n 86 (ES - Hello two nuevo worlds)\n'
'#l10n 87 (ES - Hello two worlds with 102 total citizens)\n' '#l10n 87 (ES - Hello on viernes, 1 de enero de 1960)\n'
'#l10n 88 (ES - [Hola] -Mundo- #123#)\n' '#l10n 88 (ES - Hello World, on viernes, 1 de enero de 1960)\n'
'#l10n 89 (ES - \$!)\n' '#l10n 89 (ES - Hello two worlds, on viernes, 1 de enero de 1960)\n'
'#l10n 90 (ES - One \$)\n' '#l10n 90 (ES - Hello other 0 worlds, with a total of 100 citizens)\n'
"#l10n 91 (ES - Flutter's amazing!)\n" '#l10n 91 (ES - Hello World of 101 citizens)\n'
"#l10n 92 (ES - Flutter's amazing, times 2!)\n" '#l10n 92 (ES - Hello two worlds with 102 total citizens)\n'
'#l10n 93 (ES - Flutter is "amazing"!)\n' '#l10n 93 (ES - [Hola] -Mundo- #123#)\n'
'#l10n 94 (ES - Flutter is "amazing", times 2!)\n' '#l10n 94 (ES - \$!)\n'
'#l10n 95 (--- es_419 ---)\n' '#l10n 95 (ES - One \$)\n'
'#l10n 96 (ES 419 - Hello World)\n' "#l10n 96 (ES - Flutter's amazing!)\n"
'#l10n 97 (ES 419 - Hello)\n' "#l10n 97 (ES - Flutter's amazing, times 2!)\n"
'#l10n 98 (ES 419 - Hello World)\n' '#l10n 98 (ES - Flutter is "amazing"!)\n'
'#l10n 99 (ES 419 - Hello two worlds)\n' '#l10n 99 (ES - Flutter is "amazing", times 2!)\n'
'#l10n 100 (ES - 16 wheel truck)\n'
"#l10n 101 (ES - Sedan's elegance)\n"
'#l10n 102 (ES - Cabriolet has "acceleration")\n'
'#l10n 103 (ES - Oh, she found ES - 1 itemES - !)\n'
'#l10n 104 (ES - Indeed, ES - they like ES - Flutter!)\n'
'#l10n 105 (--- es_419 ---)\n'
'#l10n 106 (ES 419 - Hello World)\n'
'#l10n 107 (ES 419 - Hello)\n'
'#l10n 108 (ES 419 - Hello World)\n'
'#l10n 109 (ES 419 - Hello two worlds)\n'
'#l10n END\n' '#l10n END\n'
); );
} }
......
...@@ -225,6 +225,11 @@ class Home extends StatelessWidget { ...@@ -225,6 +225,11 @@ class Home extends StatelessWidget {
'${localizations.singleQuotePlural(2)}', '${localizations.singleQuotePlural(2)}',
'${localizations.doubleQuote}', '${localizations.doubleQuote}',
'${localizations.doubleQuotePlural(2)}', '${localizations.doubleQuotePlural(2)}',
"${localizations.vehicleSelect('truck')}",
"${localizations.singleQuoteSelect('sedan')}",
"${localizations.doubleQuoteSelect('cabriolet')}",
"${localizations.pluralInString(1)}",
"${localizations.selectInString('he')}",
]); ]);
}, },
), ),
...@@ -266,6 +271,11 @@ class Home extends StatelessWidget { ...@@ -266,6 +271,11 @@ class Home extends StatelessWidget {
'${localizations.singleQuotePlural(2)}', '${localizations.singleQuotePlural(2)}',
'${localizations.doubleQuote}', '${localizations.doubleQuote}',
'${localizations.doubleQuotePlural(2)}', '${localizations.doubleQuotePlural(2)}',
"${localizations.vehicleSelect('truck')}",
"${localizations.singleQuoteSelect('sedan')}",
"${localizations.doubleQuoteSelect('cabriolet')}",
"${localizations.pluralInString(1)}",
"${localizations.selectInString('he')}",
]); ]);
}, },
), ),
...@@ -608,6 +618,46 @@ void main() { ...@@ -608,6 +618,46 @@ void main() {
"placeholders": { "placeholders": {
"count": {} "count": {}
} }
},
"vehicleSelect": "{vehicleType, select, sedan{Sedan} cabriolet{Solid roof cabriolet} truck{16 wheel truck} other{Other}}",
"@vehicleSelect": {
"description": "A select message.",
"placeholders": {
"vehicleType": {}
}
},
"singleQuoteSelect": "{vehicleType, select, sedan{Sedan's elegance} cabriolet{Cabriolet' acceleration} truck{truck's heavy duty} other{Other's mirrors!}}",
"@singleQuoteSelect": {
"description": "A select message with a single quote.",
"placeholders": {
"vehicleType": {}
}
},
"doubleQuoteSelect": "{vehicleType, select, sedan{Sedan has \"elegance\"} cabriolet{Cabriolet has \"acceleration\"} truck{truck is \"heavy duty\"} other{Other have \"mirrors\"!}}",
"@doubleQuoteSelect": {
"description": "A select message with double quote.",
"placeholders": {
"vehicleType": {}
}
},
"pluralInString": "Oh, she found {count, plural, =1 {1 item} other {all {count} items} }!",
"@pluralInString": {
"description": "A plural message with prefix and suffix strings.",
"placeholders": {
"count": {}
}
},
"selectInString": "Indeed, {gender, select, male {he likes} female {she likes} other {they like} } Flutter!",
"@selectInString": {
"description": "A select message with prefix and suffix strings.",
"placeholders": {
"gender": {}
}
} }
} }
'''; ''';
...@@ -646,13 +696,18 @@ void main() { ...@@ -646,13 +696,18 @@ void main() {
"helloWorldsOn": "{count,plural, =0{ES - Hello on {date}} =1{ES - Hello World, on {date}} =2{ES - Hello two worlds, on {date}} other{ES - Hello other {count} worlds, on {date}}}", "helloWorldsOn": "{count,plural, =0{ES - Hello on {date}} =1{ES - Hello World, on {date}} =2{ES - Hello two worlds, on {date}} other{ES - Hello other {count} worlds, on {date}}}",
"helloWorldPopulation": "{ES - count,plural, =1{ES - Hello World of {population} citizens} =2{ES - Hello two worlds with {population} total citizens} many{ES - Hello all {count} worlds, with a total of {population} citizens} other{ES - Hello other {count} worlds, with a total of {population} citizens}}", "helloWorldPopulation": "{ES - count,plural, =1{ES - Hello World of {population} citizens} =2{ES - Hello two worlds with {population} total citizens} many{ES - Hello all {count} worlds, with a total of {population} citizens} other{ES - Hello other {count} worlds, with a total of {population} citizens}}",
"helloWorldInterpolation": "ES - [{hello}] #{world}#", "helloWorldInterpolation": "ES - [{hello}] #{world}#",
"helloWorldsInterpolation": "ES - {count,plural, other {ES - [{hello}] -{world}- #{count}#}}", "helloWorldsInterpolation": "{count,plural, other {ES - [{hello}] -{world}- #{count}#}}",
"dollarSign": "ES - $!", "dollarSign": "ES - $!",
"dollarSignPlural": "{count,plural, =1{ES - One $} other{ES - Many $}}", "dollarSignPlural": "{count,plural, =1{ES - One $} other{ES - Many $}}",
"singleQuote": "ES - Flutter's amazing!", "singleQuote": "ES - Flutter's amazing!",
"singleQuotePlural": "{count,plural, =1{ES - Flutter's amazing, times 1!} other{ES - Flutter's amazing, times {count}!}}", "singleQuotePlural": "{count,plural, =1{ES - Flutter's amazing, times 1!} other{ES - Flutter's amazing, times {count}!}}",
"doubleQuote": "ES - Flutter is \"amazing\"!", "doubleQuote": "ES - Flutter is \"amazing\"!",
"doubleQuotePlural": "{count,plural, =1{ES - Flutter is \"amazing\", times 1!} other{ES - Flutter is \"amazing\", times {count}!}}" "doubleQuotePlural": "{count,plural, =1{ES - Flutter is \"amazing\", times 1!} other{ES - Flutter is \"amazing\", times {count}!}}",
"vehicleSelect": "{vehicleType, select, sedan{ES - Sedan} cabriolet{ES - Solid roof cabriolet} truck{ES - 16 wheel truck} other{ES - Other}}",
"singleQuoteSelect": "{vehicleType, select, sedan{ES - Sedan's elegance} cabriolet{ES - Cabriolet' acceleration} truck{ES - truck's heavy duty} other{ES - Other's mirrors!}}",
"doubleQuoteSelect": "{vehicleType, select, sedan{ES - Sedan has \"elegance\"} cabriolet{ES - Cabriolet has \"acceleration\"} truck{ES - truck is \"heavy duty\"} other{ES - Other have \"mirrors\"!}}",
"pluralInString": "ES - Oh, she found {count, plural, =1 {ES - 1 item} other {ES - all {count} items} }ES - !",
"selectInString": "ES - Indeed, {gender, select, male {ES - he likes} female {ES - she likes} other {ES - they like} } ES - Flutter!"
} }
'''; ''';
......
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