adding i18n base project

This commit is contained in:
Azmat-7860
2026-10-02 22:52:46 +05:30
parent 2527b957aa
commit 47656678e1
11 changed files with 453 additions and 41 deletions
+54 -1
View File
@@ -29,5 +29,58 @@
"update": "Update",
"@update": { "description": "Form update button" },
"edit": "Edit",
"@edit": { "description": "Edit action" }
"@edit": { "description": "Edit action" },
"logout": "Logout",
"@logout": { "description": "Logout button" },
"forgotPassword": "Forgot Password",
"@forgotPassword": { "description": "Forgot password title" },
"email": "Email",
"@email": { "description": "Email label" },
"enterEmail": "Enter Email",
"@enterEmail": { "description": "Email input hint" },
"sendAccessLink": "Send me an access link",
"@sendAccessLink": { "description": "Forgot password submit button" },
"forgotPasswordSentMessage": "An email with a reset link has been sent to {email}.",
"@forgotPasswordSentMessage": {
"description": "Forgot password success message",
"placeholders": { "email": { "type": "String" } }
},
"forgotPasswordFailedMessage": "Failed to send the reset link. Please try again.",
"@forgotPasswordFailedMessage": { "description": "Forgot password failure message" },
"backToLogin": "Click here to return to login",
"@backToLogin": { "description": "Return to login link" },
"provideEmailOrUsername": "You must provide an email or username",
"@provideEmailOrUsername": { "description": "Login email validation" },
"usernameOrEmailHint": "Username or email address",
"@usernameOrEmailHint": { "description": "Login username hint" },
"passwordEmpty": "Password cannot be empty",
"@passwordEmpty": { "description": "Login password validation" },
"password": "Password",
"@password": { "description": "Password hint" },
"stayLoggedIn": "Stay Logged In",
"@stayLoggedIn": { "description": "Stay logged in checkbox" },
"logIn": "Log in",
"@logIn": { "description": "Login button" },
"loginSuccessful": "Login Successful",
"@loginSuccessful": { "description": "Login success snackbar" },
"provideRequiredDetails": "Please provide all required details",
"@provideRequiredDetails": { "description": "Missing details snackbar" },
"processing": "Processing...",
"@processing": { "description": "Processing snackbar" },
"loginTrouble": "Having trouble logging in?",
"@loginTrouble": { "description": "Login help link" },
"orContinueWith": "Or Continue with",
"@orContinueWith": { "description": "Alternative login divider" },
"signUp": "Sign Up",
"@signUp": { "description": "Sign up button" },
"signInGoogle": "Sign in with Google",
"@signInGoogle": { "description": "Google sign in button" },
"signInLinkedin": "Sign in with LinkedIn",
"@signInLinkedin": { "description": "LinkedIn sign in button" },
"loginHelp": "Login Help",
"@loginHelp": { "description": "Login help screen name" },
"alreadyHaveAccount": "Already have an account? Sign in",
"@alreadyHaveAccount": { "description": "Sign in link on signup" },
"language": "Language",
"@language": { "description": "Language section label" }
}
+26 -1
View File
@@ -14,5 +14,30 @@
"camera": "कैमरा",
"submit": "जमा करें",
"update": "अपडेट करें",
"edit": "संपादित करें"
"edit": "संपादित करें",
"logout": "लॉगआउट",
"forgotPassword": "पासवर्ड भूल गए",
"email": "ईमेल",
"enterEmail": "ईमेल दर्ज करें",
"sendAccessLink": "मुझे एक्सेस लिंक भेजें",
"forgotPasswordSentMessage": "{email} पर रीसेट लिंक वाला ईमेल भेजा गया है।",
"forgotPasswordFailedMessage": "रीसेट लिंक भेजने में विफल। कृपया पुनः प्रयास करें।",
"backToLogin": "लॉगिन पर वापस जाने के लिए यहां क्लिक करें",
"provideEmailOrUsername": "आपको ईमेल या उपयोगकर्ता नाम देना होगा",
"usernameOrEmailHint": "उपयोगकर्ता नाम या ईमेल पता",
"passwordEmpty": "पासवर्ड खाली नहीं हो सकता",
"password": "पासवर्ड",
"stayLoggedIn": "लॉग इन रखें",
"logIn": "लॉग इन करें",
"loginSuccessful": "लॉगिन सफल",
"provideRequiredDetails": "कृपया सभी आवश्यक विवरण दें",
"processing": "प्रसंस्करण हो रहा है...",
"loginTrouble": "लॉग इन करने में परेशानी हो रही है?",
"orContinueWith": "या इसके साथ जारी रखें",
"signUp": "साइन अप करें",
"signInGoogle": "Google से साइन इन करें",
"signInLinkedin": "LinkedIn से साइन इन करें",
"loginHelp": "लॉगिन सहायता",
"alreadyHaveAccount": "पहले से खाता है? साइन इन करें",
"language": "भाषा"
}
+150
View File
@@ -187,6 +187,156 @@ abstract class AppLocalizations {
/// In en, this message translates to:
/// **'Edit'**
String get edit;
/// Logout button
///
/// In en, this message translates to:
/// **'Logout'**
String get logout;
/// Forgot password title
///
/// In en, this message translates to:
/// **'Forgot Password'**
String get forgotPassword;
/// Email label
///
/// In en, this message translates to:
/// **'Email'**
String get email;
/// Email input hint
///
/// In en, this message translates to:
/// **'Enter Email'**
String get enterEmail;
/// Forgot password submit button
///
/// In en, this message translates to:
/// **'Send me an access link'**
String get sendAccessLink;
/// Forgot password success message
///
/// In en, this message translates to:
/// **'An email with a reset link has been sent to {email}.'**
String forgotPasswordSentMessage(String email);
/// Forgot password failure message
///
/// In en, this message translates to:
/// **'Failed to send the reset link. Please try again.'**
String get forgotPasswordFailedMessage;
/// Return to login link
///
/// In en, this message translates to:
/// **'Click here to return to login'**
String get backToLogin;
/// Login email validation
///
/// In en, this message translates to:
/// **'You must provide an email or username'**
String get provideEmailOrUsername;
/// Login username hint
///
/// In en, this message translates to:
/// **'Username or email address'**
String get usernameOrEmailHint;
/// Login password validation
///
/// In en, this message translates to:
/// **'Password cannot be empty'**
String get passwordEmpty;
/// Password hint
///
/// In en, this message translates to:
/// **'Password'**
String get password;
/// Stay logged in checkbox
///
/// In en, this message translates to:
/// **'Stay Logged In'**
String get stayLoggedIn;
/// Login button
///
/// In en, this message translates to:
/// **'Log in'**
String get logIn;
/// Login success snackbar
///
/// In en, this message translates to:
/// **'Login Successful'**
String get loginSuccessful;
/// Missing details snackbar
///
/// In en, this message translates to:
/// **'Please provide all required details'**
String get provideRequiredDetails;
/// Processing snackbar
///
/// In en, this message translates to:
/// **'Processing...'**
String get processing;
/// Login help link
///
/// In en, this message translates to:
/// **'Having trouble logging in?'**
String get loginTrouble;
/// Alternative login divider
///
/// In en, this message translates to:
/// **'Or Continue with'**
String get orContinueWith;
/// Sign up button
///
/// In en, this message translates to:
/// **'Sign Up'**
String get signUp;
/// Google sign in button
///
/// In en, this message translates to:
/// **'Sign in with Google'**
String get signInGoogle;
/// LinkedIn sign in button
///
/// In en, this message translates to:
/// **'Sign in with LinkedIn'**
String get signInLinkedin;
/// Login help screen name
///
/// In en, this message translates to:
/// **'Login Help'**
String get loginHelp;
/// Sign in link on signup
///
/// In en, this message translates to:
/// **'Already have an account? Sign in'**
String get alreadyHaveAccount;
/// Language section label
///
/// In en, this message translates to:
/// **'Language'**
String get language;
}
class _AppLocalizationsDelegate
+78
View File
@@ -52,4 +52,82 @@ class AppLocalizationsEn extends AppLocalizations {
@override
String get edit => 'Edit';
@override
String get logout => 'Logout';
@override
String get forgotPassword => 'Forgot Password';
@override
String get email => 'Email';
@override
String get enterEmail => 'Enter Email';
@override
String get sendAccessLink => 'Send me an access link';
@override
String forgotPasswordSentMessage(String email) {
return 'An email with a reset link has been sent to $email.';
}
@override
String get forgotPasswordFailedMessage =>
'Failed to send the reset link. Please try again.';
@override
String get backToLogin => 'Click here to return to login';
@override
String get provideEmailOrUsername => 'You must provide an email or username';
@override
String get usernameOrEmailHint => 'Username or email address';
@override
String get passwordEmpty => 'Password cannot be empty';
@override
String get password => 'Password';
@override
String get stayLoggedIn => 'Stay Logged In';
@override
String get logIn => 'Log in';
@override
String get loginSuccessful => 'Login Successful';
@override
String get provideRequiredDetails => 'Please provide all required details';
@override
String get processing => 'Processing...';
@override
String get loginTrouble => 'Having trouble logging in?';
@override
String get orContinueWith => 'Or Continue with';
@override
String get signUp => 'Sign Up';
@override
String get signInGoogle => 'Sign in with Google';
@override
String get signInLinkedin => 'Sign in with LinkedIn';
@override
String get loginHelp => 'Login Help';
@override
String get alreadyHaveAccount => 'Already have an account? Sign in';
@override
String get language => 'Language';
}
+78
View File
@@ -52,4 +52,82 @@ class AppLocalizationsHi extends AppLocalizations {
@override
String get edit => 'संपादित करें';
@override
String get logout => 'लॉगआउट';
@override
String get forgotPassword => 'पासवर्ड भूल गए';
@override
String get email => 'ईमेल';
@override
String get enterEmail => 'ईमेल दर्ज करें';
@override
String get sendAccessLink => 'मुझे एक्सेस लिंक भेजें';
@override
String forgotPasswordSentMessage(String email) {
return '$email पर रीसेट लिंक वाला ईमेल भेजा गया है।';
}
@override
String get forgotPasswordFailedMessage =>
'रीसेट लिंक भेजने में विफल। कृपया पुनः प्रयास करें।';
@override
String get backToLogin => 'लॉगिन पर वापस जाने के लिए यहां क्लिक करें';
@override
String get provideEmailOrUsername => 'आपको ईमेल या उपयोगकर्ता नाम देना होगा';
@override
String get usernameOrEmailHint => 'उपयोगकर्ता नाम या ईमेल पता';
@override
String get passwordEmpty => 'पासवर्ड खाली नहीं हो सकता';
@override
String get password => 'पासवर्ड';
@override
String get stayLoggedIn => 'लॉग इन रखें';
@override
String get logIn => 'लॉग इन करें';
@override
String get loginSuccessful => 'लॉगिन सफल';
@override
String get provideRequiredDetails => 'कृपया सभी आवश्यक विवरण दें';
@override
String get processing => 'प्रसंस्करण हो रहा है...';
@override
String get loginTrouble => 'लॉग इन करने में परेशानी हो रही है?';
@override
String get orContinueWith => 'या इसके साथ जारी रखें';
@override
String get signUp => 'साइन अप करें';
@override
String get signInGoogle => 'Google से साइन इन करें';
@override
String get signInLinkedin => 'LinkedIn से साइन इन करें';
@override
String get loginHelp => 'लॉगिन सहायता';
@override
String get alreadyHaveAccount => 'पहले से खाता है? साइन इन करें';
@override
String get language => 'भाषा';
}
+2 -1
View File
@@ -4,6 +4,7 @@ import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import '../Screens/Login Screen/login_screen.dart';
import '../l10n/app_localizations.dart';
import '../resources/api_constants.dart';
class LogoutButton extends StatefulWidget {
@@ -18,7 +19,7 @@ class _LogoutButtonState extends State<LogoutButton> {
onPressed: () {
_logoutUser();
},
child: const Text('Logout'),
child: Text(AppLocalizations.of(context)!.logout),
);
}
+19 -14
View File
@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import '../../Utils/color_constants.dart';
import '../../l10n/app_localizations.dart';
import '../../providers/token_manager.dart';
import '../../utilities/make_api_request.dart';
import '../main_app_screen/tabbed_layout_component.dart';
@@ -60,8 +61,9 @@ class LoginFormComponentState extends State<LoginFormComponent> {
}
// ignore: use_build_context_synchronously
ScaffoldMessenger.of(context)
.showSnackBar(const SnackBar(
content: Text("Login Successful"),
.showSnackBar(SnackBar(
content:
Text(AppLocalizations.of(context)!.loginSuccessful),
backgroundColor: Colors.green,
))
.closed
@@ -135,8 +137,8 @@ class LoginFormComponentState extends State<LoginFormComponent> {
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null || value.isEmpty) {
errorMessageSetter(
1, 'You must provide an email or username');
errorMessageSetter(1,
AppLocalizations.of(context)!.provideEmailOrUsername);
} else {
errorMessageSetter(1, "");
@@ -148,7 +150,7 @@ class LoginFormComponentState extends State<LoginFormComponent> {
return null;
},
autocorrect: false,
decoration: const InputDecoration(
decoration: InputDecoration(
fillColor: Colors.white,
border: InputBorder.none,
focusedBorder: InputBorder.none,
@@ -157,7 +159,8 @@ class LoginFormComponentState extends State<LoginFormComponent> {
disabledBorder: InputBorder.none,
contentPadding:
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
hintText: "Username or email address",
hintText:
AppLocalizations.of(context)!.usernameOrEmailHint,
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
),
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
@@ -199,7 +202,8 @@ class LoginFormComponentState extends State<LoginFormComponent> {
onFieldSubmitted: (value) => _validateLoginDetails(),
validator: (value) {
if (value == null || value.isEmpty) {
errorMessageSetter(2, 'Password cannot be empty');
errorMessageSetter(
2, AppLocalizations.of(context)!.passwordEmpty);
} else {
errorMessageSetter(2, "");
setState(() {
@@ -219,7 +223,7 @@ class LoginFormComponentState extends State<LoginFormComponent> {
disabledBorder: InputBorder.none,
contentPadding: const EdgeInsets.only(
left: 15, bottom: 11, top: 11, right: 15),
hintText: "Password",
hintText: AppLocalizations.of(context)!.password,
hintStyle:
const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
suffixIcon: IconButton(
@@ -246,7 +250,7 @@ class LoginFormComponentState extends State<LoginFormComponent> {
),
CheckboxListTile(
activeColor: ColorConstant.blue700,
title: const Text('Stay Logged In'),
title: Text(AppLocalizations.of(context)!.stayLoggedIn),
value: stayLoggedIn,
onChanged: (value) {
setState(() {
@@ -266,8 +270,8 @@ class LoginFormComponentState extends State<LoginFormComponent> {
borderRadius: BorderRadius.circular(20),
),
),
child: const Text(
'Log in',
child: Text(
AppLocalizations.of(context)!.logIn,
style: TextStyle(
fontSize: 16,
color: Colors.white,
@@ -323,8 +327,9 @@ class LoginFormComponentState extends State<LoginFormComponent> {
if (_formKey.currentState!.validate()) {
if (errorMessage1 != "" || errorMessage2 != "") {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Please provide all required details'),
SnackBar(
content: Text(
AppLocalizations.of(context)!.provideRequiredDetails),
backgroundColor: Colors.red,
),
);
@@ -332,7 +337,7 @@ class LoginFormComponentState extends State<LoginFormComponent> {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
onVisible: tryLoggingIn,
content: const Text('Processing...'),
content: Text(AppLocalizations.of(context)!.processing),
backgroundColor: Colors.blue,
),
);
+11 -9
View File
@@ -403,6 +403,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import '../../Utils/color_constants.dart';
import '../../l10n/app_localizations.dart';
import '../../utilities/hadwin_markdown_viewer.dart';
import '../../utilities/slide_right_route.dart';
import '../sign_up_screen/SignUpUser.dart';
@@ -425,22 +426,22 @@ class _LoginScreenState extends State<LoginScreen> {
child: Center(
child: InkWell(
onTap: getLoginHelp,
child: const Text(
'Having trouble logging in?',
child: Text(
AppLocalizations.of(context)!.loginTrouble,
style: TextStyle(fontSize: 14, color: Color(0xFF929BAB)),
), // FOR LOGIN HELP
),
),
);
Widget signUpContainer = const SizedBox(
Widget signUpContainer = SizedBox(
width: double.infinity,
height: 36,
child: Center(
child: InkWell(
//onTap: goToSignUpScreen,
child: Text(
'Or Continue with',
AppLocalizations.of(context)!.orContinueWith,
style: TextStyle(fontSize: 14, color: Color(0xFF929BAB)),
), // FOR SIGN UP
),
@@ -475,7 +476,7 @@ class _LoginScreenState extends State<LoginScreen> {
),
),
child: Text(
'Sign Up',
AppLocalizations.of(context)!.signUp,
style: TextStyle(
fontSize: 16,
color: ColorConstant.blue700,
@@ -507,7 +508,7 @@ class _LoginScreenState extends State<LoginScreen> {
width: 10,
),
Text(
'Sign in with Google',
AppLocalizations.of(context)!.signInGoogle,
style: TextStyle(
fontSize: 16,
color: Colors.grey, //ColorConstant.blue700,
@@ -541,7 +542,7 @@ class _LoginScreenState extends State<LoginScreen> {
width: 10,
),
Text(
'Sign in with LinkedIn',
AppLocalizations.of(context)!.signInLinkedin,
style: TextStyle(
fontSize: 16,
color: Colors.grey, //ColorConstant.blue700,
@@ -568,8 +569,9 @@ class _LoginScreenState extends State<LoginScreen> {
Navigator.push(
context,
SlideRightRoute(
page: const HadWinMarkdownViewer(
screenName: 'Login Help',
page: HadWinMarkdownViewer(
screenName:
AppLocalizations.of(context)!.loginHelp,
urlRequested:
'https://raw.githubusercontent.com/brownboycodes/HADWIN/master/docs/HADWIN_WIKI.md')));
}
@@ -3,6 +3,7 @@ import 'package:http/http.dart' as http;
import '../../Utils/color_constants.dart';
import '../../Utils/image_constant.dart';
import '../../Utils/size_utils.dart';
import '../../l10n/app_localizations.dart';
import '../../providers/token_manager.dart';
import '../../resources/api_constants.dart';
import '../../theme/app_style.dart';
@@ -21,6 +22,7 @@ class ForgotPasswordPage extends StatefulWidget {
class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
final TextEditingController emailController = TextEditingController();
String message = '';
bool linkSent = false;
bool isLoading = false; // Added to track loading state
Future<void> sendForgotPasswordRequest() async {
@@ -42,7 +44,9 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
if (response.statusCode == 200) {
setState(() {
message = 'An email with a reset link has been sent to $email.';
message = AppLocalizations.of(context)!
.forgotPasswordSentMessage(emailController.text);
linkSent = true;
});
// Delay for 3 seconds and then navigate to the login page
@@ -52,7 +56,9 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
});
} else {
setState(() {
message = 'Failed to send the reset link. Please try again.';
message =
AppLocalizations.of(context)!.forgotPasswordFailedMessage;
linkSent = false;
});
}
@@ -76,7 +82,8 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
Navigator.pop(context);
}),
centerTitle: true,
title: AppbarTitle(text: "Forgot Password")),
title: AppbarTitle(
text: AppLocalizations.of(context)!.forgotPassword)),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
@@ -88,19 +95,20 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.start,
children: [
Text("Email",
Text(AppLocalizations.of(context)!.email,
overflow: TextOverflow.ellipsis,
textAlign: TextAlign.left,
style: AppStyle.txtGilroyMedium16Bluegray900),
CustomTextFormField(
focusNode: FocusNode(),
hintText: "Enter Email",
hintText:
AppLocalizations.of(context)!.enterEmail,
controller: emailController,
margin: getMargin(top: 6))
])),
CustomButton(
height: getVerticalSize(50),
text: "Send me an access link",
text: AppLocalizations.of(context)!.sendAccessLink,
margin: getMargin(top: 24, bottom: 5),
onTap: () async {
sendForgotPasswordRequest();
@@ -111,9 +119,10 @@ class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
color: ColorConstant.blue700,
) // Show loading indicator when isLoading is true
: Text(message, style: AppStyle.txtGilroyMedium16Bluegray900),
if (message.contains('An email with a reset link'))
if (linkSent)
InkWell(
child: Text('Click here to return to login',
child: Text(
AppLocalizations.of(context)!.backToLogin,
style: AppStyle.txtGilroyMedium16Bluegray900),
onTap: () {
Navigator.push(
@@ -6,6 +6,7 @@ import 'package:image_picker/image_picker.dart';
import '../../Utils/image_constant.dart';
import '../../Utils/size_utils.dart';
import '../../l10n/app_localizations.dart';
import '../../providers/token_manager.dart';
import '../../resources/api_constants.dart';
import '../../theme/app_style.dart';
@@ -14,6 +15,7 @@ import '../../widgets/app_bar/appbar_title.dart';
import '../../widgets/app_bar/custom_app_bar.dart';
import '../../widgets/custom_button.dart';
import '../../widgets/custom_text_form_field.dart';
import '../../widgets/language_switcher.dart';
import '../Login Screen/login_screen.dart';
import '../LogoutService/Logoutservice.dart';
import 'apiserviceprofilemanagement.dart';
@@ -332,6 +334,14 @@ class _ProfileSettingsScreenState extends State<ProfileSettingsScreen> {
),
),
SizedBox(height: 20),
// Section: App language (EN | HI) - switches ARB + dynamic strings together
Text(
AppLocalizations.of(context)!.language,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
SizedBox(height: 10),
const LanguageSwitcher(),
SizedBox(height: 20),
// Section: Profile Form
Text(
@@ -1,5 +1,6 @@
import 'package:flutter/material.dart';
import '../../l10n/app_localizations.dart';
import 'sign_up_steps.dart';
class SignUpScreen extends StatefulWidget {
@@ -35,13 +36,13 @@ class _SignUpScreenState extends State<SignUpScreen> {
SizedBox(
width: double.infinity,
height: 16,
child: Center(
child: InkWell(
child: const Text(
'Already have an account? Sign in',
style:
TextStyle(fontSize: 14, color: Color(0xFF929BAB)),
),
child: Center(
child: InkWell(
child: Text(
AppLocalizations.of(context)!.alreadyHaveAccount,
style: TextStyle(
fontSize: 14, color: Color(0xFF929BAB)),
),
onTap: () {
Navigator.pop(context);
},