Skip to content

Commit

Permalink
Merge pull request #81 from jorre127/feature/localization-singleton
Browse files Browse the repository at this point in the history
Feature/localization singleton
  • Loading branch information
vanlooverenkoen authored Oct 3, 2022
2 parents e24f323 + ffae882 commit 6b72f5b
Show file tree
Hide file tree
Showing 12 changed files with 189 additions and 158 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
# Changelog
## [9.0.0] - 2022-10-03
### Breaking
- Translations can no longer be accessed from static methods on the Localization class. Instead you now need to manually manage the different localization instances. Migration steps are described in the readme.

## [8.0.0] - 2022-09-24
### Breaking
- Arguments are now formatted using the [sprintf](https://pub.dev/packages/sprintf) package. This means %d now refers to integers only. Use %f to format doubles, you can also use some format specifiers, eg: (%.2f will show 2 decimals)
Expand Down
24 changes: 24 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,30 @@ flutter packages pub run locale_gen
pub run locale_gen
```

### Migration steps <9.0.0 to >=9.0.0
With version 9.0.0 of local gen you no longer have static access to the translations, instead you can now manually manage the different localization instances. You can for example store a localization instance as a static. This way you can use it largely the same way as before. Example from the example project:

```dart
class LocaleViewModel with ChangeNotifier {
static final Localization localizationInstance = Localization();
...
Future<void> init(){
await Localization.load(
locale: locale,
localizationOverrides: customLocalizationOverrides,
);
notifyListeners();
}
```

You can then access this localizationInstance anywhere in the project like:
```dart
LocaleViewModel.localizationInstance.translation1;
LocaleViewModel.localizationInstance.translation2;
LocaleViewModel.localizationInstance.translation3;
```

### Migration steps <7.0.0 to >=7.0.0
With the newest version of locale_gen the context no longer needs to be provided when accessing the translations. This means there are a couple of breaking changes.

Expand Down
6 changes: 3 additions & 3 deletions example/lib/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:locale_gen_example/repository/locale_repository.dart';
import 'package:locale_gen_example/screen/home_screen.dart';
import 'package:locale_gen_example/util/locale/localization.dart';
import 'package:locale_gen_example/viewmodel/locale/locale_viewmodel.dart';
import 'package:provider/provider.dart';

Expand All @@ -20,8 +19,9 @@ class MyApp extends StatelessWidget {
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
locale: Localization.locale,
supportedLocales: Localization.supportedLocales,
locale: LocaleViewModel.localizationInstance.locale,
supportedLocales:
LocaleViewModel.localizationInstance.supportedLocales,
home: HomeScreen(),
),
),
Expand Down
18 changes: 9 additions & 9 deletions example/lib/screen/home_screen.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:locale_gen_example/util/locale/localization.dart';
import 'package:locale_gen_example/viewmodel/locale/locale_viewmodel.dart';
import 'package:provider/provider.dart';

Expand Down Expand Up @@ -45,14 +44,15 @@ class HomeScreen extends StatelessWidget {
Provider.of<LocaleViewModel>(context).showTranslationKeys,
),
Container(height: 22),
Text(Localization.test),
Text(Localization.testArg1('string')),
Text(Localization.testArg2(1)),
Text(Localization.testArg3('string', 1)),
Text(Localization.testArg4('string', 1)),
Text(Localization.testNonPositional('string', 1)),
Text(Localization.testPlural(4, 4)),
Text(Localization.testPlural(1, 1)),
Text(LocaleViewModel.localizationInstance.test),
Text(LocaleViewModel.localizationInstance.testArg1('string')),
Text(LocaleViewModel.localizationInstance.testArg2(1)),
Text(LocaleViewModel.localizationInstance.testArg3('string', 1)),
Text(LocaleViewModel.localizationInstance.testArg4('string', 1)),
Text(LocaleViewModel.localizationInstance
.testNonPositional('string', 1)),
Text(LocaleViewModel.localizationInstance.testPlural(4, 4)),
Text(LocaleViewModel.localizationInstance.testPlural(1, 1)),
],
),
),
Expand Down
46 changes: 23 additions & 23 deletions example/lib/util/locale/localization.dart
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ import 'package:sprintf/sprintf.dart';
typedef LocaleFilter = bool Function(String languageCode);

class Localization {
static LocaleFilter? localeFilter;
LocaleFilter? localeFilter;

static var _localisedValues = <String, dynamic>{};
static var _localisedOverrideValues = <String, dynamic>{};
var _localisedValues = <String, dynamic>{};
var _localisedOverrideValues = <String, dynamic>{};

/// The locale is used to get the correct json locale.
/// It can later be used to check what the locale is that was used to load this Localization instance.
static Locale? locale;
Locale? locale;

static const defaultLocale = Locale.fromSubtags(
languageCode: 'en', scriptCode: null, countryCode: null);
Expand All @@ -34,7 +34,7 @@ class Localization {
Locale.fromSubtags(languageCode: 'fi', scriptCode: null, countryCode: 'FI'),
];

static List<String> get supportedLanguages {
List<String> get supportedLanguages {
final supportedLanguageTags =
_supportedLocales.map((e) => e.toLanguageTag()).toList(growable: false);
if (localeFilter == null) return supportedLanguageTags;
Expand All @@ -43,21 +43,21 @@ class Localization {
.toList();
}

static List<Locale> get supportedLocales {
List<Locale> get supportedLocales {
if (localeFilter == null) return _supportedLocales;
return _supportedLocales
.where((element) => localeFilter?.call(element.toLanguageTag()) ?? true)
.toList();
}

static Future<void> load({
Future<void> load({
Locale? locale,
LocalizationOverrides? localizationOverrides,
bool showLocalizationKeys = false,
bool useCaching = true,
}) async {
final currentLocale = locale ?? defaultLocale;
Localization.locale = currentLocale;
this.locale = currentLocale;
if (showLocalizationKeys) {
_localisedValues.clear();
_localisedOverrideValues.clear();
Expand All @@ -74,7 +74,7 @@ class Localization {
_localisedValues = json.decode(jsonContent) as Map<String, dynamic>;
}

static String _t(String key, {List<dynamic>? args}) {
String _t(String key, {List<dynamic>? args}) {
try {
final value =
(_localisedOverrideValues[key] ?? _localisedValues[key]) as String?;
Expand All @@ -86,7 +86,7 @@ class Localization {
}
}

static String _plural(String key, {required num count, List<dynamic>? args}) {
String _plural(String key, {required num count, List<dynamic>? args}) {
try {
final value = (_localisedOverrideValues[key] ?? _localisedValues[key])
as Map<String, dynamic>?;
Expand Down Expand Up @@ -117,7 +117,7 @@ class Localization {
/// zh-Hans-CN: **'视频的灯光脚本'**
///
/// fi-FI: **'Näet lisää napauttamalla kuvakkeita'**
static String get test => _t(LocalizationKeys.test);
String get test => _t(LocalizationKeys.test);

/// Translations:
///
Expand All @@ -128,7 +128,7 @@ class Localization {
/// zh-Hans-CN: **'频的 [arg1 string]'**
///
/// fi-FI: **'Lisää napauttamalla [arg1 string]'**
static String testArg1(String arg1) =>
String testArg1(String arg1) =>
_t(LocalizationKeys.testArg1, args: <dynamic>[arg1]);

/// Translations:
Expand All @@ -140,7 +140,7 @@ class Localization {
/// zh-Hans-CN: **'频的 [arg1 number]'**
///
/// fi-FI: **'Lisää napauttamalla [arg1 number]'**
static String testArg2(int arg1) =>
String testArg2(int arg1) =>
_t(LocalizationKeys.testArg2, args: <dynamic>[arg1]);

/// Translations:
Expand All @@ -152,7 +152,7 @@ class Localization {
/// zh-Hans-CN: **'频的 [arg1 string] [arg2 number]'**
///
/// fi-FI: **'Lisää napauttamalla [arg1 string] [arg2 number]'**
static String testArg3(String arg1, int arg2) =>
String testArg3(String arg1, int arg2) =>
_t(LocalizationKeys.testArg3, args: <dynamic>[arg1, arg2]);

/// Translations:
Expand All @@ -164,7 +164,7 @@ class Localization {
/// zh-Hans-CN: **'频的 [arg1 string] %2$f [arg1 string]'**
///
/// fi-FI: **'Lisää napauttamalla [arg1 string] %2$f [arg1 string]'**
static String testArg4(String arg1, double arg2) =>
String testArg4(String arg1, double arg2) =>
_t(LocalizationKeys.testArg4, args: <dynamic>[arg1, arg2]);

/// Translations:
Expand All @@ -176,7 +176,7 @@ class Localization {
/// zh-Hans-CN: **'频\n的\n\n[arg1 string] [arg2 number] [arg1 string]'**
///
/// fi-FI: **'Lisää\nLisää napauttamalla\n\n[arg1 string] [arg2 number] [arg1 string]'**
static String testNewLine(String arg1, int arg2) =>
String testNewLine(String arg1, int arg2) =>
_t(LocalizationKeys.testNewLine, args: <dynamic>[arg1, arg2]);

/// Translations:
Expand All @@ -188,7 +188,7 @@ class Localization {
/// zh-Hans-CN: **'Carriage\r\nReturn'**
///
/// fi-FI: **'Carriage\r\nReturn'**
static String get testNewLineCarriageReturn =>
String get testNewLineCarriageReturn =>
_t(LocalizationKeys.testNewLineCarriageReturn);

/// Translations:
Expand All @@ -200,21 +200,21 @@ class Localization {
/// zh-Hans-CN: **'测试非位置参数 %s 和 %f'**
///
/// fi-FI: **'Testataan ei-positiaalista argumenttia %s ja %f'**
static String testNonPositional(String arg1, double arg2) =>
String testNonPositional(String arg1, double arg2) =>
_t(LocalizationKeys.testNonPositional, args: <dynamic>[arg1, arg2]);

/// Translations:
///
/// en: **'{one: %d hour, other: %d hours}'**
///
/// nl: **''**
/// nl: **'{one: %d uur, other: %d uren}'**
///
/// zh-Hans-CN: **''**
/// zh-Hans-CN: **'{other: %d 小时}'**
///
/// fi-FI: **''**
static String testPlural(num count, int arg1) =>
/// fi-FI: **'{one: %d tunti, other: %d tuntia}'**
String testPlural(num count, int arg1) =>
_plural(LocalizationKeys.testPlural, count: count, args: <dynamic>[arg1]);

static String getTranslation(String key, {List<dynamic>? args}) =>
String getTranslation(String key, {List<dynamic>? args}) =>
_t(key, args: args ?? <dynamic>[]);
}
6 changes: 3 additions & 3 deletions example/lib/util/locale/localization_keys.dart
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,10 @@ class LocalizationKeys {
///
/// en: **'{one: %d hour, other: %d hours}'**
///
/// nl: **''**
/// nl: **'{one: %d uur, other: %d uren}'**
///
/// zh-Hans-CN: **''**
/// zh-Hans-CN: **'{other: %d 小时}'**
///
/// fi-FI: **''**
/// fi-FI: **'{one: %d tunti, other: %d tuntia}'**
static const testPlural = 'test_plural';
}
9 changes: 6 additions & 3 deletions example/lib/viewmodel/locale/locale_viewmodel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ import 'package:locale_gen_example/util/locale/localization.dart';
class LocaleViewModel with ChangeNotifier {
final LocaleRepository _localeRepository;
var customLocalizationOverrides = CustomLocalizationOverrideManager();
static final Localization _localizationInstance = Localization();

static Localization get localizationInstance => _localizationInstance;

LocaleViewModel(this._localeRepository);

Expand All @@ -16,7 +19,7 @@ class LocaleViewModel with ChangeNotifier {

Future<void> initLocale() async {
final locale = await _localeRepository.getCustomLocale();
await Localization.load(
await _localizationInstance.load(
locale: locale,
localizationOverrides: customLocalizationOverrides,
);
Expand Down Expand Up @@ -51,7 +54,7 @@ class LocaleViewModel with ChangeNotifier {
Future<void> showTranslationKeys() async {
final locale = await _localeRepository.getCustomLocale();

await Localization.load(
await _localizationInstance.load(
locale: locale,
localizationOverrides: customLocalizationOverrides,
showLocalizationKeys: true,
Expand All @@ -61,7 +64,7 @@ class LocaleViewModel with ChangeNotifier {

Future<void> _onUpdateLocaleClicked(Locale? locale) async {
await _localeRepository.setCustomLocale(locale);
await Localization.load(
await _localizationInstance.load(
locale: locale,
localizationOverrides: customLocalizationOverrides,
);
Expand Down
22 changes: 11 additions & 11 deletions lib/src/locale_gen_sb_writer.dart
Original file line number Diff line number Diff line change
Expand Up @@ -63,15 +63,15 @@ class LocaleGenSbWriter {
..writeln('typedef LocaleFilter = bool Function(String languageCode);')
..writeln()
..writeln('class Localization {')
..writeln(' static LocaleFilter? localeFilter;')
..writeln(' LocaleFilter? localeFilter;')
..writeln()
..writeln(' static var _localisedValues = <String, dynamic>{};')
..writeln(' static var _localisedOverrideValues = <String, dynamic>{};')
..writeln(' var _localisedValues = <String, dynamic>{};')
..writeln(' var _localisedOverrideValues = <String, dynamic>{};')
..writeln()
..writeln(' /// The locale is used to get the correct json locale.')
..writeln(
' /// It can later be used to check what the locale is that was used to load this Localization instance.')
..writeln(' static Locale? locale;')
..writeln(' Locale? locale;')
..writeln()
..writeln(
LocaleGenParser.parseDefaultLanguageLocale(params.defaultLanguage))
Expand All @@ -83,28 +83,28 @@ class LocaleGenSbWriter {
sb
..writeln(' ];')
..writeln()
..writeln(' static List<String> get supportedLanguages {')
..writeln(' List<String> get supportedLanguages {')
..writeln(
' final supportedLanguageTags = _supportedLocales.map((e) => e.toLanguageTag()).toList(growable: false);')
..writeln(' if (localeFilter == null) return supportedLanguageTags;')
..writeln(
' return supportedLanguageTags.where((element) => localeFilter?.call(element) ?? true).toList();')
..writeln(' }')
..writeln()
..writeln(' static List<Locale> get supportedLocales {')
..writeln(' List<Locale> get supportedLocales {')
..writeln(' if (localeFilter == null) return _supportedLocales;')
..writeln(
' return _supportedLocales.where((element) => localeFilter?.call(element.toLanguageTag()) ?? true).toList();')
..writeln(' }')
..writeln()
..writeln(' static Future<void> load({')
..writeln(' Future<void> load({')
..writeln(' Locale? locale, ')
..writeln(' LocalizationOverrides? localizationOverrides,')
..writeln(' bool showLocalizationKeys = false,')
..writeln(' bool useCaching = true,')
..writeln(' }) async {')
..writeln(' final currentLocale = locale ?? defaultLocale;')
..writeln(' Localization.locale = currentLocale;')
..writeln(' this.locale = currentLocale;')
..writeln(' if (showLocalizationKeys) {')
..writeln(' _localisedValues.clear();')
..writeln(' _localisedOverrideValues.clear();')
Expand All @@ -121,7 +121,7 @@ class LocaleGenSbWriter {
' _localisedValues = json.decode(jsonContent) as Map<String, dynamic>;')
..writeln(' }')
..writeln()
..writeln(' static String _t(String key, {List<dynamic>? args}) {')
..writeln(' String _t(String key, {List<dynamic>? args}) {')
..writeln(' try {')
..writeln(
' final value = (_localisedOverrideValues[key] ?? _localisedValues[key]) as String?;')
Expand All @@ -136,7 +136,7 @@ class LocaleGenSbWriter {
if (hasPlurals) {
sb
..writeln(
' static String _plural(String key, {required num count, List<dynamic>? args}) {')
' String _plural(String key, {required num count, List<dynamic>? args}) {')
..writeln(' try {')
..writeln(
' final value = (_localisedOverrideValues[key] ?? _localisedValues[key]) as Map<String, dynamic>?;')
Expand Down Expand Up @@ -166,7 +166,7 @@ class LocaleGenSbWriter {
});
sb
..writeln(
' static String getTranslation(String key, {List<dynamic>? args}) => _t(key, args: args ?? <dynamic>[]);')
' String getTranslation(String key, {List<dynamic>? args}) => _t(key, args: args ?? <dynamic>[]);')
..writeln()
..writeln('}');
return sb.toString();
Expand Down
Loading

0 comments on commit 6b72f5b

Please sign in to comment.