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
2 changes: 1 addition & 1 deletion packages/clerk_flutter/l10n/en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@
"passkey": "passkey",
"password": "Password",
"passwordAndPasswordConfirmationMustMatch": "Password and password confirmation must match",
"passwordConfirmation": "password confirmation",
"passwordConfirmation": "confirm password",
"passwordMatchError": "Password and password confirmation must match",
"passwordMustBeSupplied": "A password must be supplied",
"passwordRequires": "Password requires:",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,7 @@ abstract class ClerkSdkLocalizations {
/// No description provided for @passwordConfirmation.
///
/// In en, this message translates to:
/// **'password confirmation'**
/// **'confirm password'**
String get passwordConfirmation;

/// No description provided for @passwordMatchError.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ class ClerkSdkLocalizationsEn extends ClerkSdkLocalizations {
'Password and password confirmation must match';

@override
String get passwordConfirmation => 'password confirmation';
String get passwordConfirmation => 'confirm password';

@override
String get passwordMatchError =>
Expand Down
135 changes: 57 additions & 78 deletions packages/clerk_flutter/lib/src/utils/localization_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,38 +2,36 @@ import 'package:clerk_auth/clerk_auth.dart' as clerk;
import 'package:clerk_flutter/src/generated/clerk_sdk_localizations.dart';

/// Function that performs localization
typedef LocalizedMessage = String Function(ClerkSdkLocalizations localizations);
typedef LocalizedMessage = String Function(ClerkSdkLocalizations l10ns);

/// An extension class to enable localization of [clerk.AuthError]
///
extension ClerkAuthErrorExtension on clerk.AuthError {
/// Allow localization of an [clerk.AuthError]
String localizedMessage(ClerkSdkLocalizations localizations) {
String localizedMessage(ClerkSdkLocalizations l10ns) {
return switch (code) {
clerk.AuthErrorCode.actionNotTimely => localizations.actionNotTimely,
clerk.AuthErrorCode.cannotDeleteSelf => localizations.cannotDeleteSelf,
clerk.AuthErrorCode.actionNotTimely => l10ns.actionNotTimely,
clerk.AuthErrorCode.cannotDeleteSelf => l10ns.cannotDeleteSelf,
clerk.AuthErrorCode.jwtPoorlyFormatted =>
localizations.jwtPoorlyFormatted(argument.toString()),
l10ns.jwtPoorlyFormatted(argument.toString()),
clerk.AuthErrorCode.noAssociatedStrategy =>
localizations.noAssociatedStrategy(argument.toString()),
l10ns.noAssociatedStrategy(argument.toString()),
clerk.AuthErrorCode.noSessionFoundForUser =>
localizations.noSessionFoundForUser(argument.toString()),
l10ns.noSessionFoundForUser(argument.toString()),
clerk.AuthErrorCode.noSessionTokenRetrieved =>
localizations.noSessionTokenRetrieved,
l10ns.noSessionTokenRetrieved,
clerk.AuthErrorCode.noStageForStatus =>
localizations.noStageForStatus(argument.toString()),
l10ns.noStageForStatus(argument.toString()),
clerk.AuthErrorCode.noSuchFirstFactorStrategy =>
localizations.noSuchFirstFactorStrategy(argument.toString()),
l10ns.noSuchFirstFactorStrategy(argument.toString()),
clerk.AuthErrorCode.noSuchSecondFactorStrategy =>
localizations.noSuchSecondFactorStrategy(argument.toString()),
l10ns.noSuchSecondFactorStrategy(argument.toString()),
clerk.AuthErrorCode.passwordMatchError =>
localizations.passwordAndPasswordConfirmationMustMatch,
l10ns.passwordAndPasswordConfirmationMustMatch,
clerk.AuthErrorCode.passwordResetStrategyError =>
localizations.unsupportedPasswordResetStrategy(argument.toString()),
clerk.AuthErrorCode.problemsConnecting =>
localizations.problemsConnecting,
clerk.AuthErrorCode.signInError =>
localizations.signInError(argument.toString()),
l10ns.unsupportedPasswordResetStrategy(argument.toString()),
clerk.AuthErrorCode.problemsConnecting => l10ns.problemsConnecting,
clerk.AuthErrorCode.signInError => l10ns.signInError(argument.toString()),
_ => toString(),
};
}
Expand All @@ -43,25 +41,20 @@ extension ClerkAuthErrorExtension on clerk.AuthError {
///
extension ClerkEnrollmentTypeExtension on clerk.EnrollmentMode {
/// Allow localization of a "via [clerk.EnrollmentMode]" message
String viaInvitationMessage(ClerkSdkLocalizations localizations) {
String viaInvitationMessage(ClerkSdkLocalizations l10ns) {
return switch (this) {
clerk.EnrollmentMode.manualInvitation =>
localizations.viaManualInvitation,
clerk.EnrollmentMode.automaticInvitation =>
localizations.viaAutomaticInvitation,
clerk.EnrollmentMode.automaticSuggestion =>
localizations.viaAutomaticSuggestion,
clerk.EnrollmentMode.manualInvitation => l10ns.viaManualInvitation,
clerk.EnrollmentMode.automaticInvitation => l10ns.viaAutomaticInvitation,
clerk.EnrollmentMode.automaticSuggestion => l10ns.viaAutomaticSuggestion,
};
}

/// Allow localization of a [clerk.EnrollmentMode]
String localizedName(ClerkSdkLocalizations localizations) {
String localizedName(ClerkSdkLocalizations l10ns) {
return switch (this) {
clerk.EnrollmentMode.manualInvitation => localizations.manualInvitation,
clerk.EnrollmentMode.automaticInvitation =>
localizations.automaticInvitation,
clerk.EnrollmentMode.automaticSuggestion =>
localizations.automaticSuggestion,
clerk.EnrollmentMode.manualInvitation => l10ns.manualInvitation,
clerk.EnrollmentMode.automaticInvitation => l10ns.automaticInvitation,
clerk.EnrollmentMode.automaticSuggestion => l10ns.automaticSuggestion,
};
}
}
Expand All @@ -70,21 +63,21 @@ extension ClerkEnrollmentTypeExtension on clerk.EnrollmentMode {
///
extension ClerkStatusLocalization on clerk.Status {
/// Allow localization of an [clerk.Status]
String localizedMessage(ClerkSdkLocalizations localizations) {
String localizedMessage(ClerkSdkLocalizations l10ns) {
return switch (this) {
clerk.Status.abandoned => localizations.abandoned,
clerk.Status.active => localizations.active,
clerk.Status.complete => localizations.complete,
clerk.Status.expired => localizations.expired,
clerk.Status.failed => localizations.failed,
clerk.Status.missingRequirements => localizations.missingRequirements,
clerk.Status.needsFirstFactor => localizations.needsFirstFactor,
clerk.Status.needsIdentifier => localizations.needsIdentifier,
clerk.Status.needsSecondFactor => localizations.needsSecondFactor,
clerk.Status.pending => localizations.pending,
clerk.Status.transferable => localizations.transferable,
clerk.Status.unverified => localizations.unverified,
clerk.Status.verified => localizations.verified,
clerk.Status.abandoned => l10ns.abandoned,
clerk.Status.active => l10ns.active,
clerk.Status.complete => l10ns.complete,
clerk.Status.expired => l10ns.expired,
clerk.Status.failed => l10ns.failed,
clerk.Status.missingRequirements => l10ns.missingRequirements,
clerk.Status.needsFirstFactor => l10ns.needsFirstFactor,
clerk.Status.needsIdentifier => l10ns.needsIdentifier,
clerk.Status.needsSecondFactor => l10ns.needsSecondFactor,
clerk.Status.pending => l10ns.pending,
clerk.Status.transferable => l10ns.transferable,
clerk.Status.unverified => l10ns.unverified,
clerk.Status.verified => l10ns.verified,
_ => title,
};
}
Expand All @@ -95,30 +88,17 @@ extension ClerkStatusLocalization on clerk.Status {
extension ClerkStrategyLocalization on clerk.Strategy {
/// Allow localization of an [clerk.Strategy]
String localizedMessage(
ClerkSdkLocalizations localizations, {
ClerkSdkLocalizations l10ns, {
bool concise = false,
}) {
if (concise) {
return switch (this) {
clerk.Strategy.resetPasswordEmailCode ||
clerk.Strategy.emailAddress =>
localizations.emailAddressConcise,
clerk.Strategy.resetPasswordPhoneCode ||
clerk.Strategy.phoneNumber =>
localizations.phoneNumberConcise,
clerk.Strategy.username => localizations.username,
_ => toString(),
};
}

return switch (this) {
clerk.Strategy.resetPasswordEmailCode ||
clerk.Strategy.emailAddress =>
localizations.emailAddress,
concise ? l10ns.emailAddressConcise : l10ns.emailAddress,
clerk.Strategy.resetPasswordPhoneCode ||
clerk.Strategy.phoneNumber =>
localizations.phoneNumber,
clerk.Strategy.username => localizations.username,
concise ? l10ns.phoneNumberConcise : l10ns.phoneNumber,
clerk.Strategy.username => l10ns.username,
_ => toString(),
};
}
Expand All @@ -128,11 +108,11 @@ extension ClerkStrategyLocalization on clerk.Strategy {
///
extension ClerkFieldLocalization on clerk.Field {
/// Allow localization of an [clerk.Field]
String localizedMessage(ClerkSdkLocalizations localizations) {
String localizedMessage(ClerkSdkLocalizations l10ns) {
return switch (this) {
clerk.Field.emailAddress => localizations.emailAddress,
clerk.Field.phoneNumber => localizations.phoneNumber,
clerk.Field.username => localizations.username,
clerk.Field.emailAddress => l10ns.emailAddress,
clerk.Field.phoneNumber => l10ns.phoneNumber,
clerk.Field.username => l10ns.username,
_ => name,
};
}
Expand All @@ -142,20 +122,19 @@ extension ClerkFieldLocalization on clerk.Field {
///
extension ClerkUserAttributeLocalization on clerk.UserAttribute {
/// Allow localization of an [clerk.UserAttribute]
String localizedMessage(ClerkSdkLocalizations localizations) {
String localizedMessage(ClerkSdkLocalizations l10ns) {
return switch (this) {
clerk.UserAttribute.emailAddress => localizations.emailAddress,
clerk.UserAttribute.phoneNumber => localizations.phoneNumber,
clerk.UserAttribute.username => localizations.username,
clerk.UserAttribute.firstName => localizations.firstName,
clerk.UserAttribute.lastName => localizations.lastName,
clerk.UserAttribute.password => localizations.password,
clerk.UserAttribute.passwordConfirmation =>
localizations.passwordConfirmation,
clerk.UserAttribute.web3Wallet => localizations.web3Wallet,
clerk.UserAttribute.authenticatorApp => localizations.authenticatorApp,
clerk.UserAttribute.backupCode => localizations.backupCode,
clerk.UserAttribute.passkey => localizations.passkey,
clerk.UserAttribute.emailAddress => l10ns.emailAddress,
clerk.UserAttribute.phoneNumber => l10ns.phoneNumber,
clerk.UserAttribute.username => l10ns.username,
clerk.UserAttribute.firstName => l10ns.firstName,
clerk.UserAttribute.lastName => l10ns.lastName,
clerk.UserAttribute.password => l10ns.password,
clerk.UserAttribute.passwordConfirmation => l10ns.passwordConfirmation,
clerk.UserAttribute.web3Wallet => l10ns.web3Wallet,
clerk.UserAttribute.authenticatorApp => l10ns.authenticatorApp,
clerk.UserAttribute.backupCode => l10ns.backupCode,
clerk.UserAttribute.passkey => l10ns.passkey,
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ class _ClerkSignUpPanelState extends State<ClerkSignUpPanel>
final _values = <clerk.UserAttribute, String?>{};
bool _isObscured = true;

static const _signUpAttributes = [
clerk.UserAttribute.username,
clerk.UserAttribute.emailAddress,
clerk.UserAttribute.phoneNumber,
clerk.UserAttribute.firstName,
clerk.UserAttribute.lastName,
clerk.UserAttribute.password,
];

@override
void didChangeDependencies() {
super.didChangeDependencies();
Expand Down Expand Up @@ -127,11 +136,12 @@ class _ClerkSignUpPanelState extends State<ClerkSignUpPanel>
final hasPassword =
_values[clerk.UserAttribute.password]?.isNotEmpty == true;
final l10ns = authState.localizationsOf(context);
final attributes = authState.env.user.attributes.entries
.where((a) => a.value.isEnabled)
.map(_Attribute.fromMapEntry)
.toList(growable: false)
..sort((a, b) => a.index - b.index);
final attributes = [
for (final attr in _signUpAttributes) //
if (authState.env.user.attributes[attr]
case clerk.UserAttributeData data when data.isEnabled) //
_Attribute(attr, data),
];

bool isMissing(clerk.UserAttribute attr) =>
signUp?.missing(attr.relatedField) == true;
Expand Down Expand Up @@ -189,7 +199,7 @@ class _ClerkSignUpPanelState extends State<ClerkSignUpPanel>
verticalMargin16,
ClerkTextFormField(
initial: _values[clerk.UserAttribute.passwordConfirmation],
label: attribute.title(l10ns),
label: l10ns.grammar.toSentence(l10ns.passwordConfirmation),
isOptional: attribute.isOptional,
obscureText: _isObscured,
onObscure: _onObscure,
Expand Down Expand Up @@ -308,24 +318,17 @@ class _CodeInputBoxState extends State<_CodeInputBox> {
}

class _Attribute {
const _Attribute(this.attr, this.isRequired);

factory _Attribute.fromMapEntry(
MapEntry<clerk.UserAttribute, clerk.UserAttributeData> entry,
) =>
_Attribute(entry.key, entry.value.isRequired);
const _Attribute(this.attr, this.data);

final clerk.UserAttribute attr;

final bool isRequired;

int get index => attr.index;
final clerk.UserAttributeData data;

bool get isPhoneNumber => attr == clerk.UserAttribute.phoneNumber;

bool get isPassword => attr == clerk.UserAttribute.password;

bool get isOptional => isRequired == false;
bool get isOptional => data.isRequired == false;

String title(ClerkSdkLocalizations l10ns) =>
l10ns.grammar.toSentence(attr.localizedMessage(l10ns));
Expand Down