[examples] migrate Topaz's localized_mod

- Copies localized_mod from topaz/examples/ui
- Renames the example to localized_flutter_app (it's a flutter app with
  no Modular deps)
- Adds stub test targets to build files

Change-Id: If0803b1073d3681f341a4edf90d0a8446920f37b
diff --git a/examples/BUILD.gn b/examples/BUILD.gn
index 0ad0859..f4b74e6 100644
--- a/examples/BUILD.gn
+++ b/examples/BUILD.gn
@@ -5,6 +5,7 @@
 group("examples") {
   deps = [
     "hello_experiences",
+    "localized_flutter_app",
   ]
 }
 
@@ -20,6 +21,7 @@
   testonly = true
 
   deps = [
+    "localized_flutter_app:localized_flutter_app_unittests($host_toolchain)",
     "hello_experiences:hello_experiences_unittests($host_toolchain)",
   ]
 }
diff --git a/examples/localized_flutter_app/BUILD.gn b/examples/localized_flutter_app/BUILD.gn
new file mode 100644
index 0000000..f5364a8
--- /dev/null
+++ b/examples/localized_flutter_app/BUILD.gn
@@ -0,0 +1,37 @@
+# Copyright 2019 The Fuchsia 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("//topaz/runtime/flutter_runner/flutter_app.gni")
+import("//topaz/runtime/dart/flutter_test.gni")
+
+flutter_app("localized_flutter_app") {
+  main_dart = "lib/main.dart"
+  package_name = "localized_flutter_app"
+
+  sources = []
+
+  deps = [
+    "//third_party/dart-pkg/git/flutter/packages/flutter",
+    "//third_party/dart-pkg/git/flutter/packages/flutter_localizations",
+    "//third_party/dart/third_party/pkg/intl",
+    "//topaz/public/dart/widgets:lib.widgets",
+  ]
+
+  meta = [
+    {
+      path = rebase_path("meta/localized_flutter_app.cmx")
+      dest = "localized_flutter_app.cmx"
+    },
+  ]
+}
+
+flutter_test("localized_flutter_app_unittests") {
+  sources = [
+    "sample_test.dart",
+  ]
+
+  deps = [
+   "//third_party/dart-pkg/pub/test",
+  ]
+}
diff --git a/examples/localized_flutter_app/OWNERS b/examples/localized_flutter_app/OWNERS
new file mode 100644
index 0000000..71bb700
--- /dev/null
+++ b/examples/localized_flutter_app/OWNERS
@@ -0,0 +1,4 @@
+fmil@google.com
+kpozin@google.com
+shayba@google.com
+viktard@google.com
diff --git a/examples/localized_flutter_app/README.md b/examples/localized_flutter_app/README.md
new file mode 100644
index 0000000..7ea2893
--- /dev/null
+++ b/examples/localized_flutter_app/README.md
@@ -0,0 +1,10 @@
+# Localized Mod
+
+This is an example of a simple Flutter application that can display localized
+strings in several supported locales. It uses
+[`dart:intl_translation`](https://pub.dartlang.org/packages/intl_translation)
+for extracting localized strings from code and for generating the
+localization-loading classes.
+
+This is intended as a testbed for any efforts to integrate Fuchsia's Gerrit with
+a translation pipeline.
diff --git a/examples/localized_flutter_app/analysis_options.yaml b/examples/localized_flutter_app/analysis_options.yaml
new file mode 100644
index 0000000..bebf512
--- /dev/null
+++ b/examples/localized_flutter_app/analysis_options.yaml
@@ -0,0 +1,5 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+include: ../../analysis_options.yaml
diff --git a/examples/localized_flutter_app/lib/localization/README.md b/examples/localized_flutter_app/lib/localization/README.md
new file mode 100644
index 0000000..e608e3d
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/README.md
@@ -0,0 +1,46 @@
+# `localized_mod/lib/localization`
+
+Most of the files in this directory were generated. Here's how:
+
+## `intl_messages.arb`
+
+This is generated from `localized_mod/localized_mod_strings.dart` using
+
+```shell
+localized_mod$ $FUCHSIA/third_party/dart-pkg/git/flutter/bin/flutter \
+packages pub run \
+intl_translation:extract_to_arb \
+--output-dir=lib/localization \
+lib/localized_mod_strings.dart
+```
+
+This file should be checked in.
+
+## `intl_messages_*.arb`
+
+These are the result of _manually_ translating `intl_messages.arb` into each
+target locale.
+
+One option for generating these more easily is the
+[Google Translator Toolkit](https://translate.google.com/toolkit/).
+
+In production code, these would be imported from a translation pipeline.
+
+These files should be checked in.
+
+## `messages_*.dart`
+
+These are generated from the `.arb` files. The command is
+
+```shell
+localized_mod$ $FUCHSIA/third_party/dart-pkg/git/flutter/bin/flutter \
+packages pub run \
+intl_translation:generate_from_arb \
+--output-dir=lib/localization \
+lib/localized_mod_strings.dart lib/localization/intl_*.arb
+```
+
+These are checked into the repo _only as a temporary workaround_.
+
+In the future, there should be a GN build rule that will generate these code
+files at build time, so as to not pollute the source tree (FL-162).
diff --git a/examples/localized_flutter_app/lib/localization/intl_messages.arb b/examples/localized_flutter_app/lib/localization/intl_messages.arb
new file mode 100644
index 0000000..750d348
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/intl_messages.arb
@@ -0,0 +1,25 @@
+{
+  "@@last_modified": "2019-01-24T15:29:41.574074",
+  "appTitle": "Localized Mod",
+  "@appTitle": {
+    "description": "Title of the demo application. \"Mod\" is short for \"module\" (can also be translated as \"app\").",
+    "type": "text",
+    "placeholders": {}
+  },
+  "bodyText": "{itemCount,plural, =0{There are no messages.}=1{There is one message.}other{There are {itemCount} messages.}}",
+  "@bodyText": {
+    "description": "How many messages are in the list.",
+    "type": "text",
+    "placeholders": {
+      "itemCount": {
+        "example": 42
+      }
+    }
+  },
+  "footer": "Coming soon: actually reading those messages!",
+  "@footer": {
+    "description": "Footer text of the demo application. Implies that messages cannot currently be read.",
+    "type": "text",
+    "placeholders": {}
+  }
+}
\ No newline at end of file
diff --git a/examples/localized_flutter_app/lib/localization/intl_messages_he.arb b/examples/localized_flutter_app/lib/localization/intl_messages_he.arb
new file mode 100644
index 0000000..45043dd
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/intl_messages_he.arb
@@ -0,0 +1,25 @@
+{
+  "@@locale": "he",
+  "appTitle": "אפליקציה מתורגמת לשפה מקומית",
+  "@appTitle": {
+    "description": "Title of the demo application. \"Mod\" is short for \"module\" (can also be translated as \"app\").",
+    "type": "text",
+    "placeholders": {}
+  },
+  "bodyText": "{itemCount, plural, =0 {אין הודעות.} =1 {יש הודעה אחת.} other {יש {itemCount} הודעות.}}",
+  "@bodyText": {
+    "description": "How many messages are in the list.",
+    "type": "text",
+    "placeholders": {
+      "itemCount": {
+        "example": "42"
+      }
+    }
+  },
+  "footer": "בקרוב: קריאת ההודעות האלה!",
+  "@footer": {
+    "description": "Footer text of the demo application. Implies that messages cannot currently be read.",
+    "type": "text",
+    "placeholders": {}
+  }
+}
\ No newline at end of file
diff --git a/examples/localized_flutter_app/lib/localization/messages_all.dart b/examples/localized_flutter_app/lib/localization/messages_all.dart
new file mode 100755
index 0000000..0fc8910
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_all.dart
@@ -0,0 +1,139 @@
+// 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.
+
+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 'messages_ar-XB.dart' deferred as messages_ar_xb;
+import 'messages_en-XA.dart' deferred as messages_en_xa;
+import 'messages_en-XC.dart' deferred as messages_en_xc;
+import 'messages_he.dart' deferred as messages_he;
+import 'messages_sr-Latn.dart' deferred as messages_sr_latn;
+import 'messages_sr.dart' deferred as messages_sr;
+
+typedef Future<dynamic> LibraryLoader();
+Map<String, LibraryLoader> _deferredLibraries = {
+  'ar_XB': messages_ar_xb.loadLibrary,
+  'en_XA': messages_en_xa.loadLibrary,
+  'en_XC': messages_en_xc.loadLibrary,
+  'sr_Latn': messages_sr_latn.loadLibrary,
+  'he': messages_he.loadLibrary,
+  'sr': messages_sr.loadLibrary,
+};
+
+MessageLookupByLibrary _findExact(localeName) {
+  switch (localeName) {
+    case 'ar_XB':
+      return messages_ar_xb.messages;
+    case 'en_XA':
+      return messages_en_xa.messages;
+    case 'en_XC':
+      return messages_en_xc.messages;
+    case 'sr_Latn':
+      return messages_sr_latn.messages;
+    case 'sr':
+      return messages_sr.messages;
+    case 'he':
+      return messages_he.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) {
+    // ignore: unnecessary_new
+    return new Future.value(false);
+  }
+  var lib = _deferredLibraries[availableLocale];
+  // ignore: unnecessary_new
+  await (lib == null ? new Future.value(false) : lib());
+  // ignore: unnecessary_new
+  initializeInternalMessageLookup(() => new CompositeMessageLookup());
+  messageLookup.addLocale(availableLocale, _findGeneratedMessagesFor);
+  // ignore: unnecessary_new
+  return new Future.value(true);
+}
+
+bool _messagesExistFor(String locale) {
+  try {
+    return _findExact(locale) != null;
+  } catch (e) {
+    return false;
+  }
+}
+
+MessageLookupByLibrary _findGeneratedMessagesFor(locale) {
+  var actualLocale =
+      Intl.verifiedLocale(locale, _messagesExistFor, onFailure: (_) => null);
+  if (actualLocale == null) return null;
+  return _findExact(actualLocale);
+}
+
+/// Turn the JSON template into a string.
+///
+/// We expect one of the following forms for the template.
+/// * null -> null
+/// * String s -> s
+/// * int n -> '${args[n]}'
+/// * List list, one of
+///   * ['Intl.plural', int howMany, (templates for zero, one, ...)]
+///   * ['Intl.gender', String gender, (templates for female, male, other)]
+///   * ['Intl.select', String choice, { 'case' : template, ...} ]
+///   * ['text alternating with ', 0 , ' indexes in the argument list']
+String evaluateJsonTemplate(Object input, List<dynamic> args) {
+  if (input == null) return null;
+  if (input is String) return input;
+  if (input is int) {
+    return "${args[input]}";
+  }
+
+  List<dynamic> template = input;
+  var messageName = template.first;
+  if (messageName == "Intl.plural") {
+    var howMany = args[template[1]];
+    return evaluateJsonTemplate(
+        Intl.pluralLogic(howMany,
+            zero: template[2],
+            one: template[3],
+            two: template[4],
+            few: template[5],
+            many: template[6],
+            other: template[7]),
+        args);
+  }
+  if (messageName == "Intl.gender") {
+    var gender = args[template[1]];
+    return evaluateJsonTemplate(
+        Intl.genderLogic(gender,
+            female: template[2], male: template[3], other: template[4]),
+        args);
+  }
+  if (messageName == "Intl.select") {
+    var select = args[template[1]];
+    var choices = template[2];
+    return evaluateJsonTemplate(Intl.selectLogic(select, choices), args);
+  }
+
+  // If we get this far, then we are a basic interpolation, just strings and
+  // ints.
+  // ignore: unnecessary_new
+  var output = new StringBuffer();
+  for (var entry in template) {
+    if (entry is int) {
+      output.write("${args[entry]}");
+    } else {
+      output.write("$entry");
+    }
+  }
+  return output.toString();
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_ar-XB.dart b/examples/localized_flutter_app/lib/localization/messages_ar-XB.dart
new file mode 100755
index 0000000..2945433
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_ar-XB.dart
@@ -0,0 +1,34 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a ar_XB locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+// ignore_for_file: unnecessary_brace_in_string_interps
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+import 'dart:convert';
+import 'messages_all.dart' show evaluateJsonTemplate;
+
+// ignore: unnecessary_new
+final messages = new MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List<dynamic> args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'ar_XB';
+
+  String evaluateMessage(translation, List<dynamic> args) {
+    return evaluateJsonTemplate(translation, args);
+  }
+
+  var _messages;
+  // ignore: unnecessary_new
+  get messages => _messages ??= new JsonDecoder().convert(messageText);
+  static final messageText = r'''
+{"appTitle":"‏‮Localized‬‏ ‏‮Mod‬‏","bodyText":["Intl.plural",0,"‏‮There‬‏ ‏‮are‬‏ ‏‮no‬‏ ‏‮messages‬‏.","‏‮There‬‏ ‏‮is‬‏ ‏‮one‬‏ ‏‮message‬‏.",["‏‮There‬‏ ‏‮are‬‏ ",0," ‏‮messages‬‏."],["‏‮There‬‏ ‏‮are‬‏ ",0," ‏‮messages‬‏."],["‏‮There‬‏ ‏‮are‬‏ ",0," ‏‮messages‬‏."],["‏‮There‬‏ ‏‮are‬‏ ",0," ‏‮messages‬‏."]],"footer":"‏‮Coming‬‏ ‏‮soon‬‏: ‏‮actually‬‏ ‏‮reading‬‏ ‏‮those‬‏ ‏‮messages‬‏!"}''';
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_en-XA.dart b/examples/localized_flutter_app/lib/localization/messages_en-XA.dart
new file mode 100755
index 0000000..fdd77f1
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_en-XA.dart
@@ -0,0 +1,34 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a en_XA locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+// ignore_for_file: unnecessary_brace_in_string_interps
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+import 'dart:convert';
+import 'messages_all.dart' show evaluateJsonTemplate;
+
+// ignore: unnecessary_new
+final messages = new MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List<dynamic> args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'en_XA';
+
+  String evaluateMessage(translation, List<dynamic> args) {
+    return evaluateJsonTemplate(translation, args);
+  }
+
+  var _messages;
+  // ignore: unnecessary_new
+  get messages => _messages ??= new JsonDecoder().convert(messageText);
+  static final messageText = r'''
+{"appTitle":"[Ļöçåļîžéð Möð one two]","bodyText":["Intl.plural",0,"[Ţĥéŕé åŕé ñö méššåĝéš. one two three four five]","[Ţĥéŕé îš öñé méššåĝé. one two three four five]",null,null,null,["[Ţĥéŕé åŕé ᐅ",0,"ᐊ méššåĝéš. one two three four five]"]],"footer":"[Çömîñĝ šööñ: åçţûåļļý ŕéåðîñĝ ţĥöšé méššåĝéš¡ one two three four five six seven eight nine]"}''';
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_en-XC.dart b/examples/localized_flutter_app/lib/localization/messages_en-XC.dart
new file mode 100755
index 0000000..dd7a49f
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_en-XC.dart
@@ -0,0 +1,34 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a en_XC locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+// ignore_for_file: unnecessary_brace_in_string_interps
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+import 'dart:convert';
+import 'messages_all.dart' show evaluateJsonTemplate;
+
+// ignore: unnecessary_new
+final messages = new MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List<dynamic> args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'en_XC';
+
+  String evaluateMessage(translation, List<dynamic> args) {
+    return evaluateJsonTemplate(translation, args);
+  }
+
+  var _messages;
+  // ignore: unnecessary_new
+  get messages => _messages ??= new JsonDecoder().convert(messageText);
+  static final messageText = r'''
+{"appTitle":"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‏‏‏‏‏‎‏‏‎‎‏‏‏‏‏‎‏‎‏‎‏‎‏‎‎‎‏‎‏‎‎‏‎‎‎‏‏‎‏‏‏‎‎‎‎‏‎‎‎‎‎‏‏‏‎‎‎‎‏‎‎‏‏‎‎‎Localized Mod‎‏‎‎‏‎","bodyText":["Intl.plural",0,"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎There are no messages.‎‏‎‎‏‎","‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎There is one message.‎‏‎‎‏‎",null,null,null,["‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‎‎‏‏‏‎‎‏‎‎‎‎‏‏‎‏‎‏‏‎‎‎‎‎‏‏‎‏‏‏‏‏‏‎‏‏‎‎‏‎‏‎‏‏‎‎‎‎‏‎‎‎‏‎‎‏‎‎‏‎‎There are ‎‏‎‎‏‏‎",0,"‎‏‎‎‏‏‏‎ messages.‎‏‎‎‏‎"]],"footer":"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‏‎‎‎‎‏‏‏‎‎‏‎‏‏‏‏‎‏‏‏‎‎‎‏‎‎‏‎‏‏‏‎‏‏‎‏‎‎‎‏‎‏‎‏‎‎‎‎‎‎‎‎‎‏‎‎‏‏‎‎‏‎‏‏‎‎‏‎‏‎‏‎‎‎‎‎‎‎‏‎Coming soon: actually reading those messages!‎‏‎‎‏‎"}''';
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_he.dart b/examples/localized_flutter_app/lib/localization/messages_he.dart
new file mode 100644
index 0000000..0246077
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_he.dart
@@ -0,0 +1,29 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a he locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+
+// ignore: unnecessary_new
+final messages = MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'he';
+
+  static m0(itemCount) => "${Intl.plural(itemCount, zero: 'אין הודעות.', one: 'יש הודעה אחת.', other: 'יש ${itemCount} הודעות.')}";
+
+  final messages = _notInlinedMessages(_notInlinedMessages);
+  static _notInlinedMessages(_) => <String, Function> {
+    "appTitle" : MessageLookupByLibrary.simpleMessage("אפליקציה מתורגמת לשפה מקומית"),
+    "bodyText" : m0,
+    "footer" : MessageLookupByLibrary.simpleMessage("בקרוב: קריאת ההודעות האלה!")
+  };
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_sr-Latn.dart b/examples/localized_flutter_app/lib/localization/messages_sr-Latn.dart
new file mode 100755
index 0000000..8e0d562
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_sr-Latn.dart
@@ -0,0 +1,34 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a sr_Latn locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+// ignore_for_file: unnecessary_brace_in_string_interps
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+import 'dart:convert';
+import 'messages_all.dart' show evaluateJsonTemplate;
+
+// ignore: unnecessary_new
+final messages = new MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List<dynamic> args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'sr_Latn';
+
+  String evaluateMessage(translation, List<dynamic> args) {
+    return evaluateJsonTemplate(translation, args);
+  }
+
+  var _messages;
+  // ignore: unnecessary_new
+  get messages => _messages ??= new JsonDecoder().convert(messageText);
+  static final messageText = r'''
+{"appTitle":"Lokalizovani mod","bodyText":["Intl.plural",0,"Nema poruka.","Jedna poruka.",null,[0," poruke."],null,[0," poruka."]],"footer":"Dolazi uskoro: zapravo čitanje ovih poruka!"}''';
+}
diff --git a/examples/localized_flutter_app/lib/localization/messages_sr.dart b/examples/localized_flutter_app/lib/localization/messages_sr.dart
new file mode 100755
index 0000000..c7aa735
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localization/messages_sr.dart
@@ -0,0 +1,34 @@
+// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
+// This is a library that provides messages for a sr locale. All the
+// messages from the main program should be duplicated here with the same
+// function name.
+
+// ignore_for_file: unnecessary_brace_in_string_interps
+
+import 'package:intl/intl.dart';
+import 'package:intl/message_lookup_by_library.dart';
+import 'dart:convert';
+import 'messages_all.dart' show evaluateJsonTemplate;
+
+// ignore: unnecessary_new
+final messages = new MessageLookup();
+
+// ignore: unused_element
+final _keepAnalysisHappy = Intl.defaultLocale;
+
+// ignore: non_constant_identifier_names
+typedef MessageIfAbsent(String message_str, List<dynamic> args);
+
+class MessageLookup extends MessageLookupByLibrary {
+  get localeName => 'sr';
+
+  String evaluateMessage(translation, List<dynamic> args) {
+    return evaluateJsonTemplate(translation, args);
+  }
+
+  var _messages;
+  // ignore: unnecessary_new
+  get messages => _messages ??= new JsonDecoder().convert(messageText);
+  static final messageText = r'''
+{"appTitle":"Локализовани мод","bodyText":["Intl.plural",0,"Нема порука.","Једна порука.",null,[0," поруке."],null,[0," порука."]],"footer":"Долази ускоро: заправо читање ових порука!"}''';
+}
diff --git a/examples/localized_flutter_app/lib/localized_mod_localizations_delegate.dart b/examples/localized_flutter_app/lib/localized_mod_localizations_delegate.dart
new file mode 100644
index 0000000..df79eea
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localized_mod_localizations_delegate.dart
@@ -0,0 +1,50 @@
+// Copyright 2019 The Fuchsia 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 'dart:ui' show Locale;
+
+import 'package:flutter/material.dart';
+import 'package:flutter_localizations/flutter_localizations.dart';
+import 'package:intl/intl.dart';
+
+import 'localization/messages_all.dart' as messages_all;
+import 'supported_locales.dart';
+
+/// A [LocalizationsDelegate] for Localized Mod that connects Flutter's
+/// localization updates to the `intl` library's translation loading.
+///
+/// Every mod that uses localized strings needs to have a
+/// `LocalizationsDelegate`.
+class LocalizedModLocalizationsDelegate extends LocalizationsDelegate<void> {
+  /// Loads the translations for the given locale.
+  static Future<void> loadLocale(Locale locale) async {
+    final String name =
+        (locale.countryCode == null || locale.countryCode.isEmpty)
+            ? locale.languageCode
+            : locale.toString();
+    final String localeName = Intl.canonicalizedLocale(name);
+    await messages_all.initializeMessages(localeName);
+    Intl.defaultLocale = localeName;
+  }
+
+  const LocalizedModLocalizationsDelegate();
+
+  @override
+  Future<void> load(Locale locale) => loadLocale(locale);
+
+  @override
+  bool shouldReload(LocalizedModLocalizationsDelegate _) => false;
+
+  @override
+  bool isSupported(Locale locale) => supportedLocales.contains(locale);
+}
+
+const List<LocalizationsDelegate> allLocalizationsDelegates = [
+  // Delegate containing all app-level messages
+  LocalizedModLocalizationsDelegate(),
+  // Flutter-provided delegates for Flutter UI messages
+  GlobalMaterialLocalizations.delegate,
+  GlobalWidgetsLocalizations.delegate,
+];
diff --git a/examples/localized_flutter_app/lib/localized_mod_strings.dart b/examples/localized_flutter_app/lib/localized_mod_strings.dart
new file mode 100644
index 0000000..b197e13
--- /dev/null
+++ b/examples/localized_flutter_app/lib/localized_mod_strings.dart
@@ -0,0 +1,37 @@
+// Copyright 2019 The Fuchsia 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 'package:intl/intl.dart';
+
+// ignore: avoid_classes_with_only_static_members
+
+/// A container for strings used by Localized Mod.
+/// If the app were larger, there would be a separate __Strings class for each
+/// package that needed one.
+class LocalizedModStrings {
+  static String get appTitle => Intl.message(
+        'Localized Mod',
+        name: 'appTitle',
+        desc: 'Title of the demo application. '
+            '"Mod" is short for "module" (can also be translated as "app").',
+      );
+
+  static String bodyText(int itemCount) => Intl.plural(
+        itemCount,
+        zero: 'There are no messages.',
+        one: 'There is one message.',
+        other: 'There are $itemCount messages.',
+        name: 'bodyText',
+        args: [itemCount],
+        desc: 'How many messages are in the list.',
+        examples: const {'itemCount': 42},
+      );
+
+  static String get footer => Intl.message(
+        'Coming soon: actually reading those messages!',
+        name: 'footer',
+        desc: 'Footer text of the demo application. '
+            'Implies that messages cannot currently be read.',
+      );
+}
diff --git a/examples/localized_flutter_app/lib/main.dart b/examples/localized_flutter_app/lib/main.dart
new file mode 100644
index 0000000..2989ea5
--- /dev/null
+++ b/examples/localized_flutter_app/lib/main.dart
@@ -0,0 +1,81 @@
+// Copyright 2019 The Fuchsia 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:math';
+
+import 'package:flutter/material.dart';
+import 'package:lib.widgets/model.dart';
+
+import 'localized_mod_localizations_delegate.dart' as localizations_delegate;
+import 'localized_mod_strings.dart';
+import 'supported_locales.dart' as supported_locales;
+
+void main() {
+  final providers = Providers()..provideValue(CurrentLocale(null));
+
+  runApp(ProviderNode(providers: providers, child: LocalizedMod()));
+  // TODO(FL-157): Receive i18n settings from the View interface.
+}
+
+/// The main application widget for Localized Mod.
+class LocalizedMod extends StatelessWidget {
+  @override
+  Widget build(BuildContext context) {
+    return Provide<CurrentLocale>(
+        builder: (BuildContext context, Widget child, currentLocale) =>
+            MaterialApp(
+              onGenerateTitle: (BuildContext context) =>
+                  LocalizedModStrings.appTitle,
+              localizationsDelegates:
+                  localizations_delegate.allLocalizationsDelegates,
+              supportedLocales: supported_locales.supportedLocales,
+              locale: currentLocale.value,
+              home: _LocalizedModHome(Random().nextInt(100)),
+            ));
+  }
+}
+
+/// The root layout widget for Localized Mod.
+class _LocalizedModHome extends StatelessWidget {
+  static final List<DropdownMenuItem<Locale>> dropdownItems = supported_locales
+      .supportedLocales
+      .map((Locale locale) =>
+          DropdownMenuItem(value: locale, child: Text(locale.toString())))
+      .toList();
+
+  final int messageCount;
+
+  const _LocalizedModHome(this.messageCount) : super();
+
+  @override
+  Widget build(BuildContext context) {
+    return Scaffold(
+        appBar: AppBar(
+          title: Text(LocalizedModStrings.appTitle),
+        ),
+        body: Center(
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.spaceBetween,
+            children: [
+              DropdownButton<Locale>(
+                  value: Localizations.localeOf(context),
+                  items: dropdownItems,
+                  onChanged: (newValue) =>
+                      Provide.value<CurrentLocale>(context).value = newValue),
+              Container(
+                  margin: EdgeInsets.symmetric(vertical: 40),
+                  child: Text(LocalizedModStrings.bodyText(messageCount))),
+              Container(
+                  margin: EdgeInsets.symmetric(vertical: 40),
+                  child: Text(LocalizedModStrings.footer)),
+            ],
+          ),
+        ));
+  }
+}
+
+/// Holds the current [Locale] and notifies any listeners when it changes.
+class CurrentLocale extends ValueNotifier<Locale> {
+  CurrentLocale(Locale value) : super(value);
+}
diff --git a/examples/localized_flutter_app/lib/supported_locales.dart b/examples/localized_flutter_app/lib/supported_locales.dart
new file mode 100644
index 0000000..a6bed55
--- /dev/null
+++ b/examples/localized_flutter_app/lib/supported_locales.dart
@@ -0,0 +1,21 @@
+// Copyright 2019 The Fuchsia 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 'package:flutter/widgets.dart';
+
+// Ideally, this file should be generated at build time from a build variable.
+const List<Locale> supportedLocales = <Locale>[
+  Locale('en'),
+  Locale('ar', 'XB'),
+  Locale('en', 'XA'),
+  Locale('en', 'XC'),
+  // Note: There is no messages_es.dart checked in. Creating this file is
+  // left as an exercise for those working on integrating Fuchsia with a
+  // translation pipeline.
+  Locale('es'),
+  Locale('he'),
+  Locale('sr'),
+  // Here is how to to specify a locale with a script code.
+  Locale.fromSubtags(languageCode: 'sr', scriptCode: 'Latn', countryCode: 'RS')
+];
diff --git a/examples/localized_flutter_app/meta/localized_flutter_app.cmx b/examples/localized_flutter_app/meta/localized_flutter_app.cmx
new file mode 100644
index 0000000..b6a31f1
--- /dev/null
+++ b/examples/localized_flutter_app/meta/localized_flutter_app.cmx
@@ -0,0 +1,14 @@
+{
+    "program": {
+        "data": "data/localized_flutter_app"
+    },
+    "sandbox": {
+        "services": [
+            "fuchsia.accessibility.ToggleBroadcaster",
+            "fuchsia.fonts.Provider",
+            "fuchsia.modular.Clipboard",
+            "fuchsia.sys.Environment",
+            "fuchsia.ui.scenic.Scenic"
+        ]
+    }
+}
diff --git a/examples/localized_flutter_app/pubspec.yaml b/examples/localized_flutter_app/pubspec.yaml
new file mode 100644
index 0000000..0673f90
--- /dev/null
+++ b/examples/localized_flutter_app/pubspec.yaml
@@ -0,0 +1,17 @@
+# Copyright 2019 The Fuchsia Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+name:
+  localized_flutter_app
+
+dependencies:
+  flutter:
+    sdk: flutter
+  flutter_localizations:
+    sdk: flutter
+  intl: ^0.15.7
+  intl_translation: ^0.17.2
+
+flutter:
+  uses-material-design: true
diff --git a/examples/localized_flutter_app/test/sample_test.dart b/examples/localized_flutter_app/test/sample_test.dart
new file mode 100644
index 0000000..c0596dd
--- /dev/null
+++ b/examples/localized_flutter_app/test/sample_test.dart
@@ -0,0 +1,11 @@
+// Copyright 2019 The Fuchsia 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 'package:test/test.dart';
+
+void main() {
+  test('test should pass', () {
+    expect(1, 1);
+  });
+}