Add localizations system
This commit is contained in:
parent
4f4e3a4df5
commit
1f230c0a63
31
README.md
31
README.md
|
@ -23,3 +23,34 @@ Community: [#fluffychat:matrix.org](https://matrix.to/#/#fluffychat:matrix.org)
|
|||
4. `flutter config --enable-web`
|
||||
|
||||
5. `flutter run`
|
||||
|
||||
## How to add translations for your language
|
||||
|
||||
1. Replace the non-translated string in the codebase:
|
||||
```
|
||||
Text("Hello world"),
|
||||
```
|
||||
with a method call:
|
||||
```
|
||||
Text(I18n.of(context).helloWorld),
|
||||
```
|
||||
And add the method to `/lib/i18n/i18n.dart`:
|
||||
```
|
||||
String get helloWorld => Intl.message('Hello world');
|
||||
```
|
||||
|
||||
2. Add the string to the .arb files with this command:
|
||||
```
|
||||
flutter pub run intl_translation:extract_to_arb --output-dir=lib/i18n lib/i18n/i18n.dart
|
||||
```
|
||||
|
||||
3. Copy the new translation objects from `/lib/i18n/intl_message.arb` to `/lib/i18n/intl_<yourlanguage>.arb` and translate it or create a new file for your language by copying `intl_message.arb`.
|
||||
|
||||
4. Update the translations with this command:
|
||||
```
|
||||
flutter pub run intl_translation:generate_from_arb \
|
||||
--output-dir=lib/i18n --no-use-deferred-loading \
|
||||
lib/main.dart lib/i18n/intl_*.arb
|
||||
```
|
||||
|
||||
5. Make sure your language is in `supportedLocales` in `/lib/main.dart`.
|
|
@ -1,3 +1,4 @@
|
|||
import 'package:fluffychat/i18n/i18n.dart';
|
||||
import 'package:fluffychat/views/chat.dart';
|
||||
import 'package:fluffychat/views/invitation_selection.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -54,7 +55,7 @@ class _NewGroupDialogState extends State<NewGroupDialog> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text("Create new group"),
|
||||
title: Text(I18n.of(context).createNewGroup),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: <Widget>[
|
||||
|
@ -65,12 +66,12 @@ class _NewGroupDialogState extends State<NewGroupDialog> {
|
|||
textInputAction: TextInputAction.go,
|
||||
onSubmitted: (s) => submitAction(context),
|
||||
decoration: InputDecoration(
|
||||
labelText: "(Optional) Group name",
|
||||
labelText: I18n.of(context).optionalGroupName,
|
||||
icon: Icon(Icons.people),
|
||||
hintText: "Enter a group name"),
|
||||
hintText: I18n.of(context).enterAGroupName),
|
||||
),
|
||||
SwitchListTile(
|
||||
title: Text("Group is public"),
|
||||
title: Text(I18n.of(context).groupIsPublic),
|
||||
value: publicGroup,
|
||||
onChanged: (bool b) => setState(() => publicGroup = b),
|
||||
),
|
||||
|
@ -78,14 +79,14 @@ class _NewGroupDialogState extends State<NewGroupDialog> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text("Close".toUpperCase(),
|
||||
child: Text(I18n.of(context).close.toUpperCase(),
|
||||
style: TextStyle(color: Colors.blueGrey)),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text("Create".toUpperCase()),
|
||||
child: Text(I18n.of(context).create.toUpperCase()),
|
||||
onPressed: () => submitAction(context),
|
||||
),
|
||||
],
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:famedlysdk/famedlysdk.dart';
|
||||
import 'package:fluffychat/components/avatar.dart';
|
||||
import 'package:fluffychat/i18n/i18n.dart';
|
||||
import 'package:fluffychat/views/chat.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:share/share.dart';
|
||||
|
@ -74,12 +75,10 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
"limit": 1,
|
||||
}),
|
||||
);
|
||||
print(response);
|
||||
setState(() => loading = false);
|
||||
if (response == false ||
|
||||
!(response is Map) ||
|
||||
(response["results"]?.isEmpty ?? true)) return;
|
||||
print("Set...");
|
||||
setState(() {
|
||||
foundProfile = response["results"].first;
|
||||
});
|
||||
|
@ -89,7 +88,7 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
Widget build(BuildContext context) {
|
||||
final String defaultDomain = Matrix.of(context).client.userID.split(":")[1];
|
||||
return AlertDialog(
|
||||
title: Text("New private chat"),
|
||||
title: Text(I18n.of(context).newPrivateChat),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -105,23 +104,23 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
onFieldSubmitted: (s) => submitAction(context),
|
||||
validator: (value) {
|
||||
if (value.isEmpty) {
|
||||
return 'Please enter a matrix identifier';
|
||||
return I18n.of(context).pleaseEnterAMatrixIdentifier;
|
||||
}
|
||||
final MatrixState matrix = Matrix.of(context);
|
||||
String mxid = "@" + controller.text.trim();
|
||||
if (mxid == matrix.client.userID) {
|
||||
return "You cannot invite yourself";
|
||||
return I18n.of(context).youCannotInviteYourself;
|
||||
}
|
||||
if (!mxid.contains("@")) {
|
||||
return "Make sure the identifier is valid";
|
||||
return I18n.of(context).makeSureTheIdentifierIsValid;
|
||||
}
|
||||
if (!mxid.contains(":")) {
|
||||
return "Make sure the identifier is valid";
|
||||
return I18n.of(context).makeSureTheIdentifierIsValid;
|
||||
}
|
||||
return null;
|
||||
},
|
||||
decoration: InputDecoration(
|
||||
labelText: "Enter a username",
|
||||
labelText: I18n.of(context).enterAUsername,
|
||||
icon: loading
|
||||
? Container(
|
||||
width: 24,
|
||||
|
@ -137,7 +136,8 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
)
|
||||
: Icon(Icons.account_circle),
|
||||
prefixText: "@",
|
||||
hintText: "username:$defaultDomain",
|
||||
hintText:
|
||||
"${I18n.of(context).username.toLowerCase()}:$defaultDomain",
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -179,7 +179,7 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
onTap: () => Share.share(
|
||||
"https://matrix.to/#/${Matrix.of(context).client.userID}"),
|
||||
title: Text(
|
||||
"Your own username:",
|
||||
"${I18n.of(context).yourOwnUsername}:",
|
||||
style: TextStyle(
|
||||
color: Colors.blueGrey,
|
||||
fontSize: 12,
|
||||
|
@ -194,14 +194,14 @@ class _NewPrivateChatDialogState extends State<NewPrivateChatDialog> {
|
|||
),
|
||||
actions: <Widget>[
|
||||
FlatButton(
|
||||
child: Text("Close".toUpperCase(),
|
||||
child: Text(I18n.of(context).close.toUpperCase(),
|
||||
style: TextStyle(color: Colors.blueGrey)),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
FlatButton(
|
||||
child: Text("Continue".toUpperCase()),
|
||||
child: Text(I18n.of(context).confirm.toUpperCase()),
|
||||
onPressed: () => submitAction(context),
|
||||
),
|
||||
],
|
||||
|
|
62
lib/i18n/i18n.dart
Normal file
62
lib/i18n/i18n.dart
Normal file
|
@ -0,0 +1,62 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'messages_all.dart';
|
||||
|
||||
class I18n {
|
||||
I18n(this.localeName);
|
||||
|
||||
static Future<I18n> load(Locale locale) {
|
||||
final String name =
|
||||
locale.countryCode.isEmpty ? locale.languageCode : locale.toString();
|
||||
final String localeName = Intl.canonicalizedLocale(name);
|
||||
return initializeMessages(localeName).then((_) {
|
||||
return I18n(localeName);
|
||||
});
|
||||
}
|
||||
|
||||
static I18n of(BuildContext context) {
|
||||
return Localizations.of<I18n>(context, I18n);
|
||||
}
|
||||
|
||||
final String localeName;
|
||||
|
||||
/* <=============> Translations <=============> */
|
||||
|
||||
String get close => Intl.message("Close");
|
||||
|
||||
String get confirm => Intl.message("Confirm");
|
||||
|
||||
String get create => Intl.message("Create");
|
||||
|
||||
String get createNewGroup => Intl.message("Create new group");
|
||||
|
||||
String get enterAGroupName => Intl.message("Enter a group name");
|
||||
|
||||
String get enterAUsername => Intl.message("Enter a username");
|
||||
|
||||
String get groupIsPublic => Intl.message("Group is public");
|
||||
|
||||
String get makeSureTheIdentifierIsValid =>
|
||||
Intl.message("Make sure the identifier is valid");
|
||||
|
||||
String get newPrivateChat => Intl.message("New private chat");
|
||||
|
||||
String get optionalGroupName => Intl.message("(Optional) Group name");
|
||||
|
||||
String get pleaseEnterAMatrixIdentifier =>
|
||||
Intl.message('Please enter a matrix identifier');
|
||||
|
||||
String get title => Intl.message(
|
||||
'FluffyChat',
|
||||
name: 'title',
|
||||
desc: 'Title for the application',
|
||||
locale: localeName,
|
||||
);
|
||||
|
||||
String get username => Intl.message("Username");
|
||||
|
||||
String get youCannotInviteYourself =>
|
||||
Intl.message("You cannot invite yourself");
|
||||
|
||||
String get yourOwnUsername => Intl.message("Your own username");
|
||||
}
|
9
lib/i18n/intl_de.arb
Normal file
9
lib/i18n/intl_de.arb
Normal file
|
@ -0,0 +1,9 @@
|
|||
{
|
||||
"@@last_modified": "2020-01-20T09:30:07.159333",
|
||||
"title": "FluffyChat",
|
||||
"@title": {
|
||||
"description": "Title for the application",
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
79
lib/i18n/intl_messages.arb
Normal file
79
lib/i18n/intl_messages.arb
Normal file
|
@ -0,0 +1,79 @@
|
|||
{
|
||||
"@@last_modified": "2020-01-20T09:50:21.386565",
|
||||
"Close": "Close",
|
||||
"@Close": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Confirm": "Confirm",
|
||||
"@Confirm": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Create": "Create",
|
||||
"@Create": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Create new group": "Create new group",
|
||||
"@Create new group": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Enter a group name": "Enter a group name",
|
||||
"@Enter a group name": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Enter a username": "Enter a username",
|
||||
"@Enter a username": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Group is public": "Group is public",
|
||||
"@Group is public": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Make sure the identifier is valid": "Make sure the identifier is valid",
|
||||
"@Make sure the identifier is valid": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"New private chat": "New private chat",
|
||||
"@New private chat": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"(Optional) Group name": "(Optional) Group name",
|
||||
"@(Optional) Group name": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Please enter a matrix identifier": "Please enter a matrix identifier",
|
||||
"@Please enter a matrix identifier": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"title": "FluffyChat",
|
||||
"@title": {
|
||||
"description": "Title for the application",
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Username": "Username",
|
||||
"@Username": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"You cannot invite yourself": "You cannot invite yourself",
|
||||
"@You cannot invite yourself": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
},
|
||||
"Your own username": "Your own username",
|
||||
"@Your own username": {
|
||||
"type": "text",
|
||||
"placeholders": {}
|
||||
}
|
||||
}
|
67
lib/i18n/messages_all.dart
Normal file
67
lib/i18n/messages_all.dart
Normal file
|
@ -0,0 +1,67 @@
|
|||
// 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_de.dart' as messages_de;
|
||||
import 'messages_messages.dart' as messages_messages;
|
||||
|
||||
typedef Future<dynamic> LibraryLoader();
|
||||
Map<String, LibraryLoader> _deferredLibraries = {
|
||||
'de': () => new Future.value(null),
|
||||
'messages': () => new Future.value(null),
|
||||
};
|
||||
|
||||
MessageLookupByLibrary _findExact(String localeName) {
|
||||
switch (localeName) {
|
||||
case 'de':
|
||||
return messages_de.messages;
|
||||
case 'messages':
|
||||
return messages_messages.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);
|
||||
}
|
26
lib/i18n/messages_de.dart
Normal file
26
lib/i18n/messages_de.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||
// This is a library that provides messages for a de 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 => 'de';
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
|
||||
};
|
||||
}
|
26
lib/i18n/messages_messages.dart
Normal file
26
lib/i18n/messages_messages.dart
Normal file
|
@ -0,0 +1,26 @@
|
|||
// DO NOT EDIT. This is code generated via package:intl/generate_localized.dart
|
||||
// This is a library that provides messages for a messages 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 => 'messages';
|
||||
|
||||
final messages = _notInlinedMessages(_notInlinedMessages);
|
||||
static _notInlinedMessages(_) => <String, Function> {
|
||||
|
||||
};
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'package:famedlysdk/famedlysdk.dart';
|
|||
import 'package:fluffychat/views/sign_up.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
|
||||
import 'components/matrix.dart';
|
||||
import 'views/chat_list.dart';
|
||||
|
@ -46,6 +47,15 @@ class App extends StatelessWidget {
|
|||
iconTheme: IconThemeData(color: Colors.black),
|
||||
),
|
||||
),
|
||||
localizationsDelegates: [
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
],
|
||||
supportedLocales: [
|
||||
const Locale('en'), // English
|
||||
const Locale('de'), // German
|
||||
],
|
||||
home: Builder(
|
||||
builder: (BuildContext context) => FutureBuilder<LoginState>(
|
||||
future: Matrix.of(context).client.onLoginStateChanged.stream.first,
|
||||
|
|
103
pubspec.lock
103
pubspec.lock
|
@ -1,6 +1,20 @@
|
|||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
_fe_analyzer_shared:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: _fe_analyzer_shared
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
analyzer:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: analyzer
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.39.4"
|
||||
archive:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -71,6 +85,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
csslib:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: csslib
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.1"
|
||||
cupertino_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -78,6 +99,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.1.3"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_style
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.3.3"
|
||||
famedlysdk:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -127,6 +155,11 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.1+2"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_speed_dial:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -144,6 +177,20 @@ packages:
|
|||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: html
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.14.0+3"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -172,6 +219,27 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.2+3"
|
||||
intl:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.16.0"
|
||||
intl_translation:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl_translation
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.17.9"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: js
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.6.1+1"
|
||||
json_annotation:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -214,6 +282,27 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.2.4"
|
||||
node_interop:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_interop
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.3"
|
||||
node_io:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: node_io
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1+2"
|
||||
package_config:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: package_config
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
path:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -256,6 +345,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: pub_semver
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "1.4.2"
|
||||
quiver:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -394,6 +490,13 @@ packages:
|
|||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "2.0.8"
|
||||
watcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: watcher
|
||||
url: "https://pub.dartlang.org"
|
||||
source: hosted
|
||||
version: "0.9.7+13"
|
||||
webview_flutter:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
|
|
@ -47,6 +47,11 @@ dependencies:
|
|||
share: ^0.6.3+5
|
||||
receive_sharing_intent: ^1.3.2
|
||||
|
||||
intl: ^0.16.0
|
||||
intl_translation: ^0.17.9
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
|
|
Loading…
Reference in a new issue