Remove json translations approach, add example for adding language
Signed-off-by: Sahil Kumar <[email protected]>
This commit is contained in:
@@ -1,10 +1,35 @@
|
|||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:stream_chat_persistence/stream_chat_persistence.dart';
|
import 'package:stream_chat_localizations/stream_chat_localizations.dart';
|
||||||
|
|
||||||
final chatPersistentClient = StreamChatPersistenceClient(
|
/// A custom set of localizations for the 'hi' locale.
|
||||||
logLevel: Level.INFO,
|
class StreamChatLocalizationsHi extends GlobalStreamChatLocalizations {
|
||||||
);
|
const StreamChatLocalizationsHi() : super(localeName: 'hi');
|
||||||
|
|
||||||
|
static const LocalizationsDelegate<StreamChatLocalizations> delegate =
|
||||||
|
_HindiStreamChatLocalizationsDelegate();
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get launchUrlError => 'URL लॉन्च नहीं कर सकता';
|
||||||
|
}
|
||||||
|
|
||||||
|
class _HindiStreamChatLocalizationsDelegate
|
||||||
|
extends LocalizationsDelegate<StreamChatLocalizations> {
|
||||||
|
const _HindiStreamChatLocalizationsDelegate();
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool isSupported(Locale locale) => locale.languageCode == 'hi';
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<StreamChatLocalizations> load(Locale locale) =>
|
||||||
|
SynchronousFuture(const StreamChatLocalizationsHi());
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool shouldReload(_HindiStreamChatLocalizationsDelegate old) => false;
|
||||||
|
}
|
||||||
|
|
||||||
void main() async {
|
void main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
@@ -14,7 +39,7 @@ void main() async {
|
|||||||
final client = StreamChatClient(
|
final client = StreamChatClient(
|
||||||
's2dxdhpxd94g',
|
's2dxdhpxd94g',
|
||||||
logLevel: Level.INFO,
|
logLevel: Level.INFO,
|
||||||
)..chatPersistenceClient = chatPersistentClient;
|
);
|
||||||
|
|
||||||
/// Set the current user and connect the websocket. In a production scenario, this should be done using
|
/// Set the current user and connect the websocket. In a production scenario, this should be done using
|
||||||
/// a backend to generate a user token using our server SDK.
|
/// a backend to generate a user token using our server SDK.
|
||||||
@@ -58,6 +83,17 @@ class MyApp extends StatelessWidget {
|
|||||||
theme: ThemeData.light(),
|
theme: ThemeData.light(),
|
||||||
darkTheme: ThemeData.dark(),
|
darkTheme: ThemeData.dark(),
|
||||||
themeMode: ThemeMode.system,
|
themeMode: ThemeMode.system,
|
||||||
|
supportedLocales: [
|
||||||
|
Locale('en', 'US'),
|
||||||
|
Locale('hi', 'IN'),
|
||||||
|
],
|
||||||
|
localizationsDelegates: [
|
||||||
|
GlobalStreamChatLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
StreamChatLocalizationsHi.delegate,
|
||||||
|
],
|
||||||
builder: (context, widget) {
|
builder: (context, widget) {
|
||||||
return StreamChat(
|
return StreamChat(
|
||||||
client: client,
|
client: client,
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ dependencies:
|
|||||||
# path: ../../stream_chat_flutter_core
|
# path: ../../stream_chat_flutter_core
|
||||||
stream_chat_flutter:
|
stream_chat_flutter:
|
||||||
path: ../
|
path: ../
|
||||||
|
stream_chat_localizations:
|
||||||
|
path: ../../stream_chat_localizations
|
||||||
stream_chat_persistence:
|
stream_chat_persistence:
|
||||||
path: ../../stream_chat_persistence
|
path: ../../stream_chat_persistence
|
||||||
|
|
||||||
|
|||||||
@@ -104,11 +104,7 @@ extension BuildContextX on BuildContext {
|
|||||||
double get textScaleFactor =>
|
double get textScaleFactor =>
|
||||||
MediaQuery.maybeOf(this)?.textScaleFactor ?? 1.0;
|
MediaQuery.maybeOf(this)?.textScaleFactor ?? 1.0;
|
||||||
|
|
||||||
String translate({
|
StreamChatLocalizations? get translations => StreamChatLocalizations.of(this);
|
||||||
required String key,
|
|
||||||
required String defaultValue,
|
|
||||||
}) =>
|
|
||||||
StreamChatLocalizations.of(this)?.translate(key) ?? defaultValue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension on [BorderRadius]
|
/// Extension on [BorderRadius]
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart';
|
||||||
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
import 'package:stream_chat_flutter_core/stream_chat_flutter_core.dart';
|
||||||
|
import 'package:stream_chat_flutter/src/extension.dart';
|
||||||
|
|
||||||
/// Text widget to display in message
|
/// Text widget to display in message
|
||||||
class MessageText extends StatelessWidget {
|
class MessageText extends StatelessWidget {
|
||||||
@@ -29,6 +30,8 @@ class MessageText extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final texts = context.translations?.launchUrlError ?? 'defaultValue';
|
||||||
|
return Text(texts);
|
||||||
final text = _replaceMentions(message.text ?? '').replaceAll('\n', '\n\n');
|
final text = _replaceMentions(message.text ?? '').replaceAll('\n', '\n\n');
|
||||||
|
|
||||||
final themeData = Theme.of(context);
|
final themeData = Theme.of(context);
|
||||||
|
|||||||
@@ -71,9 +71,6 @@ import 'package:flutter/widgets.dart';
|
|||||||
/// * [GlobalStreamChatLocalizations], which provides material localizations
|
/// * [GlobalStreamChatLocalizations], which provides material localizations
|
||||||
/// for many languages.
|
/// for many languages.
|
||||||
abstract class StreamChatLocalizations {
|
abstract class StreamChatLocalizations {
|
||||||
///
|
|
||||||
String? translate(String key);
|
|
||||||
|
|
||||||
/// The `StreamChatLocalizations` from the closest [Localizations] instance
|
/// The `StreamChatLocalizations` from the closest [Localizations] instance
|
||||||
/// that encloses the given context.
|
/// that encloses the given context.
|
||||||
///
|
///
|
||||||
@@ -94,4 +91,6 @@ abstract class StreamChatLocalizations {
|
|||||||
context,
|
context,
|
||||||
StreamChatLocalizations,
|
StreamChatLocalizations,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
String get launchUrlError;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ issue_tracker: https://github.com/GetStream/stream-chat-flutter/issues
|
|||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.12.0 <3.0.0'
|
sdk: '>=2.12.0 <3.0.0'
|
||||||
|
flutter: ">=1.17.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
cached_network_image: ^3.0.0
|
cached_network_image: ^3.0.0
|
||||||
|
|||||||
@@ -1,12 +1,45 @@
|
|||||||
import 'dart:convert';
|
import 'package:flutter/foundation.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart' show rootBundle;
|
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
import 'package:stream_chat_flutter/stream_chat_flutter.dart'
|
||||||
show StreamChatLocalizations;
|
show StreamChatLocalizations;
|
||||||
|
|
||||||
const kStreamChatSupportedLanguages = [];
|
part 'stream_chat_localizations_en.dart';
|
||||||
|
|
||||||
|
/// The set of supported languages, as language code strings.
|
||||||
|
///
|
||||||
|
/// The [GlobalStreamChatLocalizations.delegate] can generate localizations for
|
||||||
|
/// any [Locale] with a language code from this set.
|
||||||
|
///
|
||||||
|
/// See also:
|
||||||
|
///
|
||||||
|
/// * [getStreamChatTranslation], whose documentation describes these values.
|
||||||
|
const kStreamChatSupportedLanguages = {'en'};
|
||||||
|
|
||||||
|
/// Creates a [GlobalStreamChatLocalizations] instance for the given `locale`.
|
||||||
|
///
|
||||||
|
/// All of the function's arguments except `locale` will be passed to the
|
||||||
|
/// [GlobalStreamChatLocalizations] constructor. (The `localeName` argument of that
|
||||||
|
/// constructor is specified by the actual subclass constructor by this
|
||||||
|
/// function.)
|
||||||
|
///
|
||||||
|
/// The following locales are supported by this package:
|
||||||
|
///
|
||||||
|
/// * `en` - English
|
||||||
|
///
|
||||||
|
/// Generally speaking, this method is only intended to be used by
|
||||||
|
/// [GlobalStreamChatLocalizations.delegate].
|
||||||
|
GlobalStreamChatLocalizations? getStreamChatTranslation(Locale locale) {
|
||||||
|
switch (locale.languageCode) {
|
||||||
|
case 'en':
|
||||||
|
return const StreamChatLocalizationsEn();
|
||||||
|
}
|
||||||
|
assert(
|
||||||
|
false,
|
||||||
|
'getStreamChatTranslation() called for unsupported locale "$locale"',
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Implementation of localized strings for the stream chat widgets
|
/// Implementation of localized strings for the stream chat widgets
|
||||||
///
|
///
|
||||||
@@ -30,43 +63,21 @@ const kStreamChatSupportedLanguages = [];
|
|||||||
/// localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
/// localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
||||||
/// supportedLocales: [
|
/// supportedLocales: [
|
||||||
/// const Locale('en', 'US'), // American English
|
/// const Locale('en', 'US'), // American English
|
||||||
/// const Locale('he', 'IL'), // Israeli Hebrew
|
|
||||||
/// // ...
|
/// // ...
|
||||||
/// ],
|
/// ],
|
||||||
/// // ...
|
/// // ...
|
||||||
/// )
|
/// )
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
class GlobalStreamChatLocalizations implements StreamChatLocalizations {
|
abstract class GlobalStreamChatLocalizations
|
||||||
/// Construct an object that defines the localized values for the widgets
|
implements StreamChatLocalizations {
|
||||||
/// library for US English (only).
|
/// Initializes an object that defines the StreamChat widget's localized
|
||||||
///
|
/// strings for the given `localeName`.
|
||||||
/// [LocalizationsDelegate] implementations typically call the static [load]
|
const GlobalStreamChatLocalizations({
|
||||||
const GlobalStreamChatLocalizations(this.locale, this.translations);
|
required String localeName,
|
||||||
|
}) : _localeName = localeName;
|
||||||
|
|
||||||
final Locale locale;
|
final String _localeName;
|
||||||
|
|
||||||
final Map<String, String?> translations;
|
|
||||||
|
|
||||||
static String getLocalePath(Locale locale) =>
|
|
||||||
'packages/stream_chat_localizations/i18n/${locale.languageCode}.json';
|
|
||||||
|
|
||||||
/// Creates an object that provides US English resource values for the
|
|
||||||
/// lowest levels of the widgets library.
|
|
||||||
///
|
|
||||||
/// The [locale] parameter is ignored.
|
|
||||||
///
|
|
||||||
/// This method is typically used to create a [LocalizationsDelegate].
|
|
||||||
/// The [WidgetsApp] does so by default.
|
|
||||||
static Future<StreamChatLocalizations> load(Locale locale) async {
|
|
||||||
final localePath = getLocalePath(locale);
|
|
||||||
final rawTranslations = await rootBundle.loadString(localePath);
|
|
||||||
Map<String, String?> translations = json.decode(rawTranslations);
|
|
||||||
translations = translations.map(
|
|
||||||
(key, value) => MapEntry(key, value?.toString()),
|
|
||||||
);
|
|
||||||
return GlobalStreamChatLocalizations(locale, translations);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A [LocalizationsDelegate] for [StreamChatLocalizations].
|
/// A [LocalizationsDelegate] for [StreamChatLocalizations].
|
||||||
///
|
///
|
||||||
@@ -74,7 +85,7 @@ class GlobalStreamChatLocalizations implements StreamChatLocalizations {
|
|||||||
/// as the value of [MaterialApp.localizationsDelegates] to include
|
/// as the value of [MaterialApp.localizationsDelegates] to include
|
||||||
/// the localizations for both the flutter and stream chat widget libraries.
|
/// the localizations for both the flutter and stream chat widget libraries.
|
||||||
static const LocalizationsDelegate<StreamChatLocalizations> delegate =
|
static const LocalizationsDelegate<StreamChatLocalizations> delegate =
|
||||||
_StreamChatLocalizationsDelegate();
|
_StreamChatLocalizationsDelegate();
|
||||||
|
|
||||||
/// A value for [MaterialApp.localizationsDelegates] that's typically used by
|
/// A value for [MaterialApp.localizationsDelegates] that's typically used by
|
||||||
/// internationalized apps.
|
/// internationalized apps.
|
||||||
@@ -92,20 +103,19 @@ class GlobalStreamChatLocalizations implements StreamChatLocalizations {
|
|||||||
/// localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
/// localizationsDelegates: GlobalStreamChatLocalizations.delegates,
|
||||||
/// supportedLocales: [
|
/// supportedLocales: [
|
||||||
/// const Locale('en', 'US'), // English
|
/// const Locale('en', 'US'), // English
|
||||||
/// const Locale('he', 'IL'), // Hebrew
|
|
||||||
/// ],
|
/// ],
|
||||||
/// // ...
|
/// // ...
|
||||||
/// )
|
/// )
|
||||||
/// ```
|
/// ```
|
||||||
static const List<LocalizationsDelegate> delegates = [
|
static const List<LocalizationsDelegate> delegates = [
|
||||||
delegate,
|
GlobalStreamChatLocalizations.delegate,
|
||||||
GlobalCupertinoLocalizations.delegate,
|
GlobalCupertinoLocalizations.delegate,
|
||||||
GlobalMaterialLocalizations.delegate,
|
GlobalMaterialLocalizations.delegate,
|
||||||
GlobalWidgetsLocalizations.delegate,
|
GlobalWidgetsLocalizations.delegate,
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String? translate(String key) => translations[key];
|
String get launchUrlError;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _StreamChatLocalizationsDelegate
|
class _StreamChatLocalizationsDelegate
|
||||||
@@ -116,14 +126,25 @@ class _StreamChatLocalizationsDelegate
|
|||||||
bool isSupported(Locale locale) =>
|
bool isSupported(Locale locale) =>
|
||||||
kStreamChatSupportedLanguages.contains(locale.languageCode);
|
kStreamChatSupportedLanguages.contains(locale.languageCode);
|
||||||
|
|
||||||
|
static final _loadedTranslations =
|
||||||
|
<Locale, Future<StreamChatLocalizations>>{};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<StreamChatLocalizations> load(Locale locale) =>
|
Future<StreamChatLocalizations> load(Locale locale) {
|
||||||
GlobalStreamChatLocalizations.load(locale);
|
assert(isSupported(locale), '');
|
||||||
|
return _loadedTranslations.putIfAbsent(
|
||||||
|
locale,
|
||||||
|
() =>
|
||||||
|
SynchronousFuture<StreamChatLocalizations>(
|
||||||
|
getStreamChatTranslation(locale)!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldReload(_StreamChatLocalizationsDelegate old) => false;
|
bool shouldReload(_StreamChatLocalizationsDelegate old) => false;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'StreamChatLocalizations.delegate('
|
String toString() => 'GlobalStreamChatLocalizations.delegate('
|
||||||
'${kStreamChatSupportedLanguages.length} locales)';
|
'${kStreamChatSupportedLanguages.length} locales)';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
part of 'stream_chat_localizations.dart';
|
||||||
|
|
||||||
|
/// The translations for English (`en`).
|
||||||
|
class StreamChatLocalizationsEn extends GlobalStreamChatLocalizations {
|
||||||
|
/// Create an instance of the translation bundle for English.
|
||||||
|
const StreamChatLocalizationsEn({String localeName = 'en'})
|
||||||
|
: super(localeName: localeName);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get launchUrlError => 'Cannot launch the url';
|
||||||
|
}
|
||||||
@@ -1,4 +1,9 @@
|
|||||||
/// Localizations for the StreamChat Flutter library.
|
/// Localizations for the StreamChat Flutter library.
|
||||||
library stream_chat_localization;
|
library stream_chat_localization;
|
||||||
|
|
||||||
export 'src/stream_chat_localizations.dart';
|
export 'package:flutter_localizations/flutter_localizations.dart'
|
||||||
|
show
|
||||||
|
GlobalCupertinoLocalizations,
|
||||||
|
GlobalMaterialLocalizations,
|
||||||
|
GlobalWidgetsLocalizations;
|
||||||
|
export 'src/stream_chat_localizations.dart' hide getStreamChatTranslation;
|
||||||
|
|||||||
@@ -18,40 +18,3 @@ dependencies:
|
|||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
|
||||||
|
|
||||||
# The following section is specific to Flutter.
|
|
||||||
flutter:
|
|
||||||
|
|
||||||
# To add assets to your package, add an assets section, like this:
|
|
||||||
# assets:
|
|
||||||
# - images/a_dot_burr.jpeg
|
|
||||||
# - images/a_dot_ham.jpeg
|
|
||||||
#
|
|
||||||
# For details regarding assets in packages, see
|
|
||||||
# https://flutter.dev/assets-and-images/#from-packages
|
|
||||||
#
|
|
||||||
# An image asset can refer to one or more resolution-specific "variants", see
|
|
||||||
# https://flutter.dev/assets-and-images/#resolution-aware.
|
|
||||||
|
|
||||||
# To add custom fonts to your package, add a fonts section here,
|
|
||||||
# in this "flutter" section. Each entry in this list should have a
|
|
||||||
# "family" key with the font family name, and a "fonts" key with a
|
|
||||||
# list giving the asset and other descriptors for the font. For
|
|
||||||
# example:
|
|
||||||
# fonts:
|
|
||||||
# - family: Schyler
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/Schyler-Regular.ttf
|
|
||||||
# - asset: fonts/Schyler-Italic.ttf
|
|
||||||
# style: italic
|
|
||||||
# - family: Trajan Pro
|
|
||||||
# fonts:
|
|
||||||
# - asset: fonts/TrajanPro.ttf
|
|
||||||
# - asset: fonts/TrajanPro_Bold.ttf
|
|
||||||
# weight: 700
|
|
||||||
#
|
|
||||||
# For details regarding fonts in packages, see
|
|
||||||
# https://flutter.dev/custom-fonts/#from-packages
|
|
||||||
|
|||||||
@@ -1,12 +1,20 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'package:stream_chat_localization/stream_chat_localizations.dart';
|
import 'package:stream_chat_localizations/stream_chat_localizations.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
test('adds one to input values', () {
|
for (final language in kStreamChatSupportedLanguages) {
|
||||||
final calculator = Calculator();
|
test('translations exist for $language', () async {
|
||||||
expect(calculator.addOne(2), 3);
|
final locale = Locale(language);
|
||||||
expect(calculator.addOne(-7), -6);
|
expect(
|
||||||
expect(calculator.addOne(0), 1);
|
GlobalStreamChatLocalizations.delegate.isSupported(locale),
|
||||||
});
|
isTrue,
|
||||||
|
);
|
||||||
|
final localizations =
|
||||||
|
await GlobalStreamChatLocalizations.delegate.load(locale);
|
||||||
|
expect(localizations.launchUrlError, isNotNull);
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user