mirror of
https://github.com/flutter/flutter
synced 2024-09-20 08:42:11 +00:00
Update gen_l10n tool to require base locale; Stocks app refresh (#51602)
This commit is contained in:
parent
6a337a76dd
commit
c98500dea3
|
@ -23,16 +23,10 @@ The `flutter run --release` command both builds and installs the Flutter app.
|
|||
## Internationalization
|
||||
|
||||
This app has been internationalized (just enough to show how it's
|
||||
done). It's an example of how one can do so with the
|
||||
[Dart intl package](https://pub.dev/packages/intl).
|
||||
done). It's an example of how one can do so with the gen_l10n tool.
|
||||
|
||||
The [Flutter Internationalization Tutorial](https://flutter.dev/tutorials/internationalization/)
|
||||
covers Flutter app internationalization in general.
|
||||
|
||||
See [regenerate.md](lib/i18n/regenerate.md) for an explanation
|
||||
of how the Dart internationalization tools, like
|
||||
`intl_translation:generate_from_arb`, were used to generate
|
||||
localizations for this app.
|
||||
See [regenerate.md](lib/i18n/regenerate.md) for an explanation for how
|
||||
the tool is used to generate localizations for this app.
|
||||
|
||||
## Icon
|
||||
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||
// This is a library that looks up messages for specific locales by
|
||||
// delegating to the appropriate library.
|
||||
|
||||
// Ignore issues from commonly used lints in this file.
|
||||
// ignore_for_file:implementation_imports, file_names, unnecessary_new
|
||||
// ignore_for_file:unnecessary_brace_in_string_interps, directives_ordering
|
||||
// ignore_for_file:argument_type_not_assignable, invalid_assignment
|
||||
// ignore_for_file:prefer_single_quotes, prefer_generic_function_type_aliases
|
||||
// ignore_for_file:comment_references
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/message_lookup_by_library.dart';
|
||||
import 'package:intl/src/intl_helpers.dart';
|
||||
|
||||
import 'messages_en_US.dart' as messages_en_us;
|
||||
import 'messages_es_ES.dart' as messages_es_es;
|
||||
|
||||
typedef Future<dynamic> LibraryLoader();
|
||||
Map<String, LibraryLoader> _deferredLibraries = {
|
||||
'en_US': () => new Future.value(null),
|
||||
'es_ES': () => new Future.value(null),
|
||||
};
|
||||
|
||||
MessageLookupByLibrary _findExact(String localeName) {
|
||||
switch (localeName) {
|
||||
case 'en_US':
|
||||
return messages_en_us.messages;
|
||||
case 'es_ES':
|
||||
return messages_es_es.messages;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// User programs should call this before using [localeName] for messages.
|
||||
Future<bool> initializeMessages(String localeName) async {
|
||||
var availableLocale = Intl.verifiedLocale(
|
||||
localeName,
|
||||
(locale) => _deferredLibraries[locale] != null,
|
||||
onFailure: (_) => null);
|
||||
if (availableLocale == null) {
|
||||
return new Future.value(false);
|
||||
}
|
||||
var lib = _deferredLibraries[availableLocale];
|
||||
await (lib == null ? new Future.value(false) : lib());
|
||||
initializeInternalMessageLookup(() => new CompositeMessageLookup());
|
||||
messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
|
||||
return new Future.value(true);
|
||||
}
|
||||
|
||||
bool _messagesExistFor(String locale) {
|
||||
try {
|
||||
return _findExact(locale) != null;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
MessageLookupByLibrary _findGeneratedMessagesFor(String locale) {
|
||||
var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor,
|
||||
onFailure: (_) => null);
|
||||
if (actualLocale == null) return null;
|
||||
return _findExact(actualLocale);
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||
// This is a library that provides messages for a en_US locale. All the
|
||||
// messages from the main program should be duplicated here with the same
|
||||
// function name.
|
||||
|
||||
// Ignore issues from commonly used lints in this file.
|
||||
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
|
||||
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
|
||||
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
|
||||
// ignore_for_file:unused_import, file_names
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/message_lookup_by_library.dart';
|
||||
|
||||
final messages = new MessageLookup();
|
||||
|
||||
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
|
||||
|
||||
class MessageLookup extends MessageLookupByLibrary {
|
||||
String get localeName => 'en_US';
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
"market" : MessageLookupByLibrary.simpleMessage("MARKET"),
|
||||
"portfolio" : MessageLookupByLibrary.simpleMessage("PORTFOLIO"),
|
||||
"title" : MessageLookupByLibrary.simpleMessage("Stocks")
|
||||
};
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||
// This is a library that provides messages for a es_ES locale. All the
|
||||
// messages from the main program should be duplicated here with the same
|
||||
// function name.
|
||||
|
||||
// Ignore issues from commonly used lints in this file.
|
||||
// ignore_for_file:unnecessary_brace_in_string_interps, unnecessary_new
|
||||
// ignore_for_file:prefer_single_quotes,comment_references, directives_ordering
|
||||
// ignore_for_file:annotate_overrides,prefer_generic_function_type_aliases
|
||||
// ignore_for_file:unused_import, file_names
|
||||
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:intl/message_lookup_by_library.dart';
|
||||
|
||||
final messages = new MessageLookup();
|
||||
|
||||
typedef String MessageIfAbsent(String messageStr, List<dynamic> args);
|
||||
|
||||
class MessageLookup extends MessageLookupByLibrary {
|
||||
String get localeName => 'es_ES';
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
"market" : MessageLookupByLibrary.simpleMessage("MERCADO"),
|
||||
"portfolio" : MessageLookupByLibrary.simpleMessage("CARTERA"),
|
||||
"title" : MessageLookupByLibrary.simpleMessage("Acciones")
|
||||
};
|
||||
}
|
|
@ -6,8 +6,9 @@ stocks app uses the [Dart `intl` package](https://github.com/dart-lang/intl).
|
|||
|
||||
Rebuilding everything requires two steps.
|
||||
|
||||
1. Create or update the English and Spanish localizations, `stocks_en_US.arb`
|
||||
and `stocks_es_ES.arb`. See the [ARB specification](https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification)
|
||||
1. Create or update the English and Spanish localizations,
|
||||
`stocks_en_US.arb`, `stocks_en.arb`, and `stocks_es.arb`. See the
|
||||
[ARB specification](https://github.com/google/app-resource-bundle/wiki/ApplicationResourceBundleSpecification)
|
||||
for more info.
|
||||
|
||||
2. With `examples/stocks` as the current directory, generate a
|
||||
|
@ -20,7 +21,9 @@ dart ${FLUTTER_PATH}/dev/tools/localization/bin/gen_l10n.dart --arb-dir=lib/i18n
|
|||
--output-class=StockStrings
|
||||
```
|
||||
|
||||
The `StockStrings` class uses the generated `initializeMessages()`function
|
||||
(`messages_all.dart`) to load the localized messages and `Intl.message()`
|
||||
to look them up. The generated class's API documentation explains how to add
|
||||
the new localizations delegate and supported locales to the Flutter application.
|
||||
The `StockStrings` class creates a delegate that performs message lookups
|
||||
based on the locale of the device. In this case, the stocks app supports
|
||||
`en`, `en_US`, and `es`. Thus, the `StockStringsEn` and `StockStringsEs`
|
||||
classes extends `StockStrings`. `StockStringsEnUs` extends
|
||||
`StockStringsEn`. This allows `StockStringsEnUs` to fall back on messages
|
||||
in `StockStringsEn`.
|
|
@ -1,10 +1,16 @@
|
|||
// Copyright 2014 The Flutter Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
import 'messages_all.dart';
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps
|
||||
|
||||
/// Callers can lookup localized strings with an instance of StockStrings returned
|
||||
/// by `StockStrings.of(context)`.
|
||||
|
@ -58,16 +64,12 @@ import 'messages_all.dart';
|
|||
/// you wish to add from the pop-up menu in the Value field. This list should
|
||||
/// be consistent with the languages listed in the StockStrings.supportedLocales
|
||||
/// property.
|
||||
class StockStrings {
|
||||
StockStrings(Locale locale) : _localeName = Intl.canonicalizedLocale(locale.toString());
|
||||
abstract class StockStrings {
|
||||
StockStrings(String locale) : assert(locale != null), _localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
// ignore: unused_field
|
||||
final String _localeName;
|
||||
|
||||
static Future<StockStrings> load(Locale locale) {
|
||||
return initializeMessages(locale.toString())
|
||||
.then<StockStrings>((_) => StockStrings(locale));
|
||||
}
|
||||
|
||||
static StockStrings of(BuildContext context) {
|
||||
return Localizations.of<StockStrings>(context, StockStrings);
|
||||
}
|
||||
|
@ -80,6 +82,10 @@ class StockStrings {
|
|||
/// Returns a list of localizations delegates containing this delegate along with
|
||||
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
|
||||
/// and GlobalWidgetsLocalizations.delegate.
|
||||
///
|
||||
/// Additional delegates can be added by appending to this list in
|
||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
|
@ -89,44 +95,28 @@ class StockStrings {
|
|||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('en', 'US'),
|
||||
Locale('es', 'ES'),
|
||||
Locale('en'),
|
||||
Locale('en, US'),
|
||||
Locale('es')
|
||||
];
|
||||
|
||||
String get market {
|
||||
return Intl.message(
|
||||
r'MARKET',
|
||||
locale: _localeName,
|
||||
name: 'market',
|
||||
desc: r'Label for the Market tab'
|
||||
);
|
||||
}
|
||||
// Title for the Stocks application
|
||||
String get title;
|
||||
|
||||
String get portfolio {
|
||||
return Intl.message(
|
||||
r'PORTFOLIO',
|
||||
locale: _localeName,
|
||||
name: 'portfolio',
|
||||
desc: r'Label for the Portfolio tab'
|
||||
);
|
||||
}
|
||||
|
||||
String get title {
|
||||
return Intl.message(
|
||||
r'Stocks',
|
||||
locale: _localeName,
|
||||
name: 'title',
|
||||
desc: r'Title for the Stocks application'
|
||||
);
|
||||
}
|
||||
// Label for the Market tab
|
||||
String get market;
|
||||
|
||||
// Label for the Portfolio tab
|
||||
String get portfolio;
|
||||
}
|
||||
|
||||
class _StockStringsDelegate extends LocalizationsDelegate<StockStrings> {
|
||||
const _StockStringsDelegate();
|
||||
|
||||
@override
|
||||
Future<StockStrings> load(Locale locale) => StockStrings.load(locale);
|
||||
Future<StockStrings> load(Locale locale) {
|
||||
return SynchronousFuture<StockStrings>(_lookupStockStrings(locale));
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) => <String>['en', 'es'].contains(locale.languageCode);
|
||||
|
@ -134,3 +124,59 @@ class _StockStringsDelegate extends LocalizationsDelegate<StockStrings> {
|
|||
@override
|
||||
bool shouldReload(_StockStringsDelegate old) => false;
|
||||
}
|
||||
|
||||
/// The translations for English (`en`).
|
||||
class StockStringsEn extends StockStrings {
|
||||
StockStringsEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get title => 'Stocks';
|
||||
|
||||
@override
|
||||
String get market => 'MARKET';
|
||||
|
||||
@override
|
||||
String get portfolio => 'PORTFOLIO';
|
||||
}
|
||||
|
||||
/// The translations for English, as used in the United States (`en_US`).
|
||||
class StockStringsEnUs extends StockStringsEn {
|
||||
StockStringsEnUs([String locale = 'en_US']) : super(locale);
|
||||
|
||||
@override
|
||||
String get title => 'Stocks';
|
||||
|
||||
@override
|
||||
String get market => 'MARKET';
|
||||
|
||||
@override
|
||||
String get portfolio => 'PORTFOLIO';
|
||||
}
|
||||
|
||||
/// The translations for Spanish Castilian (`es`).
|
||||
class StockStringsEs extends StockStrings {
|
||||
StockStringsEs([String locale = 'es']) : super(locale);
|
||||
|
||||
@override
|
||||
String get title => 'Acciones';
|
||||
|
||||
@override
|
||||
String get market => 'MERCADO';
|
||||
|
||||
@override
|
||||
String get portfolio => 'CARTERA';
|
||||
}
|
||||
|
||||
StockStrings _lookupStockStrings(Locale locale) {
|
||||
switch(locale.languageCode) {
|
||||
case 'en': {
|
||||
switch (locale.countryCode) {
|
||||
case 'US': return StockStringsEnUs();
|
||||
}
|
||||
return StockStringsEn();
|
||||
}
|
||||
case 'es': return StockStringsEs();
|
||||
}
|
||||
assert(false, 'StockStrings.delegate failed to load unsupported locale "$locale"');
|
||||
return null;
|
||||
}
|
||||
|
|
5
dev/benchmarks/test_apps/stocks/lib/i18n/stocks_en.arb
Normal file
5
dev/benchmarks/test_apps/stocks/lib/i18n/stocks_en.arb
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"title": "Stocks",
|
||||
"market": "MARKET",
|
||||
"portfolio": "PORTFOLIO"
|
||||
}
|
|
@ -11,18 +11,10 @@ void main() {
|
|||
|
||||
testWidgets('Changing locale', (WidgetTester tester) async {
|
||||
stocks.main();
|
||||
await tester.idle(); // see https://github.com/flutter/flutter/issues/1865
|
||||
await tester.pump();
|
||||
// The initial test app's locale is "_", so we're seeing the fallback translation here.
|
||||
expect(find.text('MARKET'), findsOneWidget);
|
||||
await tester.binding.setLocale('es', 'US');
|
||||
await tester.idle();
|
||||
|
||||
// The Localizations widget has been built with the new locale. The
|
||||
// new locale's strings are loaded asynchronously, so we're still
|
||||
// displaying the previous locale's strings.
|
||||
await tester.pump();
|
||||
expect(find.text('MARKET'), findsOneWidget);
|
||||
await tester.binding.setLocale('es', '');
|
||||
|
||||
// The localized strings have finished loading and dependent
|
||||
// widgets have been updated.
|
||||
|
|
|
@ -8,6 +8,7 @@ import 'dart:async';
|
|||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
// ignore_for_file: unnecessary_brace_in_string_interps
|
||||
|
@ -67,6 +68,7 @@ import 'package:intl/intl.dart' as intl;
|
|||
abstract class @(class) {
|
||||
@(class)(String locale) : assert(locale != null), _localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
// ignore: unused_field
|
||||
final String _localeName;
|
||||
|
||||
static @(class) of(BuildContext context) {
|
||||
|
|
|
@ -423,6 +423,23 @@ class AppResourceBundleCollection {
|
|||
languageToLocales[bundle.locale.languageCode].add(bundle.locale);
|
||||
}
|
||||
}
|
||||
|
||||
languageToLocales.forEach((String language, List<LocaleInfo> listOfCorrespondingLocales) {
|
||||
final List<String> localeStrings = listOfCorrespondingLocales.map((LocaleInfo locale) {
|
||||
return locale.toString();
|
||||
}).toList();
|
||||
if (!localeStrings.contains(language)) {
|
||||
throw L10nException(
|
||||
'Arb file for a fallback, $language, does not exist, even though \n'
|
||||
'the following locale(s) exist: $listOfCorrespondingLocales. \n'
|
||||
'When locales specify a script code or country code, a \n'
|
||||
'base locale (without the script code or country code) should \n'
|
||||
'exist as the fallback. Please create a {fileName}_$language.arb \n'
|
||||
'file.'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return AppResourceBundleCollection._(directory, localeToBundle, languageToLocales);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import '../../localization/localizations_utils.dart';
|
|||
import '../common.dart';
|
||||
|
||||
final String defaultArbPathString = path.join('lib', 'l10n');
|
||||
const String defaultTemplateArbFileName = 'app_en_US.arb';
|
||||
const String defaultTemplateArbFileName = 'app_en.arb';
|
||||
const String defaultOutputFileString = 'output-localization-file';
|
||||
const String defaultClassNameString = 'AppLocalizations';
|
||||
const String singleMessageArbFileString = '''
|
||||
|
@ -251,7 +251,7 @@ void main() {
|
|||
fail('Setting language and locales should not fail: \n$e');
|
||||
}
|
||||
|
||||
expect(generator.supportedLocales.contains(LocaleInfo.fromString('en_US')), true);
|
||||
expect(generator.supportedLocales.contains(LocaleInfo.fromString('en')), true);
|
||||
expect(generator.supportedLocales.contains(LocaleInfo.fromString('es')), true);
|
||||
});
|
||||
|
||||
|
@ -263,7 +263,7 @@ void main() {
|
|||
.writeAsStringSync(singleZhMessageArbFileString);
|
||||
l10nDirectory.childFile('app_es.arb')
|
||||
.writeAsStringSync(singleEsMessageArbFileString);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
l10nDirectory.childFile('app_en.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
|
||||
LocalizationsGenerator generator;
|
||||
|
@ -280,7 +280,7 @@ void main() {
|
|||
fail('Setting language and locales should not fail: \n$e');
|
||||
}
|
||||
|
||||
expect(generator.supportedLocales.first, LocaleInfo.fromString('en_US'));
|
||||
expect(generator.supportedLocales.first, LocaleInfo.fromString('en'));
|
||||
expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es'));
|
||||
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('zh'));
|
||||
});
|
||||
|
@ -288,7 +288,7 @@ void main() {
|
|||
test('adds preferred locales to the top of supportedLocales and supportedLanguageCodes', () {
|
||||
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
|
||||
..createSync(recursive: true);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
l10nDirectory.childFile('app_en.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
l10nDirectory.childFile('app_es.arb')
|
||||
.writeAsStringSync(singleEsMessageArbFileString);
|
||||
|
@ -313,7 +313,7 @@ void main() {
|
|||
|
||||
expect(generator.supportedLocales.first, LocaleInfo.fromString('zh'));
|
||||
expect(generator.supportedLocales.elementAt(1), LocaleInfo.fromString('es'));
|
||||
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('en_US'));
|
||||
expect(generator.supportedLocales.elementAt(2), LocaleInfo.fromString('en'));
|
||||
});
|
||||
|
||||
test(
|
||||
|
@ -322,14 +322,14 @@ void main() {
|
|||
() {
|
||||
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
|
||||
..createSync(recursive: true);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
l10nDirectory.childFile('app_en.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
l10nDirectory.childFile('app_es.arb')
|
||||
.writeAsStringSync(singleEsMessageArbFileString);
|
||||
l10nDirectory.childFile('app_zh.arb')
|
||||
.writeAsStringSync(singleZhMessageArbFileString);
|
||||
|
||||
const String preferredSupportedLocaleString = '[44, "en_US"]';
|
||||
const String preferredSupportedLocaleString = '[44, "en"]';
|
||||
LocalizationsGenerator generator;
|
||||
try {
|
||||
generator = LocalizationsGenerator(fs);
|
||||
|
@ -363,7 +363,7 @@ void main() {
|
|||
() {
|
||||
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
|
||||
..createSync(recursive: true);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
l10nDirectory.childFile('app_en.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
l10nDirectory.childFile('app_es.arb')
|
||||
.writeAsStringSync(singleEsMessageArbFileString);
|
||||
|
@ -405,7 +405,7 @@ void main() {
|
|||
.writeAsStringSync(singleZhMessageArbFileString);
|
||||
l10nDirectory.childFile('app_es.arb')
|
||||
.writeAsStringSync(singleEsMessageArbFileString);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
l10nDirectory.childFile('app_en.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
|
||||
LocalizationsGenerator generator;
|
||||
|
@ -423,11 +423,11 @@ void main() {
|
|||
}
|
||||
|
||||
if (Platform.isWindows) {
|
||||
expect(generator.arbPathStrings.first, r'lib\l10n\app_en_US.arb');
|
||||
expect(generator.arbPathStrings.first, r'lib\l10n\app_en.arb');
|
||||
expect(generator.arbPathStrings.elementAt(1), r'lib\l10n\app_es.arb');
|
||||
expect(generator.arbPathStrings.elementAt(2), r'lib\l10n\app_zh.arb');
|
||||
} else {
|
||||
expect(generator.arbPathStrings.first, 'lib/l10n/app_en_US.arb');
|
||||
expect(generator.arbPathStrings.first, 'lib/l10n/app_en.arb');
|
||||
expect(generator.arbPathStrings.elementAt(1), 'lib/l10n/app_es.arb');
|
||||
expect(generator.arbPathStrings.elementAt(2), 'lib/l10n/app_zh.arb');
|
||||
}
|
||||
|
@ -583,6 +583,32 @@ void main() {
|
|||
'should fail'
|
||||
);
|
||||
});
|
||||
|
||||
test('throws when the base locale does not exist', () {
|
||||
final Directory l10nDirectory = fs.currentDirectory.childDirectory('lib').childDirectory('l10n')
|
||||
..createSync(recursive: true);
|
||||
l10nDirectory.childFile('app_en_US.arb')
|
||||
.writeAsStringSync(singleMessageArbFileString);
|
||||
|
||||
try {
|
||||
final LocalizationsGenerator generator = LocalizationsGenerator(fs);
|
||||
generator.initialize(
|
||||
l10nDirectoryPath: defaultArbPathString,
|
||||
templateArbFileName: 'app_en_US.arb',
|
||||
outputFileString: defaultOutputFileString,
|
||||
classNameString: defaultClassNameString,
|
||||
);
|
||||
generator.loadResources();
|
||||
} on L10nException catch (e) {
|
||||
expect(e.message, contains('Arb file for a fallback, en, does not exist'));
|
||||
return;
|
||||
}
|
||||
|
||||
fail(
|
||||
'Since en_US.arb is specified, but en.arb is not, '
|
||||
'the tool should throw an error.'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
group('generateCode', () {
|
||||
|
|
Loading…
Reference in a new issue