Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ include: package:flutter_lints/flutter.yaml

analyzer:
exclude:
- '**/*.mocks.dart'
- '**/*.g.dart'
- "**/*.mocks.dart"
- "**/*.g.dart"

linter:
rules:
1 change: 1 addition & 0 deletions example/ios/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
Flutter/ephemeral/
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*

Expand Down
2 changes: 1 addition & 1 deletion example/ios/Flutter/AppFrameworkInfo.plist
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>8.0</string>
<string>13.0</string>
</dict>
</plist>
13 changes: 8 additions & 5 deletions example/ios/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 54;
objects = {

/* Begin PBXBuildFile section */
Expand Down Expand Up @@ -127,7 +127,7 @@
97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1020;
LastUpgradeCheck = 1510;
ORGANIZATIONNAME = "";
TargetAttributes = {
97C146ED1CF9000F007C117D = {
Expand Down Expand Up @@ -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 = (
Expand All @@ -185,6 +187,7 @@
};
9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1;
buildActionMask = 2147483647;
files = (
);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1020"
LastUpgradeVersion = "1510"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand All @@ -26,6 +26,7 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
</Testables>
Expand All @@ -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">
<BuildableProductRunnable
runnableDebuggingMode = "0">
Expand Down
2 changes: 1 addition & 1 deletion example/ios/Runner/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import UIKit
import Flutter

@UIApplicationMain
@main
@objc class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
Expand Down
4 changes: 4 additions & 0 deletions example/ios/Runner/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -41,5 +41,9 @@
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
<key>CADisableMinimumFrameDurationOnPhone</key>
<true/>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true/>
</dict>
</plist>
6 changes: 3 additions & 3 deletions example/lib/localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
30 changes: 15 additions & 15 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<Locale> locales = const [
Locale('en', 'US'),
Expand Down Expand Up @@ -70,25 +70,25 @@ class _MyAppState extends State<MyApp> {
}

static Map<String, ValueFormatter> 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<Locale> supportedLocales;
final ValueChanged<Locale> onUpdateLocale;
Expand Down Expand Up @@ -116,7 +116,7 @@ class _MyHomePageState extends State<MyHomePage> {
children: <Widget>[
CupertinoSegmentedControl<Locale>(
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,
Expand Down
7 changes: 4 additions & 3 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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

Expand Down
2 changes: 0 additions & 2 deletions lib/i18next.dart
Original file line number Diff line number Diff line change
@@ -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';
Expand Down
104 changes: 57 additions & 47 deletions lib/interpolator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, dynamic> variables,
I18NextOptions options,
);
typedef Translate =
String? Function(
String key,
Locale locale,
Map<String, dynamic> variables,
I18NextOptions options,
);

/// Exception thrown when the [interpolate] fails while processing
/// for either not containing a variable or with malformed or
Expand Down Expand Up @@ -71,27 +72,33 @@ String interpolate(

return todo.fold<String>(
string,
(result, helper) => result.splitMapJoin(helper.pattern, onMatch: (match) {
var variable = match[1]!.trim();

Iterable<String> 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<String> 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);
},
),
);
}

Expand Down Expand Up @@ -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<String, dynamic> decoded = jsonDecode(varsString);
newVariables = Map<String, dynamic>.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<String, dynamic> decoded = jsonDecode(varsString);
newVariables = Map<String, dynamic>.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) {
Expand Down
Loading