Skip to content

Commit

Permalink
feat: add localizations (#76)
Browse files Browse the repository at this point in the history
* feat: add localizations

* fix: use BuildContext across asynchronous gaps
  • Loading branch information
bcihanc authored Feb 28, 2024
1 parent e8a9204 commit 076e26e
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 55 deletions.
37 changes: 22 additions & 15 deletions lib/src/components/supa_email_auth.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:supabase_auth_ui/src/localizations/supa_email_auth_localization.dart';
import 'package:supabase_auth_ui/src/utils/constants.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

Expand Down Expand Up @@ -79,6 +80,9 @@ class SupaEmailAuth extends StatefulWidget {
/// Additional properties for user_metadata on signup
final Map<String, dynamic>? extraMetadata;

/// Localization for the form
final SupaEmailAuthLocalization localization;

/// {@macro supa_email_auth}
const SupaEmailAuth({
Key? key,
Expand All @@ -89,6 +93,7 @@ class SupaEmailAuth extends StatefulWidget {
this.onError,
this.metadataFields,
this.extraMetadata,
this.localization = const SupaEmailAuthLocalization(),
}) : super(key: key);

@override
Expand Down Expand Up @@ -127,6 +132,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {

@override
Widget build(BuildContext context) {
final localization = widget.localization;
return Form(
key: _formKey,
child: Column(
Expand All @@ -139,13 +145,13 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
if (value == null ||
value.isEmpty ||
!EmailValidator.validate(_emailController.text)) {
return 'Please enter a valid email address';
return localization.validEmailError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email),
label: Text('Enter your email'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.email),
label: Text(localization.enterEmail),
),
controller: _emailController,
),
Expand All @@ -157,13 +163,13 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
: [AutofillHints.newPassword],
validator: (value) {
if (value == null || value.isEmpty || value.length < 6) {
return 'Please enter a password that is at least 6 characters long';
return localization.passwordLengthError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
label: Text('Enter your password'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock),
label: Text(localization.enterPassword),
),
obscureText: true,
controller: _passwordController,
Expand Down Expand Up @@ -193,7 +199,8 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
strokeWidth: 1.5,
),
)
: Text(_isSigningIn ? 'Sign In' : 'Sign Up'),
: Text(
_isSigningIn ? localization.signIn : localization.signUp),
onPressed: () async {
if (!_formKey.currentState!.validate()) {
return;
Expand Down Expand Up @@ -226,7 +233,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
} catch (error) {
if (widget.onError == null && context.mounted) {
context.showErrorSnackBar(
'Unexpected error has occurred: $error');
'${localization.unexpectedError}: $error');
} else {
widget.onError?.call(error);
}
Expand All @@ -246,7 +253,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
_forgotPassword = true;
});
},
child: const Text('Forgot your password?'),
child: Text(localization.forgotPassword),
),
],
TextButton(
Expand All @@ -258,8 +265,8 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
});
},
child: Text(_isSigningIn
? 'Don\'t have an account? Sign up'
: 'Already have an account? Sign in'),
? localization.dontHaveAccount
: localization.haveAccount),
),
],
if (_isSigningIn && _forgotPassword) ...[
Expand All @@ -283,7 +290,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
widget.onError?.call(error);
}
},
child: const Text('Send password reset email'),
child: Text(localization.sendPasswordReset),
),
spacer(16),
TextButton(
Expand All @@ -292,7 +299,7 @@ class _SupaEmailAuthState extends State<SupaEmailAuth> {
_forgotPassword = false;
});
},
child: const Text('Back to sign in'),
child: Text(localization.backToSignIn),
),
],
spacer(16),
Expand Down
26 changes: 16 additions & 10 deletions lib/src/components/supa_magic_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'dart:async';

import 'package:email_validator/email_validator.dart';
import 'package:flutter/material.dart';
import 'package:supabase_auth_ui/src/localizations/supa_magic_auth_localization.dart';
import 'package:supabase_auth_ui/src/utils/constants.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

Expand All @@ -18,11 +19,15 @@ class SupaMagicAuth extends StatefulWidget {
/// Method to be called when the auth action threw an excepction
final void Function(Object error)? onError;

/// Localization for the form
final SupaMagicAuthLocalization localization;

const SupaMagicAuth({
Key? key,
this.redirectUrl,
required this.onSuccess,
this.onError,
this.localization = const SupaMagicAuthLocalization(),
}) : super(key: key);

@override
Expand Down Expand Up @@ -57,6 +62,7 @@ class _SupaMagicAuthState extends State<SupaMagicAuth> {

@override
Widget build(BuildContext context) {
final localization = widget.localization;
return Form(
key: _formKey,
child: Column(
Expand All @@ -69,13 +75,13 @@ class _SupaMagicAuthState extends State<SupaMagicAuth> {
if (value == null ||
value.isEmpty ||
!EmailValidator.validate(_email.text)) {
return 'Please enter a valid email address';
return localization.validEmailError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.email),
label: Text('Enter your email'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.email),
label: Text(localization.enterEmail),
),
controller: _email,
),
Expand All @@ -90,9 +96,9 @@ class _SupaMagicAuthState extends State<SupaMagicAuth> {
strokeWidth: 1.5,
),
)
: const Text(
'Continue with magic Link',
style: TextStyle(fontWeight: FontWeight.bold),
: Text(
localization.continueWithMagicLink,
style: const TextStyle(fontWeight: FontWeight.bold),
),
onPressed: () async {
if (!_formKey.currentState!.validate()) {
Expand All @@ -106,8 +112,8 @@ class _SupaMagicAuthState extends State<SupaMagicAuth> {
email: _email.text,
emailRedirectTo: widget.redirectUrl,
);
if (mounted) {
context.showSnackBar('Check your email inbox!');
if (context.mounted) {
context.showSnackBar(localization.checkYourEmail);
}
} on AuthException catch (error) {
if (widget.onError == null && context.mounted) {
Expand All @@ -118,7 +124,7 @@ class _SupaMagicAuthState extends State<SupaMagicAuth> {
} catch (error) {
if (widget.onError == null && context.mounted) {
context.showErrorSnackBar(
'Unexpected error has occurred: $error');
'${localization.unexpectedError}: $error');
} else {
widget.onError?.call(error);
}
Expand Down
25 changes: 15 additions & 10 deletions lib/src/components/supa_phone_auth.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ class SupaPhoneAuth extends StatefulWidget {
/// Method to be called when the auth action threw an excepction
final void Function(Object error)? onError;

/// Localization for the form
final SupaPhoneAuthLocalization localization;

const SupaPhoneAuth({
Key? key,
required this.authAction,
required this.onSuccess,
this.onError,
this.localization = const SupaPhoneAuthLocalization(),
}) : super(key: key);

@override
Expand All @@ -43,6 +47,7 @@ class _SupaPhoneAuthState extends State<SupaPhoneAuth> {

@override
Widget build(BuildContext context) {
final localization = widget.localization;
final isSigningIn = widget.authAction == SupaAuthAction.signIn;
return Form(
key: _formKey,
Expand All @@ -53,13 +58,13 @@ class _SupaPhoneAuthState extends State<SupaPhoneAuth> {
autofillHints: const [AutofillHints.telephoneNumber],
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter a valid phone number';
return localization.validPhoneNumberError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.phone),
label: Text('Enter your phone number'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.phone),
label: Text(localization.enterPhoneNumber),
),
controller: _phone,
),
Expand All @@ -70,21 +75,21 @@ class _SupaPhoneAuthState extends State<SupaPhoneAuth> {
: [AutofillHints.newPassword],
validator: (value) {
if (value == null || value.isEmpty || value.length < 6) {
return 'Please enter a password that is at least 6 characters long';
return localization.passwordLengthError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
label: Text('Enter your password'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock),
label: Text(localization.enterPassword),
),
obscureText: true,
controller: _password,
),
spacer(16),
ElevatedButton(
child: Text(
isSigningIn ? 'Sign In' : 'Sign Up',
isSigningIn ? localization.signIn : localization.signUp,
style: const TextStyle(fontWeight: FontWeight.bold),
),
onPressed: () async {
Expand Down Expand Up @@ -113,7 +118,7 @@ class _SupaPhoneAuthState extends State<SupaPhoneAuth> {
} catch (error) {
if (widget.onError == null && context.mounted) {
context.showErrorSnackBar(
'Unexpected error has occurred: $error');
'${localization.unexpectedError}: $error');
} else {
widget.onError?.call(error);
}
Expand Down
22 changes: 14 additions & 8 deletions lib/src/components/supa_reset_password.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import 'package:supabase_auth_ui/src/localizations/supa_reset_password_localization.dart';
import 'package:supabase_auth_ui/src/utils/constants.dart';
import 'package:supabase_flutter/supabase_flutter.dart';

Expand All @@ -13,11 +14,15 @@ class SupaResetPassword extends StatefulWidget {
/// Method to be called when the auth action threw an excepction
final void Function(Object error)? onError;

/// Localization for the form
final SupaResetPasswordLocalization localization;

const SupaResetPassword({
Key? key,
this.accessToken,
required this.onSuccess,
this.onError,
this.localization = const SupaResetPasswordLocalization(),
}) : super(key: key);

@override
Expand All @@ -36,6 +41,7 @@ class _SupaResetPasswordState extends State<SupaResetPassword> {

@override
Widget build(BuildContext context) {
final localization = widget.localization;
return Form(
key: _formKey,
child: Column(
Expand All @@ -45,21 +51,21 @@ class _SupaResetPasswordState extends State<SupaResetPassword> {
autofillHints: const [AutofillHints.newPassword],
validator: (value) {
if (value == null || value.isEmpty || value.length < 6) {
return 'Please enter a password that is at least 6 characters long';
return localization.passwordLengthError;
}
return null;
},
decoration: const InputDecoration(
prefixIcon: Icon(Icons.lock),
label: Text('Enter your password'),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.lock),
label: Text(localization.enterPassword),
),
controller: _password,
),
spacer(16),
ElevatedButton(
child: const Text(
'Update Password',
style: TextStyle(fontWeight: FontWeight.bold),
child: Text(
localization.updatePassword,
style: const TextStyle(fontWeight: FontWeight.bold),
),
onPressed: () async {
if (!_formKey.currentState!.validate()) {
Expand All @@ -81,7 +87,7 @@ class _SupaResetPasswordState extends State<SupaResetPassword> {
} catch (error) {
if (widget.onError == null && context.mounted) {
context.showErrorSnackBar(
'Unexpected error has occurred: $error');
'${localization.passwordLengthError}: $error');
} else {
widget.onError?.call(error);
}
Expand Down
Loading

0 comments on commit 076e26e

Please sign in to comment.