From 3e4bf5757dad5acc5482a8a0e53b2ab3bda7b326 Mon Sep 17 00:00:00 2001 From: Shi-Hao Hong Date: Wed, 6 Nov 2019 12:52:03 -0800 Subject: [PATCH] Update Stocks example using i18n tool (#44223) * Use l10n tool to generate stocks i18n files * Rename *_en_EN.arb to *_en_US.arb * Fix l10n script --- analysis_options.yaml | 2 +- dev/tools/localization/gen_l10n.dart | 6 +- ...ck_messages_all.dart => messages_all.dart} | 28 ++-- ...k_messages_en.dart => messages_en_US.dart} | 18 +-- ...k_messages_es.dart => messages_es_ES.dart} | 18 +-- examples/stocks/lib/i18n/regenerate.md | 43 +++--- examples/stocks/lib/i18n/stock_strings.dart | 124 ++++++++++++++++++ .../i18n/{stocks_en.arb => stocks_en_US.arb} | 0 .../i18n/{stocks_es.arb => stocks_es_ES.arb} | 0 examples/stocks/lib/main.dart | 27 +--- examples/stocks/lib/stock_home.dart | 3 +- examples/stocks/lib/stock_strings.dart | 53 -------- 12 files changed, 188 insertions(+), 134 deletions(-) rename examples/stocks/lib/i18n/{stock_messages_all.dart => messages_all.dart} (64%) rename examples/stocks/lib/i18n/{stock_messages_en.dart => messages_en_US.dart} (51%) rename examples/stocks/lib/i18n/{stock_messages_es.dart => messages_es_ES.dart} (51%) create mode 100644 examples/stocks/lib/i18n/stock_strings.dart rename examples/stocks/lib/i18n/{stocks_en.arb => stocks_en_US.arb} (100%) rename examples/stocks/lib/i18n/{stocks_es.arb => stocks_es_ES.arb} (100%) delete mode 100644 examples/stocks/lib/stock_strings.dart diff --git a/analysis_options.yaml b/analysis_options.yaml index 1b7d3ffeb0..3989e50e6d 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -36,7 +36,7 @@ analyzer: - "bin/cache/**" # the following two are relative to the stocks example and the flutter package respectively # see https://github.com/dart-lang/sdk/issues/28463 - - "lib/i18n/stock_messages_*.dart" + - "lib/i18n/messages_*.dart" - "lib/src/http/**" linter: diff --git a/dev/tools/localization/gen_l10n.dart b/dev/tools/localization/gen_l10n.dart index b0e0d4e0f4..22f768e106 100644 --- a/dev/tools/localization/gen_l10n.dart +++ b/dev/tools/localization/gen_l10n.dart @@ -99,7 +99,7 @@ class _@classNameDelegate extends LocalizationsDelegate<@className> { Future<@className> load(Locale locale) => @className.load(locale); @override - bool isSupported(Locale locale) => [@supportedLanguageCodes].contains(locale.languageCode); + bool isSupported(Locale locale) => [@supportedLanguageCodes].contains(locale.languageCode); @override bool shouldReload(_@classNameDelegate old) => false; @@ -236,7 +236,7 @@ String genPluralMethod(Map bundle, String key) { } String genSupportedLocaleProperty(Set supportedLocales) { - const String prefix = 'static const List supportedLocales = [ \n Locale('''; + const String prefix = 'static const List supportedLocales = [\n Locale('''; const String suffix = '),\n ];'; String resultingProperty = prefix; @@ -289,7 +289,7 @@ bool _isDirectoryReadableAndWritable(String statString) { String _importFilePath(String path, String fileName) { final String replaceLib = path.replaceAll('lib/', ''); - return '$replaceLib/$fileName.dart'; + return '$replaceLib/$fileName'; } Future main(List args) async { diff --git a/examples/stocks/lib/i18n/stock_messages_all.dart b/examples/stocks/lib/i18n/messages_all.dart similarity index 64% rename from examples/stocks/lib/i18n/stock_messages_all.dart rename to examples/stocks/lib/i18n/messages_all.dart index 77ebdf91e5..867afc7704 100644 --- a/examples/stocks/lib/i18n/stock_messages_all.dart +++ b/examples/stocks/lib/i18n/messages_all.dart @@ -2,28 +2,34 @@ // 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'; -// ignore: implementation_imports import 'package:intl/src/intl_helpers.dart'; -import 'stock_messages_en.dart' as messages_en; -import 'stock_messages_es.dart' as messages_es; +import 'messages_en_US.dart' as messages_en_us; +import 'messages_es_ES.dart' as messages_es_es; typedef Future LibraryLoader(); Map _deferredLibraries = { - 'en': () => new Future.value(null), - 'es': () => new Future.value(null), + 'en_US': () => new Future.value(null), + 'es_ES': () => new Future.value(null), }; -MessageLookupByLibrary _findExact(localeName) { +MessageLookupByLibrary _findExact(String localeName) { switch (localeName) { - case 'en': - return messages_en.messages; - case 'es': - return messages_es.messages; + case 'en_US': + return messages_en_us.messages; + case 'es_ES': + return messages_es_es.messages; default: return null; } @@ -53,7 +59,7 @@ bool _messagesExistFor(String locale) { } } -MessageLookupByLibrary _findGeneratedMessagesFor(locale) { +MessageLookupByLibrary _findGeneratedMessagesFor(String locale) { var actualLocale = Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null); if (actualLocale == null) return null; diff --git a/examples/stocks/lib/i18n/stock_messages_en.dart b/examples/stocks/lib/i18n/messages_en_US.dart similarity index 51% rename from examples/stocks/lib/i18n/stock_messages_en.dart rename to examples/stocks/lib/i18n/messages_en_US.dart index 258504d4f5..fedb57ca28 100644 --- a/examples/stocks/lib/i18n/stock_messages_en.dart +++ b/examples/stocks/lib/i18n/messages_en_US.dart @@ -1,26 +1,28 @@ // DO NOT EDIT. This is code generated via package:intl/generate_localized.dart -// This is a library that provides messages for a en locale. All the +// 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(); -// ignore: unused_element -final _keepAnalysisHappy = Intl.defaultLocale; - -// ignore: non_constant_identifier_names -typedef MessageIfAbsent(String message_str, List args); +typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { - get localeName => 'en'; + String get localeName => 'en_US'; final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "market" : MessageLookupByLibrary.simpleMessage("MARKET"), "portfolio" : MessageLookupByLibrary.simpleMessage("PORTFOLIO"), - "title" : MessageLookupByLibrary.simpleMessage("Stocks"), + "title" : MessageLookupByLibrary.simpleMessage("Stocks") }; } diff --git a/examples/stocks/lib/i18n/stock_messages_es.dart b/examples/stocks/lib/i18n/messages_es_ES.dart similarity index 51% rename from examples/stocks/lib/i18n/stock_messages_es.dart rename to examples/stocks/lib/i18n/messages_es_ES.dart index 136be0bde5..b2c0fd3809 100644 --- a/examples/stocks/lib/i18n/stock_messages_es.dart +++ b/examples/stocks/lib/i18n/messages_es_ES.dart @@ -1,26 +1,28 @@ // DO NOT EDIT. This is code generated via package:intl/generate_localized.dart -// This is a library that provides messages for a es locale. All the +// 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(); -// ignore: unused_element -final _keepAnalysisHappy = Intl.defaultLocale; - -// ignore: non_constant_identifier_names -typedef MessageIfAbsent(String message_str, List args); +typedef String MessageIfAbsent(String messageStr, List args); class MessageLookup extends MessageLookupByLibrary { - get localeName => 'es'; + String get localeName => 'es_ES'; final messages = _notInlinedMessages(_notInlinedMessages); static _notInlinedMessages(_) => { "market" : MessageLookupByLibrary.simpleMessage("MERCADO"), "portfolio" : MessageLookupByLibrary.simpleMessage("CARTERA"), - "title" : MessageLookupByLibrary.simpleMessage("Acciones"), + "title" : MessageLookupByLibrary.simpleMessage("Acciones") }; } diff --git a/examples/stocks/lib/i18n/regenerate.md b/examples/stocks/lib/i18n/regenerate.md index 897d61bcc7..b9ca8aa6a1 100644 --- a/examples/stocks/lib/i18n/regenerate.md +++ b/examples/stocks/lib/i18n/regenerate.md @@ -1,33 +1,26 @@ -## Regenerating the i18n files +# Regenerating the i18n files -The files in this directory are based on ../lib/stock_strings.dart -which defines all of the localizable strings used by the stocks -app. The stocks app uses -the [Dart `intl` package](https://github.com/dart-lang/intl). +The files in this directory are used to generate `stock_strings.dart`, which +is used by the stocks application to look up localized message strings. The +stocks app uses the [Dart `intl` package](https://github.com/dart-lang/intl). Rebuilding everything requires two steps. -With the `examples/stocks` as the current directory, generate -`intl_messages.arb` from `lib/stock_strings.dart`: -``` -flutter pub pub run intl_translation:extract_to_arb --output-dir=lib/i18n lib/stock_strings.dart -``` -The `intl_messages.arb` file is a JSON format map with one entry for -each `Intl.message()` function defined in `stock_strings.dart`. This -file was used to create the English and Spanish localizations, -`stocks_en.arb` and `stocks_es.arb`. The `intl_messages.arb` wasn't -checked into the repository, since it only serves as a template for -the other `.arb` files. +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) +for more info. +2. With `examples/stocks` as the current directory, generate a +`messages_.dart` for each `stocks_.arb` file, +`messages_all.dart`, and `stock_strings.dart` with the following command: -With the `examples/stocks` as the current directory, generate a -`stock_messages_.dart` for each `stocks_.arb` file and -`stock_messages_all.dart`, which imports all of the messages files: -``` -flutter pub pub run intl_translation:generate_from_arb --output-dir=lib/i18n \ - --generated-file-prefix=stock_ --no-use-deferred-loading lib/*.dart lib/i18n/stocks_*.arb +```dart +dart ${FLUTTER_PATH}/dev/tools/localization/gen_l10n.dart --arb-dir=lib/i18n + --template-arb-file=stocks_en_EN.arb --output-localization-file=stock_strings.dart + --output-class=StockStrings ``` -The `StockStrings` class uses the generated `initializeMessages()` -function (`stock_messages_all.dart`) to load the localized messages -and `Intl.message()` to look them up. +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. diff --git a/examples/stocks/lib/i18n/stock_strings.dart b/examples/stocks/lib/i18n/stock_strings.dart new file mode 100644 index 0000000000..a86de80b04 --- /dev/null +++ b/examples/stocks/lib/i18n/stock_strings.dart @@ -0,0 +1,124 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; +import 'package:flutter_localizations/flutter_localizations.dart'; +import 'package:intl/intl.dart'; + +import 'messages_all.dart'; + +/// Callers can lookup localized strings with an instance of StockStrings returned +/// by `StockStrings.of(context)`. +/// +/// Applications need to include `StockStrings.delegate()` in their app's +/// localizationDelegates list, and the locales they support in the app's +/// supportedLocales list. For example: +/// +/// ``` +/// import 'i18n/stock_strings.dart'; +/// +/// return MaterialApp( +/// localizationsDelegates: StockStrings.localizationsDelegates, +/// supportedLocales: StockStrings.supportedLocales, +/// home: MyApplicationHome(), +/// ); +/// ``` +/// +/// ## iOS Applications +/// +/// iOS applications define key application metadata, including supported +/// locales, in an Info.plist file that is built into the application bundle. +/// To configure the locales supported by your app, you’ll need to edit this +/// file. +/// +/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file. +/// Then, in the Project Navigator, open the Info.plist file under the Runner +/// project’s Runner folder. +/// +/// Next, select the Information Property List item, select Add Item from the +/// Editor menu, then select Localizations from the pop-up menu. +/// +/// Select and expand the newly-created Localizations item then, for each +/// locale your application supports, add a new item and select the locale +/// 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 = locale.toString(); + + final String _localeName; + + static Future load(Locale locale) { + return initializeMessages(locale.toString()) + .then((void _) => StockStrings(locale)); + } + + static StockStrings of(BuildContext context) { + return Localizations.of(context, StockStrings); + } + + static const LocalizationsDelegate delegate = _StockStringsDelegate(); + + /// A list of this localizations delegate along with the default localizations + /// delegates. + /// + /// Returns a list of localizations delegates containing this delegate along with + /// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate, + /// and GlobalWidgetsLocalizations.delegate. + static const List> localizationsDelegates = >[ + delegate, + GlobalMaterialLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + ]; + + /// A list of this localizations delegate's supported locales. + static const List supportedLocales = [ + Locale('en', 'US'), + Locale('es', 'ES'), + ]; + + String title() { + return Intl.message( + r'Stocks', + locale: _localeName, + name: 'title', + desc: 'Title for the Stocks application', + args: [] + ); + } + + String market() { + return Intl.message( + r'MARKET', + locale: _localeName, + name: 'market', + desc: 'Label for the Market tab', + args: [] + ); + } + + String portfolio() { + return Intl.message( + r'PORTFOLIO', + locale: _localeName, + name: 'portfolio', + desc: 'Label for the Portfolio tab', + args: [] + ); + } + +} + +class _StockStringsDelegate extends LocalizationsDelegate { + const _StockStringsDelegate(); + + @override + Future load(Locale locale) => StockStrings.load(locale); + + @override + bool isSupported(Locale locale) => ['en', 'es'].contains(locale.languageCode); + + @override + bool shouldReload(_StockStringsDelegate old) => false; +} diff --git a/examples/stocks/lib/i18n/stocks_en.arb b/examples/stocks/lib/i18n/stocks_en_US.arb similarity index 100% rename from examples/stocks/lib/i18n/stocks_en.arb rename to examples/stocks/lib/i18n/stocks_en_US.arb diff --git a/examples/stocks/lib/i18n/stocks_es.arb b/examples/stocks/lib/i18n/stocks_es_ES.arb similarity index 100% rename from examples/stocks/lib/i18n/stocks_es.arb rename to examples/stocks/lib/i18n/stocks_es_ES.arb diff --git a/examples/stocks/lib/main.dart b/examples/stocks/lib/main.dart index 9a7082bad5..04075377b5 100644 --- a/examples/stocks/lib/main.dart +++ b/examples/stocks/lib/main.dart @@ -4,8 +4,6 @@ library stocks; -import 'dart:async'; - import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show debugPaintSizeEnabled, @@ -13,26 +11,14 @@ import 'package:flutter/rendering.dart' show debugPaintLayerBordersEnabled, debugPaintPointersEnabled, debugRepaintRainbowEnabled; -import 'package:flutter_localizations/flutter_localizations.dart'; +import 'i18n/stock_strings.dart'; import 'stock_data.dart'; import 'stock_home.dart'; import 'stock_settings.dart'; -import 'stock_strings.dart'; import 'stock_symbol_viewer.dart'; import 'stock_types.dart'; -class _StocksLocalizationsDelegate extends LocalizationsDelegate { - @override - Future load(Locale locale) => StockStrings.load(locale); - - @override - bool isSupported(Locale locale) => locale.languageCode == 'es' || locale.languageCode == 'en'; - - @override - bool shouldReload(_StocksLocalizationsDelegate old) => false; -} - class StocksApp extends StatefulWidget { @override StocksAppState createState() => StocksAppState(); @@ -108,15 +94,8 @@ class StocksAppState extends State { return MaterialApp( title: 'Stocks', theme: theme, - localizationsDelegates: >[ - _StocksLocalizationsDelegate(), - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - ], - supportedLocales: const [ - Locale('en', 'US'), - Locale('es', 'ES'), - ], + localizationsDelegates: StockStrings.localizationsDelegates, + supportedLocales: StockStrings.supportedLocales, debugShowMaterialGrid: _configuration.debugShowGrid, showPerformanceOverlay: _configuration.showPerformanceOverlay, showSemanticsDebugger: _configuration.showSemanticsDebugger, diff --git a/examples/stocks/lib/stock_home.dart b/examples/stocks/lib/stock_home.dart index be60a752ad..545c7e51c4 100644 --- a/examples/stocks/lib/stock_home.dart +++ b/examples/stocks/lib/stock_home.dart @@ -6,9 +6,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart' show debugDumpRenderTree, debugDumpLayerTree, debugDumpSemanticsTree, DebugSemanticsDumpOrder; import 'package:flutter/scheduler.dart' show timeDilation; import 'package:flutter/gestures.dart' show DragStartBehavior; + +import 'i18n/stock_strings.dart'; import 'stock_data.dart'; import 'stock_list.dart'; -import 'stock_strings.dart'; import 'stock_symbol_viewer.dart'; import 'stock_types.dart'; diff --git a/examples/stocks/lib/stock_strings.dart b/examples/stocks/lib/stock_strings.dart deleted file mode 100644 index ed1422476e..0000000000 --- a/examples/stocks/lib/stock_strings.dart +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright 2015 The Chromium 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:intl/intl.dart'; -import 'package:flutter/widgets.dart'; - -import 'i18n/stock_messages_all.dart'; - -// Information about how this file relates to i18n/stock_messages_all.dart and how the i18n files -// were generated can be found in i18n/regenerate.md. - -class StockStrings { - StockStrings(Locale locale) : _localeName = locale.toString(); - - final String _localeName; - - static Future load(Locale locale) { - return initializeMessages(locale.toString()) - .then((Object _) { - return StockStrings(locale); - }); - } - - static StockStrings of(BuildContext context) { - return Localizations.of(context, StockStrings); - } - - String title() { - return Intl.message( - '', - name: 'title', - desc: 'Title for the Stocks application', - locale: _localeName, - ); - } - - String market() => Intl.message( - 'MARKET', - name: 'market', - desc: 'Label for the Market tab', - locale: _localeName, - ); - - String portfolio() => Intl.message( - 'PORTFOLIO', - name: 'portfolio', - desc: 'Label for the Portfolio tab', - locale: _localeName, - ); -}