diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml
index 4013f71..1c44901 100644
--- a/.github/workflows/build.yaml
+++ b/.github/workflows/build.yaml
@@ -12,10 +12,10 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- uses: subosito/flutter-action@v2
- name: Install Dependencies
- run: flutter packages get
+ run: flutter pub get
- name: Format
run: dart format --set-exit-if-changed lib test
- name: Analyze
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 9d3a002..32a5f98 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -2,8 +2,8 @@ include: package:flutter_lints/flutter.yaml
analyzer:
exclude:
- - '**/*.mocks.dart'
- - '**/*.g.dart'
+ - "**/*.mocks.dart"
+ - "**/*.g.dart"
linter:
rules:
diff --git a/example/ios/.gitignore b/example/ios/.gitignore
index e96ef60..61fa3c4 100644
--- a/example/ios/.gitignore
+++ b/example/ios/.gitignore
@@ -22,6 +22,7 @@ Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
+Flutter/ephemeral/
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
diff --git a/example/ios/Flutter/AppFrameworkInfo.plist b/example/ios/Flutter/AppFrameworkInfo.plist
index 9367d48..1dc6cf7 100644
--- a/example/ios/Flutter/AppFrameworkInfo.plist
+++ b/example/ios/Flutter/AppFrameworkInfo.plist
@@ -21,6 +21,6 @@
CFBundleVersion
1.0
MinimumOSVersion
- 8.0
+ 13.0
diff --git a/example/ios/Runner.xcodeproj/project.pbxproj b/example/ios/Runner.xcodeproj/project.pbxproj
index c6759a6..db9bdcf 100644
--- a/example/ios/Runner.xcodeproj/project.pbxproj
+++ b/example/ios/Runner.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 46;
+ objectVersion = 54;
objects = {
/* Begin PBXBuildFile section */
@@ -127,7 +127,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
- LastUpgradeCheck = 1020;
+ LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
@@ -171,10 +171,12 @@
/* Begin PBXShellScriptBuildPhase section */
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
inputPaths = (
+ "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
);
name = "Thin Binary";
outputPaths = (
@@ -185,6 +187,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
@@ -272,7 +275,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
@@ -346,7 +349,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -395,7 +398,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+ IPHONEOS_DEPLOYMENT_TARGET = 13.0;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos;
diff --git a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index a28140c..fc5ae03 100644
--- a/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,6 +1,6 @@
@@ -45,11 +46,13 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
+ enableGPUValidationMode = "1"
allowLocationSimulation = "YES">
diff --git a/example/ios/Runner/AppDelegate.swift b/example/ios/Runner/AppDelegate.swift
index 70693e4..b636303 100644
--- a/example/ios/Runner/AppDelegate.swift
+++ b/example/ios/Runner/AppDelegate.swift
@@ -1,7 +1,7 @@
import UIKit
import Flutter
-@UIApplicationMain
+@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
diff --git a/example/ios/Runner/Info.plist b/example/ios/Runner/Info.plist
index a060db6..4f68a2c 100644
--- a/example/ios/Runner/Info.plist
+++ b/example/ios/Runner/Info.plist
@@ -41,5 +41,9 @@
UIViewControllerBasedStatusBarAppearance
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
diff --git a/example/lib/localizations.dart b/example/lib/localizations.dart
index 82c3a59..b055b94 100644
--- a/example/lib/localizations.dart
+++ b/example/lib/localizations.dart
@@ -15,9 +15,9 @@ class HomePageL10n {
i18next.t('homepage:today', variables: {'date': date});
String hello({required String name, required String world}) => i18next.t(
- 'homepage:helloMessage',
- variables: {'name': name, 'world': world},
- );
+ 'homepage:helloMessage',
+ variables: {'name': name, 'world': world},
+ );
String gendered(String gender) =>
i18next.t('homepage:genderMessage', context: gender);
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 0b8c84e..23519b2 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -9,7 +9,7 @@ import 'localizations.dart';
void main() => runApp(const MyApp());
class MyApp extends StatefulWidget {
- const MyApp({Key? key}) : super(key: key);
+ const MyApp({super.key});
final List locales = const [
Locale('en', 'US'),
@@ -70,25 +70,25 @@ class _MyAppState extends State {
}
static Map formatters() => {
- 'uppercase': (value, format, locale, options) =>
- value?.toString().toUpperCase(),
- 'lowercase': (value, format, locale, options) =>
- value?.toString().toLowerCase(),
- 'datetime': (value, format, locale, options) {
- if (value is! DateTime) return value;
- var dateFormat = format.options['format'];
- dateFormat = dateFormat is String ? dateFormat : 'dd/MM/yyyy';
- return DateFormat(dateFormat, locale.toString()).format(value);
- },
- };
+ 'uppercase': (value, format, locale, options) =>
+ value?.toString().toUpperCase(),
+ 'lowercase': (value, format, locale, options) =>
+ value?.toString().toLowerCase(),
+ 'datetime': (value, format, locale, options) {
+ if (value is! DateTime) return value;
+ var dateFormat = format.options['format'];
+ dateFormat = dateFormat is String ? dateFormat : 'dd/MM/yyyy';
+ return DateFormat(dateFormat, locale.toString()).format(value);
+ },
+ };
}
class MyHomePage extends StatefulWidget {
const MyHomePage({
- Key? key,
+ super.key,
required this.supportedLocales,
required this.onUpdateLocale,
- }) : super(key: key);
+ });
final List supportedLocales;
final ValueChanged onUpdateLocale;
@@ -116,7 +116,7 @@ class _MyHomePageState extends State {
children: [
CupertinoSegmentedControl(
children: {
- for (final e in widget.supportedLocales) e: Text(e.toString())
+ for (final e in widget.supportedLocales) e: Text(e.toString()),
},
groupValue: Localizations.localeOf(context),
onValueChanged: widget.onUpdateLocale,
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 66b5403..92849d1 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -5,7 +5,8 @@ version: 0.1.0
publish_to: none
environment:
- sdk: ">=2.18.0 <4.0.0"
+ sdk: ^3.10.0
+ flutter: ^3.38.5
dependencies:
flutter:
@@ -14,10 +15,10 @@ dependencies:
sdk: flutter
i18next:
path: ../
- intl: ^0.18.1
+ intl: ^0.20.2
dev_dependencies:
- flutter_lints: ^2.0.3
+ flutter_lints: ^6.0.0
flutter_test:
sdk: flutter
diff --git a/lib/i18next.dart b/lib/i18next.dart
index 38389ed..813f3ac 100644
--- a/lib/i18next.dart
+++ b/lib/i18next.dart
@@ -1,5 +1,3 @@
-library i18next;
-
export 'src/data_sources/asset_bundle_data_source.dart';
export 'src/data_sources/localization_data_source.dart';
export 'src/i18next.dart';
diff --git a/lib/interpolator.dart b/lib/interpolator.dart
index 31ecd80..e754fc7 100644
--- a/lib/interpolator.dart
+++ b/lib/interpolator.dart
@@ -5,12 +5,13 @@ import 'src/formatter.dart' as formatter;
import 'src/options.dart';
import 'utils.dart';
-typedef Translate = String? Function(
- String key,
- Locale locale,
- Map variables,
- I18NextOptions options,
-);
+typedef Translate =
+ String? Function(
+ String key,
+ Locale locale,
+ Map variables,
+ I18NextOptions options,
+ );
/// Exception thrown when the [interpolate] fails while processing
/// for either not containing a variable or with malformed or
@@ -71,27 +72,33 @@ String interpolate(
return todo.fold(
string,
- (result, helper) => result.splitMapJoin(helper.pattern, onMatch: (match) {
- var variable = match[1]!.trim();
-
- Iterable formats = [];
- if (variable.contains(formatSeparator)) {
- final variableParts = variable.split(formatSeparator);
- variable = variableParts.first.trim();
- formats = variableParts.skip(1).map((e) => e.trim());
- }
-
- if (variable.isEmpty) {
- throw InterpolationException('Missing variable', match);
- }
-
- final path = variable.split(keySeparator);
- final value = evaluate(path, variables);
- final formatted = formatter.format(value, formats, locale, options) ??
- (throw InterpolationException(
- 'Could not evaluate or format variable', match));
- return helper.escape(formatted);
- }),
+ (result, helper) => result.splitMapJoin(
+ helper.pattern,
+ onMatch: (match) {
+ var variable = match[1]!.trim();
+
+ Iterable formats = [];
+ if (variable.contains(formatSeparator)) {
+ final variableParts = variable.split(formatSeparator);
+ variable = variableParts.first.trim();
+ formats = variableParts.skip(1).map((e) => e.trim());
+ }
+
+ if (variable.isEmpty) {
+ throw InterpolationException('Missing variable', match);
+ }
+
+ final path = variable.split(keySeparator);
+ final value = evaluate(path, variables);
+ final formatted =
+ formatter.format(value, formats, locale, options) ??
+ (throw InterpolationException(
+ 'Could not evaluate or format variable',
+ match,
+ ));
+ return helper.escape(formatted);
+ },
+ ),
);
}
@@ -121,26 +128,29 @@ String nest(
I18NextOptions options,
) {
final pattern = nestingPattern(options);
- return string.splitMapJoin(pattern, onMatch: (match) {
- match = match as RegExpMatch;
- final key = match.namedGroup('key');
- if (key == null || key.isEmpty) {
- throw NestingException('Key not found', match);
- }
-
- var newVariables = variables;
- final varsString = match.namedGroup('variables');
- if (varsString != null && varsString.isNotEmpty) {
- final Map decoded = jsonDecode(varsString);
- newVariables = Map.of(variables)..addAll(decoded);
- }
-
- final value = translate(key, locale, newVariables, options);
- if (value == null) {
- throw NestingException('Translation not found', match);
- }
- return value;
- });
+ return string.splitMapJoin(
+ pattern,
+ onMatch: (match) {
+ match = match as RegExpMatch;
+ final key = match.namedGroup('key');
+ if (key == null || key.isEmpty) {
+ throw NestingException('Key not found', match);
+ }
+
+ var newVariables = variables;
+ final varsString = match.namedGroup('variables');
+ if (varsString != null && varsString.isNotEmpty) {
+ final Map decoded = jsonDecode(varsString);
+ newVariables = Map.of(variables)..addAll(decoded);
+ }
+
+ final value = translate(key, locale, newVariables, options);
+ if (value == null) {
+ throw NestingException('Translation not found', match);
+ }
+ return value;
+ },
+ );
}
RegExp interpolationPattern(I18NextOptions options) {
diff --git a/lib/src/data_sources/asset_bundle_data_source.dart b/lib/src/data_sources/asset_bundle_data_source.dart
index b7478d6..43b24ee 100644
--- a/lib/src/data_sources/asset_bundle_data_source.dart
+++ b/lib/src/data_sources/asset_bundle_data_source.dart
@@ -13,8 +13,7 @@ class AssetBundleLocalizationDataSource implements LocalizationDataSource {
this.bundlePath = 'localizations',
AssetBundle? bundle,
this.cache = true,
- }) : bundle = bundle ?? rootBundle,
- super();
+ }) : bundle = bundle ?? rootBundle;
/// The path prefixed to the asset when retrieving from the [bundle].
///
@@ -50,16 +49,9 @@ class AssetBundleLocalizationDataSource implements LocalizationDataSource {
/// The end result is a [Map] that contains all the namespaces which are
/// the file names themselves (case sensitive).
@override
- Future