Gen l10n add named argument option (#138663)
Add an option to use named argument for generated method. Fix #116308
This commit is contained in:
parent
0d6927cb61
commit
e8436970e6
1
AUTHORS
1
AUTHORS
@ -118,4 +118,5 @@ Kim Jiun <kkimj@hanyang.ac.kr>
|
||||
LinXunFeng <linxunfeng@yeah.net>
|
||||
Sabin Neupane <sabin.neupane26@gmail.com>
|
||||
Mahdi Bagheri <1839491@gmail.com>
|
||||
Mok Kah Wai <taboosun1996@gmail.com>
|
||||
Lucas Saudon <lsaudon@gmail.com>
|
||||
|
@ -207,6 +207,10 @@ class GenerateLocalizationsCommand extends FlutterCommand {
|
||||
'and "}" is treated as a string if it does not close any previous "{" '
|
||||
'that is treated as a special character.',
|
||||
);
|
||||
argParser.addFlag(
|
||||
'use-named-parameters',
|
||||
help: 'Whether or not to use named parameters for the generated localization methods.',
|
||||
);
|
||||
}
|
||||
|
||||
final FileSystem _fileSystem;
|
||||
|
@ -73,6 +73,7 @@ Future<LocalizationsGenerator> generateLocalizations({
|
||||
logger: logger,
|
||||
suppressWarnings: options.suppressWarnings,
|
||||
useRelaxedSyntax: options.relaxSyntax,
|
||||
useNamedParameters: options.useNamedParameters,
|
||||
)
|
||||
..loadResources()
|
||||
..writeOutputFiles(isFromYaml: true, useCRLF: useCRLF);
|
||||
@ -122,9 +123,9 @@ String _syntheticL10nPackagePath(FileSystem fileSystem) => fileSystem.path.join(
|
||||
// For example, if placeholders are used for plurals and no type was specified, then the type will
|
||||
// automatically set to 'num'. Similarly, if such placeholders are used for selects, then the type
|
||||
// will be set to 'String'. For such placeholders that are used for both, we should throw an error.
|
||||
List<String> generateMethodParameters(Message message) {
|
||||
List<String> generateMethodParameters(Message message, bool useNamedParameters) {
|
||||
return message.placeholders.values.map((Placeholder placeholder) {
|
||||
return '${placeholder.type} ${placeholder.name}';
|
||||
return '${useNamedParameters ? 'required ' : ''}${placeholder.type} ${placeholder.name}';
|
||||
}).toList();
|
||||
}
|
||||
|
||||
@ -231,7 +232,7 @@ Map<String, String> pluralCases = <String, String>{
|
||||
'other': 'other',
|
||||
};
|
||||
|
||||
String generateBaseClassMethod(Message message, LocaleInfo? templateArbLocale) {
|
||||
String generateBaseClassMethod(Message message, LocaleInfo? templateArbLocale, bool useNamedParameters) {
|
||||
final String comment = message
|
||||
.description
|
||||
?.split('\n')
|
||||
@ -242,11 +243,11 @@ String generateBaseClassMethod(Message message, LocaleInfo? templateArbLocale) {
|
||||
/// **'${generateString(message.value)}'**''';
|
||||
|
||||
if (message.placeholders.isNotEmpty) {
|
||||
return baseClassMethodTemplate
|
||||
return (useNamedParameters ? baseClassMethodWithNamedParameterTemplate : baseClassMethodTemplate)
|
||||
.replaceAll('@(comment)', comment)
|
||||
.replaceAll('@(templateLocaleTranslationComment)', templateLocaleTranslationComment)
|
||||
.replaceAll('@(name)', message.resourceId)
|
||||
.replaceAll('@(parameters)', generateMethodParameters(message).join(', '));
|
||||
.replaceAll('@(parameters)', generateMethodParameters(message, useNamedParameters).join(', '));
|
||||
}
|
||||
return baseClassGetterTemplate
|
||||
.replaceAll('@(comment)', comment)
|
||||
@ -492,6 +493,7 @@ class LocalizationsGenerator {
|
||||
required Logger logger,
|
||||
bool suppressWarnings = false,
|
||||
bool useRelaxedSyntax = false,
|
||||
bool useNamedParameters = false,
|
||||
}) {
|
||||
final Directory? projectDirectory = projectDirFromPath(fileSystem, projectPathString);
|
||||
final Directory inputDirectory = inputDirectoryFromPath(fileSystem, inputPathString, projectDirectory);
|
||||
@ -516,6 +518,7 @@ class LocalizationsGenerator {
|
||||
logger: logger,
|
||||
suppressWarnings: suppressWarnings,
|
||||
useRelaxedSyntax: useRelaxedSyntax,
|
||||
useNamedParameters: useNamedParameters,
|
||||
);
|
||||
}
|
||||
|
||||
@ -541,6 +544,7 @@ class LocalizationsGenerator {
|
||||
this.useEscaping = false,
|
||||
this.suppressWarnings = false,
|
||||
this.useRelaxedSyntax = false,
|
||||
this.useNamedParameters = false,
|
||||
});
|
||||
|
||||
final FileSystem _fs;
|
||||
@ -685,6 +689,14 @@ class LocalizationsGenerator {
|
||||
/// Whether or not to suppress warnings or not.
|
||||
final bool suppressWarnings;
|
||||
|
||||
/// Whether to generate the Dart localization methods with named parameters.
|
||||
///
|
||||
/// If this sets to true, the generated Dart localization methods will be:
|
||||
/// ```
|
||||
/// String helloWorld({required String name});
|
||||
/// ```
|
||||
final bool useNamedParameters;
|
||||
|
||||
static bool _isNotReadable(FileStat fileStat) {
|
||||
final String rawStatString = fileStat.modeString();
|
||||
// Removes potential prepended permission bits, such as '(suid)' and '(guid)'.
|
||||
@ -1124,7 +1136,7 @@ class LocalizationsGenerator {
|
||||
return fileTemplate
|
||||
.replaceAll('@(header)', header.isEmpty ? '' : '$header\n')
|
||||
.replaceAll('@(class)', className)
|
||||
.replaceAll('@(methods)', _allMessages.map((Message message) => generateBaseClassMethod(message, _templateArbLocale)).join('\n'))
|
||||
.replaceAll('@(methods)', _allMessages.map((Message message) => generateBaseClassMethod(message, _templateArbLocale, useNamedParameters)).join('\n'))
|
||||
.replaceAll('@(importFile)', '$directory/$outputFileName')
|
||||
.replaceAll('@(supportedLocales)', supportedLocalesCode.join(',\n '))
|
||||
.replaceAll('@(supportedLanguageCodes)', supportedLanguageCodes.join(', '))
|
||||
@ -1306,9 +1318,9 @@ The plural cases must be one of "=0", "=1", "=2", "zero", "one", "two", "few", "
|
||||
}
|
||||
final String messageString = generateVariables(node, isRoot: true);
|
||||
final String tempVarLines = tempVariables.isEmpty ? '' : '${tempVariables.join('\n')}\n';
|
||||
return methodTemplate
|
||||
return (useNamedParameters ? methodWithNamedParameterTemplate : methodTemplate)
|
||||
.replaceAll('@(name)', message.resourceId)
|
||||
.replaceAll('@(parameters)', generateMethodParameters(message).join(', '))
|
||||
.replaceAll('@(parameters)', generateMethodParameters(message, useNamedParameters).join(', '))
|
||||
.replaceAll('@(dateFormatting)', generateDateFormattingLogic(message))
|
||||
.replaceAll('@(numberFormatting)', generateNumberFormattingLogic(message))
|
||||
.replaceAll('@(tempVars)', tempVarLines)
|
||||
|
@ -142,6 +142,14 @@ const String methodTemplate = '''
|
||||
@(tempVars) return @(message);
|
||||
}''';
|
||||
|
||||
const String methodWithNamedParameterTemplate = '''
|
||||
@override
|
||||
String @(name)({@(parameters)}) {
|
||||
@(dateFormatting)
|
||||
@(numberFormatting)
|
||||
@(tempVars) return @(message);
|
||||
}''';
|
||||
|
||||
const String pluralVariableTemplate = '''
|
||||
String @(varName) = intl.Intl.pluralLogic(
|
||||
@(count),
|
||||
@ -195,6 +203,13 @@ const String baseClassMethodTemplate = '''
|
||||
String @(name)(@(parameters));
|
||||
''';
|
||||
|
||||
const String baseClassMethodWithNamedParameterTemplate = '''
|
||||
@(comment)
|
||||
///
|
||||
@(templateLocaleTranslationComment)
|
||||
String @(name)({@(parameters)});
|
||||
''';
|
||||
|
||||
// DELEGATE CLASS TEMPLATES
|
||||
|
||||
const String delegateClassTemplate = '''
|
||||
|
@ -355,6 +355,7 @@ class LocalizationOptions {
|
||||
bool? useEscaping,
|
||||
bool? suppressWarnings,
|
||||
bool? relaxSyntax,
|
||||
bool? useNamedParameters,
|
||||
}) : templateArbFile = templateArbFile ?? 'app_en.arb',
|
||||
outputLocalizationFile = outputLocalizationFile ?? 'app_localizations.dart',
|
||||
outputClass = outputClass ?? 'AppLocalizations',
|
||||
@ -365,7 +366,8 @@ class LocalizationOptions {
|
||||
format = format ?? false,
|
||||
useEscaping = useEscaping ?? false,
|
||||
suppressWarnings = suppressWarnings ?? false,
|
||||
relaxSyntax = relaxSyntax ?? false;
|
||||
relaxSyntax = relaxSyntax ?? false,
|
||||
useNamedParameters = useNamedParameters ?? false;
|
||||
|
||||
/// The `--arb-dir` argument.
|
||||
///
|
||||
@ -467,6 +469,14 @@ class LocalizationOptions {
|
||||
/// This was added in for backward compatibility and is not recommended
|
||||
/// as it may mask errors.
|
||||
final bool relaxSyntax;
|
||||
|
||||
/// The `use-named-parameters` argument.
|
||||
///
|
||||
/// Whether or not to use named parameters for the generated localization
|
||||
/// methods.
|
||||
///
|
||||
/// Defaults to `false`.
|
||||
final bool useNamedParameters;
|
||||
}
|
||||
|
||||
/// Parse the localizations configuration options from [file].
|
||||
@ -511,6 +521,7 @@ LocalizationOptions parseLocalizationsOptionsFromYAML({
|
||||
useEscaping: _tryReadBool(yamlNode, 'use-escaping', logger),
|
||||
suppressWarnings: _tryReadBool(yamlNode, 'suppress-warnings', logger),
|
||||
relaxSyntax: _tryReadBool(yamlNode, 'relax-syntax', logger),
|
||||
useNamedParameters: _tryReadBool(yamlNode, 'use-named-parameters', logger),
|
||||
);
|
||||
}
|
||||
|
||||
@ -537,6 +548,7 @@ LocalizationOptions parseLocalizationsOptionsFromCommand({
|
||||
format: command.boolArg('format'),
|
||||
useEscaping: command.boolArg('use-escaping'),
|
||||
suppressWarnings: command.boolArg('suppress-warnings'),
|
||||
useNamedParameters: command.boolArg('use-named-parameters'),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -96,6 +96,7 @@ void main() {
|
||||
bool areResourceAttributeRequired = false,
|
||||
bool suppressWarnings = false,
|
||||
bool relaxSyntax = false,
|
||||
bool useNamedParameters = false,
|
||||
void Function(Directory)? setup,
|
||||
}
|
||||
) {
|
||||
@ -128,6 +129,7 @@ void main() {
|
||||
areResourceAttributesRequired: areResourceAttributeRequired,
|
||||
suppressWarnings: suppressWarnings,
|
||||
useRelaxedSyntax: relaxSyntax,
|
||||
useNamedParameters: useNamedParameters,
|
||||
)
|
||||
..loadResources()
|
||||
..writeOutputFiles(isFromYaml: isFromYaml);
|
||||
@ -2491,4 +2493,43 @@ NumberFormat.decimalPatternDigits(
|
||||
setupLocalizations(<String, String>{ 'en': dollarSignWithSelect });
|
||||
expect(getGeneratedFileContent(locale: 'en'), contains(r'\$nice_bug\nHello Bug! Manifistation #1 $_temp0'));
|
||||
});
|
||||
|
||||
testWithoutContext('can generate method with named parameter', () {
|
||||
const String arbFile = '''
|
||||
{
|
||||
"helloName": "Hello {name}!",
|
||||
"@helloName": {
|
||||
"description": "A more personal greeting",
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String",
|
||||
"description": "The name of the person to greet"
|
||||
}
|
||||
}
|
||||
},
|
||||
"helloNameAndAge": "Hello {name}! You are {age} years old.",
|
||||
"@helloNameAndAge": {
|
||||
"description": "A more personal greeting",
|
||||
"placeholders": {
|
||||
"name": {
|
||||
"type": "String",
|
||||
"description": "The name of the person to greet"
|
||||
},
|
||||
"age": {
|
||||
"type": "int",
|
||||
"description": "The age of the person to greet"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
''';
|
||||
setupLocalizations(<String, String>{ 'en': arbFile }, useNamedParameters: true);
|
||||
final String localizationsFile = getGeneratedFileContent(locale: 'en');
|
||||
expect(localizationsFile, containsIgnoringWhitespace(r'''
|
||||
String helloName({required String name}) {
|
||||
'''));
|
||||
expect(localizationsFile, containsIgnoringWhitespace(r'''
|
||||
String helloNameAndAge({required String name, required int age}) {
|
||||
'''));
|
||||
});
|
||||
}
|
||||
|
@ -11,7 +11,12 @@ import 'test_data/gen_l10n_project.dart';
|
||||
import 'test_driver.dart';
|
||||
import 'test_utils.dart';
|
||||
|
||||
final GenL10nProject project = GenL10nProject();
|
||||
final GenL10nProject project = GenL10nProject(
|
||||
useNamedParameters: false,
|
||||
);
|
||||
final GenL10nProject projectWithNamedParameter = GenL10nProject(
|
||||
useNamedParameters: true,
|
||||
);
|
||||
|
||||
// Verify that the code generated by gen_l10n executes correctly.
|
||||
// It can fail if gen_l10n produces a lib/l10n/app_localizations.dart that
|
||||
@ -180,4 +185,11 @@ void main() {
|
||||
final StringBuffer stdout = await runApp();
|
||||
expectOutput(stdout);
|
||||
});
|
||||
|
||||
testWithoutContext('generated l10n classes produce expected localized strings when named parameter is used', () async {
|
||||
await projectWithNamedParameter.setUpIn(tempDir);
|
||||
flutter = FlutterRunTestDriver(tempDir);
|
||||
final StringBuffer stdout = await runApp();
|
||||
expectOutput(stdout);
|
||||
});
|
||||
}
|
||||
|
@ -8,6 +8,8 @@ import '../test_utils.dart';
|
||||
import 'project.dart';
|
||||
|
||||
class GenL10nProject extends Project {
|
||||
GenL10nProject({required this.useNamedParameters});
|
||||
|
||||
@override
|
||||
Future<void> setUpIn(Directory dir, {
|
||||
bool useDeferredLoading = false,
|
||||
@ -26,10 +28,12 @@ class GenL10nProject extends Project {
|
||||
writeFile(fileSystem.path.join(dir.path, 'l10n.yaml'), l10nYaml(
|
||||
useDeferredLoading: useDeferredLoading,
|
||||
useSyntheticPackage: useSyntheticPackage,
|
||||
useNamedParameters: useNamedParameters,
|
||||
));
|
||||
return super.setUpIn(dir);
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
final String pubspec = '''
|
||||
name: test_l10n_project
|
||||
@ -44,290 +48,13 @@ dependencies:
|
||||
intl: any # Pick up the pinned version from flutter_localizations
|
||||
''';
|
||||
|
||||
String? _main;
|
||||
|
||||
@override
|
||||
final String main = r'''
|
||||
import 'package:flutter/material.dart';
|
||||
String get main =>
|
||||
_main ??= (useNamedParameters ? _getMainWithNamedParameters() : _getMain());
|
||||
|
||||
import 'l10n/app_localizations.dart';
|
||||
|
||||
class LocaleBuilder extends StatelessWidget {
|
||||
const LocaleBuilder({
|
||||
Key? key,
|
||||
this.locale,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final Locale? locale;
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Localizations.override(
|
||||
locale: locale,
|
||||
context: context,
|
||||
child: ResultBuilder(
|
||||
test: test,
|
||||
callback: callback,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ResultBuilder extends StatelessWidget {
|
||||
const ResultBuilder({
|
||||
Key? key,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
try {
|
||||
callback(context);
|
||||
} on Exception catch (e) {
|
||||
print('#l10n A(n) $e has occurred trying to generate "$test" results.');
|
||||
print('#l10n END');
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> results = [];
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
LocaleBuilder(
|
||||
test: 'supportedLocales',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- supportedLocales tests ---');
|
||||
int n = 0;
|
||||
for (Locale locale in AppLocalizations.supportedLocales) {
|
||||
String languageCode = locale.languageCode;
|
||||
String? countryCode = locale.countryCode;
|
||||
String? scriptCode = locale.scriptCode;
|
||||
results.add('supportedLocales[$n]: languageCode: $languageCode, countryCode: $countryCode, scriptCode: $scriptCode');
|
||||
n += 1;
|
||||
}
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'CA'),
|
||||
test: 'countryCode - en_CA',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_CA) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello("CA fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'GB'),
|
||||
test: 'countryCode - en_GB',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_GB) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello("GB fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('zh'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- zh ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(0));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(1));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(2));
|
||||
// Should use the fallback language, in this case,
|
||||
// "Hello 世界" should be displayed.
|
||||
results.add(AppLocalizations.of(context)!.hello("世界"));
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
results.add(AppLocalizations.of(context)!.helloCost("价钱", 123));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode: zh_Hans ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', countryCode: 'TW', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_TW_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant_TW ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en'),
|
||||
test: 'General formatting',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- General formatting tests ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello("World")}',
|
||||
'${localizations.greeting("Hello", "World")}',
|
||||
'${localizations.helloWorldOn(DateTime(1960))}',
|
||||
'${localizations.helloOn("world argument", DateTime(1960), DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(DateTime(1960), DateTime(2020))}',
|
||||
'${localizations.helloFor(123)}',
|
||||
'${localizations.helloCost("price", 123)}',
|
||||
'${localizations.helloCostWithOptionalParam("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter1("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter2("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter3("price", .5)}',
|
||||
'${localizations.helloDecimalPattern(1200000)}',
|
||||
'${localizations.helloPercentPattern(1200000)}',
|
||||
'${localizations.helloScientificPattern(1200000)}',
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
'${localizations.helloAdjectiveWorlds(0, "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(1, "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(2, "new")}',
|
||||
'${localizations.helloWorldsOn(0, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(1, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(2, DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(0, 100)}',
|
||||
'${localizations.helloWorldPopulation(1, 101)}',
|
||||
'${localizations.helloWorldPopulation(2, 102)}',
|
||||
'${localizations.helloWorldsInterpolation(123, "Hello", "World")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(2)}',
|
||||
"${localizations.vehicleSelect('truck')}",
|
||||
"${localizations.singleQuoteSelect('sedan')}",
|
||||
"${localizations.doubleQuoteSelect('cabriolet')}",
|
||||
"${localizations.pluralInString(1)}",
|
||||
"${localizations.selectInString('he')}",
|
||||
"${localizations.selectWithPlaceholder('male', 'ice cream')}",
|
||||
"${localizations.selectWithPlaceholder('female', 'chocolate')}",
|
||||
"${localizations.selectInPlural('male', 1)}",
|
||||
"${localizations.selectInPlural('male', 2)}",
|
||||
"${localizations.selectInPlural('female', 1)}",
|
||||
'${localizations.datetime1(DateTime(2023, 6, 26))}',
|
||||
'${localizations.datetime2(DateTime(2023, 6, 26, 5, 23))}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('es'),
|
||||
test: '--- es ---',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello("Mundo")}',
|
||||
'${localizations.greeting("Hola", "Mundo")}',
|
||||
'${localizations.helloWorldOn(DateTime(1960))}',
|
||||
'${localizations.helloOn("world argument", DateTime(1960), DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(DateTime(1960), DateTime(2020))}',
|
||||
'${localizations.helloFor(123)}',
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
'${localizations.helloAdjectiveWorlds(0, "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(1, "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(2, "nuevo")}',
|
||||
'${localizations.helloWorldsOn(0, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(1, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(2, DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(0, 100)}',
|
||||
'${localizations.helloWorldPopulation(1, 101)}',
|
||||
'${localizations.helloWorldPopulation(2, 102)}',
|
||||
'${localizations.helloWorldsInterpolation(123, "Hola", "Mundo")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(2)}',
|
||||
"${localizations.vehicleSelect('truck')}",
|
||||
"${localizations.singleQuoteSelect('sedan')}",
|
||||
"${localizations.doubleQuoteSelect('cabriolet')}",
|
||||
"${localizations.pluralInString(1)}",
|
||||
"${localizations.selectInString('he')}",
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'es', countryCode: '419'),
|
||||
test: 'countryCode - es_419',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es_419 ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll([
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
callback: (BuildContext context) {
|
||||
try {
|
||||
int n = 0;
|
||||
for (final String result in results) {
|
||||
// Newline character replacement is necessary because
|
||||
// the stream breaks up stdout by new lines.
|
||||
print('#l10n $n (${result.replaceAll('\n', '_NEWLINE_')})');
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
print('#l10n END');
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(
|
||||
MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: Home(),
|
||||
),
|
||||
);
|
||||
}
|
||||
''';
|
||||
final bool useNamedParameters;
|
||||
|
||||
final String appEn = r'''
|
||||
{
|
||||
@ -777,9 +504,577 @@ void main() {
|
||||
}
|
||||
''';
|
||||
|
||||
String _getMain() => r'''
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'l10n/app_localizations.dart';
|
||||
|
||||
class LocaleBuilder extends StatelessWidget {
|
||||
const LocaleBuilder({
|
||||
Key? key,
|
||||
this.locale,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final Locale? locale;
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Localizations.override(
|
||||
locale: locale,
|
||||
context: context,
|
||||
child: ResultBuilder(
|
||||
test: test,
|
||||
callback: callback,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ResultBuilder extends StatelessWidget {
|
||||
const ResultBuilder({
|
||||
Key? key,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
try {
|
||||
callback(context);
|
||||
} on Exception catch (e) {
|
||||
print('#l10n A(n) $e has occurred trying to generate "$test" results.');
|
||||
print('#l10n END');
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> results = [];
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
LocaleBuilder(
|
||||
test: 'supportedLocales',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- supportedLocales tests ---');
|
||||
int n = 0;
|
||||
for (Locale locale in AppLocalizations.supportedLocales) {
|
||||
String languageCode = locale.languageCode;
|
||||
String? countryCode = locale.countryCode;
|
||||
String? scriptCode = locale.scriptCode;
|
||||
results.add('supportedLocales[$n]: languageCode: $languageCode, countryCode: $countryCode, scriptCode: $scriptCode');
|
||||
n += 1;
|
||||
}
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'CA'),
|
||||
test: 'countryCode - en_CA',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_CA) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello("CA fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'GB'),
|
||||
test: 'countryCode - en_GB',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_GB) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello("GB fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('zh'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- zh ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(0));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(1));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(2));
|
||||
// Should use the fallback language, in this case,
|
||||
// "Hello 世界" should be displayed.
|
||||
results.add(AppLocalizations.of(context)!.hello("世界"));
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
results.add(AppLocalizations.of(context)!.helloCost("价钱", 123));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode: zh_Hans ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', countryCode: 'TW', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_TW_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant_TW ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en'),
|
||||
test: 'General formatting',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- General formatting tests ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello("World")}',
|
||||
'${localizations.greeting("Hello", "World")}',
|
||||
'${localizations.helloWorldOn(DateTime(1960))}',
|
||||
'${localizations.helloOn("world argument", DateTime(1960), DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(DateTime(1960), DateTime(2020))}',
|
||||
'${localizations.helloFor(123)}',
|
||||
'${localizations.helloCost("price", 123)}',
|
||||
'${localizations.helloCostWithOptionalParam("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter1("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter2("price", .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter3("price", .5)}',
|
||||
'${localizations.helloDecimalPattern(1200000)}',
|
||||
'${localizations.helloPercentPattern(1200000)}',
|
||||
'${localizations.helloScientificPattern(1200000)}',
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
'${localizations.helloAdjectiveWorlds(0, "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(1, "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(2, "new")}',
|
||||
'${localizations.helloWorldsOn(0, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(1, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(2, DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(0, 100)}',
|
||||
'${localizations.helloWorldPopulation(1, 101)}',
|
||||
'${localizations.helloWorldPopulation(2, 102)}',
|
||||
'${localizations.helloWorldsInterpolation(123, "Hello", "World")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(2)}',
|
||||
"${localizations.vehicleSelect('truck')}",
|
||||
"${localizations.singleQuoteSelect('sedan')}",
|
||||
"${localizations.doubleQuoteSelect('cabriolet')}",
|
||||
"${localizations.pluralInString(1)}",
|
||||
"${localizations.selectInString('he')}",
|
||||
"${localizations.selectWithPlaceholder('male', 'ice cream')}",
|
||||
"${localizations.selectWithPlaceholder('female', 'chocolate')}",
|
||||
"${localizations.selectInPlural('male', 1)}",
|
||||
"${localizations.selectInPlural('male', 2)}",
|
||||
"${localizations.selectInPlural('female', 1)}",
|
||||
'${localizations.datetime1(DateTime(2023, 6, 26))}',
|
||||
'${localizations.datetime2(DateTime(2023, 6, 26, 5, 23))}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('es'),
|
||||
test: '--- es ---',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello("Mundo")}',
|
||||
'${localizations.greeting("Hola", "Mundo")}',
|
||||
'${localizations.helloWorldOn(DateTime(1960))}',
|
||||
'${localizations.helloOn("world argument", DateTime(1960), DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(DateTime(1960), DateTime(2020))}',
|
||||
'${localizations.helloFor(123)}',
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
'${localizations.helloAdjectiveWorlds(0, "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(1, "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(2, "nuevo")}',
|
||||
'${localizations.helloWorldsOn(0, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(1, DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(2, DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(0, 100)}',
|
||||
'${localizations.helloWorldPopulation(1, 101)}',
|
||||
'${localizations.helloWorldPopulation(2, 102)}',
|
||||
'${localizations.helloWorldsInterpolation(123, "Hola", "Mundo")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(2)}',
|
||||
"${localizations.vehicleSelect('truck')}",
|
||||
"${localizations.singleQuoteSelect('sedan')}",
|
||||
"${localizations.doubleQuoteSelect('cabriolet')}",
|
||||
"${localizations.pluralInString(1)}",
|
||||
"${localizations.selectInString('he')}",
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'es', countryCode: '419'),
|
||||
test: 'countryCode - es_419',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es_419 ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll([
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloWorlds(0)}',
|
||||
'${localizations.helloWorlds(1)}',
|
||||
'${localizations.helloWorlds(2)}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
callback: (BuildContext context) {
|
||||
try {
|
||||
int n = 0;
|
||||
for (final String result in results) {
|
||||
// Newline character replacement is necessary because
|
||||
// the stream breaks up stdout by new lines.
|
||||
print('#l10n $n (${result.replaceAll('\n', '_NEWLINE_')})');
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
print('#l10n END');
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(
|
||||
MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: Home(),
|
||||
),
|
||||
);
|
||||
}
|
||||
''';
|
||||
|
||||
String _getMainWithNamedParameters() => r'''
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'l10n/app_localizations.dart';
|
||||
|
||||
class LocaleBuilder extends StatelessWidget {
|
||||
const LocaleBuilder({
|
||||
Key? key,
|
||||
this.locale,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final Locale? locale;
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Localizations.override(
|
||||
locale: locale,
|
||||
context: context,
|
||||
child: ResultBuilder(
|
||||
test: test,
|
||||
callback: callback,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ResultBuilder extends StatelessWidget {
|
||||
const ResultBuilder({
|
||||
Key? key,
|
||||
this.test,
|
||||
required this.callback,
|
||||
}) : super(key: key);
|
||||
|
||||
final String? test;
|
||||
final void Function (BuildContext context) callback;
|
||||
|
||||
@override build(BuildContext context) {
|
||||
return Builder(
|
||||
builder: (BuildContext context) {
|
||||
try {
|
||||
callback(context);
|
||||
} on Exception catch (e) {
|
||||
print('#l10n A(n) $e has occurred trying to generate "$test" results.');
|
||||
print('#l10n END');
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class Home extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final List<String> results = [];
|
||||
return Row(
|
||||
children: <Widget>[
|
||||
LocaleBuilder(
|
||||
test: 'supportedLocales',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- supportedLocales tests ---');
|
||||
int n = 0;
|
||||
for (Locale locale in AppLocalizations.supportedLocales) {
|
||||
String languageCode = locale.languageCode;
|
||||
String? countryCode = locale.countryCode;
|
||||
String? scriptCode = locale.scriptCode;
|
||||
results.add('supportedLocales[$n]: languageCode: $languageCode, countryCode: $countryCode, scriptCode: $scriptCode');
|
||||
n += 1;
|
||||
}
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'CA'),
|
||||
test: 'countryCode - en_CA',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_CA) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello(world: "CA fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en', 'GB'),
|
||||
test: 'countryCode - en_GB',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- countryCode (en_GB) tests ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.hello(world: "GB fallback World"));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('zh'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- zh ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(count: 0));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(count: 1));
|
||||
results.add(AppLocalizations.of(context)!.helloWorlds(count: 2));
|
||||
// Should use the fallback language, in this case,
|
||||
// "Hello 世界" should be displayed.
|
||||
results.add(AppLocalizations.of(context)!.hello(world: "世界"));
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
results.add(AppLocalizations.of(context)!.helloCost(price: "价钱", value: 123));
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hans'),
|
||||
test: 'zh',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode: zh_Hans ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'zh', countryCode: 'TW', scriptCode: 'Hant'),
|
||||
test: 'scriptCode - zh_TW_Hant',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- scriptCode - zh_Hant_TW ---');
|
||||
results.add(AppLocalizations.of(context)!.helloWorld);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('en'),
|
||||
test: 'General formatting',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- General formatting tests ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello(world: "World")}',
|
||||
'${localizations.greeting(hello: "Hello", world: "World")}',
|
||||
'${localizations.helloWorldOn(date: DateTime(1960))}',
|
||||
'${localizations.helloOn(world: "world argument", date: DateTime(1960), time: DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(startDate: DateTime(1960), endDate: DateTime(2020))}',
|
||||
'${localizations.helloFor(value: 123)}',
|
||||
'${localizations.helloCost(price: "price", value: 123)}',
|
||||
'${localizations.helloCostWithOptionalParam(price: "price", value: .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter1(price: "price", value: .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter2(price: "price", value: .5)}',
|
||||
'${localizations.helloCostWithSpecialCharacter3(price: "price", value: .5)}',
|
||||
'${localizations.helloDecimalPattern(value: 1200000)}',
|
||||
'${localizations.helloPercentPattern(value: 1200000)}',
|
||||
'${localizations.helloScientificPattern(value: 1200000)}',
|
||||
'${localizations.helloWorlds(count: 0)}',
|
||||
'${localizations.helloWorlds(count: 1)}',
|
||||
'${localizations.helloWorlds(count: 2)}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 0, adjective: "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 1, adjective: "new")}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 2, adjective: "new")}',
|
||||
'${localizations.helloWorldsOn(count: 0, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(count: 1, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(count: 2, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(count: 0, population: 100)}',
|
||||
'${localizations.helloWorldPopulation(count: 1, population: 101)}',
|
||||
'${localizations.helloWorldPopulation(count: 2, population: 102)}',
|
||||
'${localizations.helloWorldsInterpolation(count: 123, hello: "Hello", world: "World")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(count: 1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(count: 2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(count: 2)}',
|
||||
"${localizations.vehicleSelect(vehicleType: 'truck')}",
|
||||
"${localizations.singleQuoteSelect(vehicleType: 'sedan')}",
|
||||
"${localizations.doubleQuoteSelect(vehicleType: 'cabriolet')}",
|
||||
"${localizations.pluralInString(count: 1)}",
|
||||
"${localizations.selectInString(gender: 'he')}",
|
||||
"${localizations.selectWithPlaceholder(gender: 'male', preference: 'ice cream')}",
|
||||
"${localizations.selectWithPlaceholder(gender: 'female', preference: 'chocolate')}",
|
||||
"${localizations.selectInPlural(gender: 'male', count: 1)}",
|
||||
"${localizations.selectInPlural(gender: 'male', count: 2)}",
|
||||
"${localizations.selectInPlural(gender: 'female', count: 1)}",
|
||||
'${localizations.datetime1(today: DateTime(2023, 6, 26))}',
|
||||
'${localizations.datetime2(current: DateTime(2023, 6, 26, 5, 23))}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale('es'),
|
||||
test: '--- es ---',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll(<String>[
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloNewlineWorld}',
|
||||
'${localizations.testDollarSign}',
|
||||
'${localizations.hello(world: "Mundo")}',
|
||||
'${localizations.greeting(hello: "Hola", world: "Mundo")}',
|
||||
'${localizations.helloWorldOn(date: DateTime(1960))}',
|
||||
'${localizations.helloOn(world: "world argument", date: DateTime(1960), time: DateTime(1960))}',
|
||||
'${localizations.helloWorldDuring(startDate: DateTime(1960), endDate: DateTime(2020))}',
|
||||
'${localizations.helloFor(value: 123)}',
|
||||
// helloCost is tested in 'zh' because 'es' currency format contains a
|
||||
// non-breaking space character (U+00A0), which if removed,
|
||||
// makes it hard to decipher why the test is failing.
|
||||
'${localizations.helloWorlds(count: 0)}',
|
||||
'${localizations.helloWorlds(count: 1)}',
|
||||
'${localizations.helloWorlds(count: 2)}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 0, adjective: "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 1, adjective: "nuevo")}',
|
||||
'${localizations.helloAdjectiveWorlds(count: 2, adjective: "nuevo")}',
|
||||
'${localizations.helloWorldsOn(count: 0, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(count: 1, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldsOn(count: 2, date: DateTime(1960))}',
|
||||
'${localizations.helloWorldPopulation(count: 0, population: 100)}',
|
||||
'${localizations.helloWorldPopulation(count: 1, population: 101)}',
|
||||
'${localizations.helloWorldPopulation(count: 2, population: 102)}',
|
||||
'${localizations.helloWorldsInterpolation(count: 123, hello: "Hola", world: "Mundo")}',
|
||||
'${localizations.dollarSign}',
|
||||
'${localizations.dollarSignPlural(count: 1)}',
|
||||
'${localizations.singleQuote}',
|
||||
'${localizations.singleQuotePlural(count: 2)}',
|
||||
'${localizations.doubleQuote}',
|
||||
'${localizations.doubleQuotePlural(count: 2)}',
|
||||
"${localizations.vehicleSelect(vehicleType: 'truck')}",
|
||||
"${localizations.singleQuoteSelect(vehicleType: 'sedan')}",
|
||||
"${localizations.doubleQuoteSelect(vehicleType: 'cabriolet')}",
|
||||
"${localizations.pluralInString(count: 1)}",
|
||||
"${localizations.selectInString(gender: 'he')}",
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
locale: Locale.fromSubtags(languageCode: 'es', countryCode: '419'),
|
||||
test: 'countryCode - es_419',
|
||||
callback: (BuildContext context) {
|
||||
results.add('--- es_419 ---');
|
||||
final AppLocalizations localizations = AppLocalizations.of(context)!;
|
||||
results.addAll([
|
||||
'${localizations.helloWorld}',
|
||||
'${localizations.helloWorlds(count: 0)}',
|
||||
'${localizations.helloWorlds(count: 1)}',
|
||||
'${localizations.helloWorlds(count: 2)}',
|
||||
]);
|
||||
},
|
||||
),
|
||||
LocaleBuilder(
|
||||
callback: (BuildContext context) {
|
||||
try {
|
||||
int n = 0;
|
||||
for (final String result in results) {
|
||||
// Newline character replacement is necessary because
|
||||
// the stream breaks up stdout by new lines.
|
||||
print('#l10n $n (${result.replaceAll('\n', '_NEWLINE_')})');
|
||||
n += 1;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
print('#l10n END');
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
runApp(
|
||||
MaterialApp(
|
||||
localizationsDelegates: AppLocalizations.localizationsDelegates,
|
||||
supportedLocales: AppLocalizations.supportedLocales,
|
||||
home: Home(),
|
||||
),
|
||||
);
|
||||
}''';
|
||||
|
||||
String l10nYaml({
|
||||
required bool useDeferredLoading,
|
||||
required bool useSyntheticPackage,
|
||||
required bool useNamedParameters,
|
||||
}) {
|
||||
String l10nYamlString = '';
|
||||
|
||||
@ -791,6 +1086,10 @@ void main() {
|
||||
l10nYamlString += 'synthetic-package: false\n';
|
||||
}
|
||||
|
||||
if (useNamedParameters) {
|
||||
l10nYamlString += 'use-named-parameters: true\n';
|
||||
}
|
||||
|
||||
return l10nYamlString;
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user