From 60c243ba20e5cefade7f1e55d4c1480de66fcf1d Mon Sep 17 00:00:00 2001 From: Gyanu Date: Sun, 21 Dec 2025 19:01:08 +0530 Subject: [PATCH 1/4] Implement multi-language support with language selection screen - Add support for 10 languages: English, Chinese, Hindi, Spanish, Arabic, French, Bengali, Portuguese, Russian, Urdu - Create LocaleHelper utility class for managing locale changes - Add UpdateAppApplication class to initialize locale on app start - Implement LanguageActivity with RecyclerView for language selection - Create LanguageAdapter and LanguageModel for language list - Add strings.xml files for all supported languages - Update MainActivity and LanguageActivity to support locale changes - Language preference persists after app restart - Immediate language switching when language is selected Fixes #7 --- app/src/main/AndroidManifest.xml | 1 + .../updateapp/Helpers/LocaleHelper.java | 53 +++++++++++ .../com/example/updateapp/MainActivity.java | 7 ++ .../updateapp/UpdateAppApplication.java | 13 +++ .../updateapp/adapters/LanguageAdapter.java | 73 +++++++++++++++ .../updateapp/models/LanguageModel.java | 37 ++++++++ .../views/activites/LanguageActivity.java | 88 +++++++++++++++++++ .../views/fragments/ProfileFragment.java | 2 - app/src/main/res/layout/item_language.xml | 26 ++++++ app/src/main/res/values-ar/strings.xml | 16 ++++ app/src/main/res/values-bn/strings.xml | 16 ++++ app/src/main/res/values-es/strings.xml | 16 ++++ app/src/main/res/values-fr/strings.xml | 16 ++++ app/src/main/res/values-hi/strings.xml | 16 ++++ app/src/main/res/values-pt/strings.xml | 16 ++++ app/src/main/res/values-ru/strings.xml | 16 ++++ app/src/main/res/values-ur/strings.xml | 16 ++++ app/src/main/res/values-zh/strings.xml | 16 ++++ app/src/main/res/values/strings.xml | 11 +++ 19 files changed, 453 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java create mode 100644 app/src/main/java/com/example/updateapp/UpdateAppApplication.java create mode 100644 app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java create mode 100644 app/src/main/java/com/example/updateapp/models/LanguageModel.java create mode 100644 app/src/main/res/layout/item_language.xml create mode 100644 app/src/main/res/values-ar/strings.xml create mode 100644 app/src/main/res/values-bn/strings.xml create mode 100644 app/src/main/res/values-es/strings.xml create mode 100644 app/src/main/res/values-fr/strings.xml create mode 100644 app/src/main/res/values-hi/strings.xml create mode 100644 app/src/main/res/values-pt/strings.xml create mode 100644 app/src/main/res/values-ru/strings.xml create mode 100644 app/src/main/res/values-ur/strings.xml create mode 100644 app/src/main/res/values-zh/strings.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5c94866..8964d7d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ = Build.VERSION_CODES.N) { + configuration.setLocale(locale); + } else { + configuration.locale = locale; + } + + context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); + + // Save language preference + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + prefs.edit().putString(KEY_LANGUAGE, languageCode).apply(); + } + + public static Context attachBaseContext(Context context) { + String languageCode = getSavedLanguage(context); + Locale locale = new Locale(languageCode); + Locale.setDefault(locale); + + Configuration configuration = context.getResources().getConfiguration(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + configuration.setLocale(locale); + return context.createConfigurationContext(configuration); + } else { + configuration.locale = locale; + context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); + return context; + } + } + + public static String getSavedLanguage(Context context) { + SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + return prefs.getString(KEY_LANGUAGE, "en"); // Default to English + } +} diff --git a/app/src/main/java/com/example/updateapp/MainActivity.java b/app/src/main/java/com/example/updateapp/MainActivity.java index 57ab71d..9e02f23 100644 --- a/app/src/main/java/com/example/updateapp/MainActivity.java +++ b/app/src/main/java/com/example/updateapp/MainActivity.java @@ -1,9 +1,11 @@ package com.example.updateapp; +import android.content.Context; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.databinding.ActivityMainBinding; import com.example.updateapp.views.fragments.ChatbotFragment; import com.example.updateapp.views.fragments.ProfileFragment; @@ -54,4 +56,9 @@ private void loadFragment(Fragment fragment) { transaction.commit(); } + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/UpdateAppApplication.java b/app/src/main/java/com/example/updateapp/UpdateAppApplication.java new file mode 100644 index 0000000..fcd5e7a --- /dev/null +++ b/app/src/main/java/com/example/updateapp/UpdateAppApplication.java @@ -0,0 +1,13 @@ +package com.example.updateapp; + +import android.app.Application; +import android.content.Context; + +import com.example.updateapp.Helpers.LocaleHelper; + +public class UpdateAppApplication extends Application { + @Override + protected void attachBaseContext(Context base) { + super.attachBaseContext(LocaleHelper.attachBaseContext(base)); + } +} diff --git a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java new file mode 100644 index 0000000..5593c37 --- /dev/null +++ b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java @@ -0,0 +1,73 @@ +package com.example.updateapp.adapters; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.example.updateapp.R; +import com.example.updateapp.models.LanguageModel; + +import java.util.List; + +public class LanguageAdapter extends RecyclerView.Adapter { + + private List languageList; + private OnLanguageClickListener listener; + + public interface OnLanguageClickListener { + void onLanguageClick(LanguageModel language); + } + + public LanguageAdapter(List languageList, OnLanguageClickListener listener) { + this.languageList = languageList; + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_language, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + LanguageModel language = languageList.get(position); + holder.languageName.setText(language.getLanguageName()); + holder.selectedIcon.setVisibility(language.isSelected() ? View.VISIBLE : View.GONE); + + holder.itemView.setOnClickListener(v -> { + if (listener != null) { + listener.onLanguageClick(language); + } + }); + } + + @Override + public int getItemCount() { + return languageList.size(); + } + + public void updateSelection(String selectedLanguageCode) { + for (LanguageModel language : languageList) { + language.setSelected(language.getLanguageCode().equals(selectedLanguageCode)); + } + notifyDataSetChanged(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + TextView languageName; + ImageView selectedIcon; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + languageName = itemView.findViewById(R.id.txt_language_name); + selectedIcon = itemView.findViewById(R.id.img_selected); + } + } +} diff --git a/app/src/main/java/com/example/updateapp/models/LanguageModel.java b/app/src/main/java/com/example/updateapp/models/LanguageModel.java new file mode 100644 index 0000000..0b6e8ea --- /dev/null +++ b/app/src/main/java/com/example/updateapp/models/LanguageModel.java @@ -0,0 +1,37 @@ +package com.example.updateapp.models; + +public class LanguageModel { + private String languageCode; + private String languageName; + private boolean isSelected; + + public LanguageModel(String languageCode, String languageName, boolean isSelected) { + this.languageCode = languageCode; + this.languageName = languageName; + this.isSelected = isSelected; + } + + public String getLanguageCode() { + return languageCode; + } + + public void setLanguageCode(String languageCode) { + this.languageCode = languageCode; + } + + public String getLanguageName() { + return languageName; + } + + public void setLanguageName(String languageName) { + this.languageName = languageName; + } + + public boolean isSelected() { + return isSelected; + } + + public void setSelected(boolean selected) { + isSelected = selected; + } +} diff --git a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java index afb5e59..1b8ab25 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java @@ -1,17 +1,35 @@ package com.example.updateapp.views.activites; +import android.content.Context; +import android.content.Intent; import android.os.Bundle; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.R; +import com.example.updateapp.adapters.LanguageAdapter; +import com.example.updateapp.models.LanguageModel; + +import java.util.ArrayList; +import java.util.List; public class LanguageActivity extends AppCompatActivity { + private RecyclerView recyclerView; + private LanguageAdapter adapter; + private List languageList; + private String currentLanguageCode; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -22,5 +40,75 @@ protected void onCreate(Bundle savedInstanceState) { v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom); return insets; }); + + // Initialize views + recyclerView = findViewById(R.id.rev_langauge); + TextView titleText = findViewById(R.id.txt_title); + ImageView doneButton = findViewById(R.id.img_done); + + // Get current language + currentLanguageCode = LocaleHelper.getSavedLanguage(this); + + // Setup RecyclerView + languageList = createLanguageList(); + adapter = new LanguageAdapter(languageList, this::onLanguageSelected); + recyclerView.setLayoutManager(new LinearLayoutManager(this)); + recyclerView.setAdapter(adapter); + + // Update selection UI + adapter.updateSelection(currentLanguageCode); + + // Done button click handler + doneButton.setOnClickListener(v -> finish()); + + // Set title + titleText.setText(getString(R.string.language)); + } + + private List createLanguageList() { + List list = new ArrayList<>(); + String[] languageCodes = {"en", "zh", "hi", "es", "ar", "fr", "bn", "pt", "ru", "ur"}; + String[] languageNames = { + getString(R.string.language_english), + getString(R.string.language_chinese), + getString(R.string.language_hindi), + getString(R.string.language_spanish), + getString(R.string.language_arabic), + getString(R.string.language_french), + getString(R.string.language_bengali), + getString(R.string.language_portuguese), + getString(R.string.language_russian), + getString(R.string.language_urdu) + }; + + for (int i = 0; i < languageCodes.length; i++) { + boolean isSelected = languageCodes[i].equals(currentLanguageCode); + list.add(new LanguageModel(languageCodes[i], languageNames[i], isSelected)); + } + + return list; + } + + private void onLanguageSelected(LanguageModel language) { + String selectedLanguageCode = language.getLanguageCode(); + + if (!selectedLanguageCode.equals(currentLanguageCode)) { + // Save and apply new language + LocaleHelper.setLocale(this, selectedLanguageCode); + + // Update current language + currentLanguageCode = selectedLanguageCode; + + // Update adapter selection + adapter.updateSelection(selectedLanguageCode); + + // Restart activity to apply language changes immediately + recreate(); + } + } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/fragments/ProfileFragment.java b/app/src/main/java/com/example/updateapp/views/fragments/ProfileFragment.java index 988fe58..0b14bd0 100644 --- a/app/src/main/java/com/example/updateapp/views/fragments/ProfileFragment.java +++ b/app/src/main/java/com/example/updateapp/views/fragments/ProfileFragment.java @@ -121,8 +121,6 @@ public void onClick(View v) { binding.relLang.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - - Toast.makeText(requireContext(), "Coming Soon", Toast.LENGTH_SHORT).show(); Intent intent = new Intent(getContext(), LanguageActivity.class); startActivity(intent); } diff --git a/app/src/main/res/layout/item_language.xml b/app/src/main/res/layout/item_language.xml new file mode 100644 index 0000000..d9130f7 --- /dev/null +++ b/app/src/main/res/layout/item_language.xml @@ -0,0 +1,26 @@ + + + + + + + + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml new file mode 100644 index 0000000..4bff932 --- /dev/null +++ b/app/src/main/res/values-ar/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + اللغة + الإنجليزية + الصينية + الهندية + الإسبانية + العربية + الفرنسية + البنغالية + البرتغالية + الروسية + الأردية + diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml new file mode 100644 index 0000000..d918930 --- /dev/null +++ b/app/src/main/res/values-bn/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + ভাষা + ইংরেজি + চীনা + হিন্দি + স্প্যানিশ + আরবি + ফরাসি + বাংলা + পর্তুগিজ + রাশিয়ান + উর্দু + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml new file mode 100644 index 0000000..03a1f32 --- /dev/null +++ b/app/src/main/res/values-es/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + Idioma + Inglés + Chino + Hindi + Español + Árabe + Francés + Bengalí + Portugués + Ruso + Urdu + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml new file mode 100644 index 0000000..4e053ba --- /dev/null +++ b/app/src/main/res/values-fr/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + Langue + Anglais + Chinois + Hindi + Espagnol + Arabe + Français + Bengali + Portugais + Russe + Ourdou + diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml new file mode 100644 index 0000000..8bcf1f7 --- /dev/null +++ b/app/src/main/res/values-hi/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + भाषा + अंग्रेजी + चीनी + हिन्दी + स्पेनिश + अरबी + फ्रेंच + बंगाली + पुर्तगाली + रूसी + उर्दू + diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml new file mode 100644 index 0000000..481ee7f --- /dev/null +++ b/app/src/main/res/values-pt/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + Idioma + Inglês + Chinês + Hindi + Espanhol + Árabe + Francês + Bengali + Português + Russo + Urdu + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml new file mode 100644 index 0000000..369c07e --- /dev/null +++ b/app/src/main/res/values-ru/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + Язык + Английский + Китайский + Хинди + Испанский + Арабский + Французский + Бенгальский + Португальский + Русский + Урду + diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml new file mode 100644 index 0000000..05e84b3 --- /dev/null +++ b/app/src/main/res/values-ur/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + زبان + انگریزی + چینی + ہندی + ہسپانوی + عربی + فرانسیسی + بنگالی + پرتگالی + روسی + اردو + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml new file mode 100644 index 0000000..de359fc --- /dev/null +++ b/app/src/main/res/values-zh/strings.xml @@ -0,0 +1,16 @@ + + UpdateApp + Hello blank fragment + 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + 语言 + 英语 + 中文 + 印地语 + 西班牙语 + 阿拉伯语 + 法语 + 孟加拉语 + 葡萄牙语 + 俄语 + 乌尔都语 + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2869aff..a9ee1dd 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -3,4 +3,15 @@ Hello blank fragment 610596201338-8jkqtv5msdu5q7mi0qs0gho2tu8a8esv.apps.googleusercontent.com + Language + English + 中文 + हिन्दी + Español + العربية + Français + বাংলা + Português + Русский + اردو \ No newline at end of file From 87743a4ee335a91bd6ef2a47c4377730b50bd862 Mon Sep 17 00:00:00 2001 From: Gyanu Date: Mon, 22 Dec 2025 23:59:30 +0530 Subject: [PATCH 2/4] Implement multi-language support with language selection screen - Add first-launch language selection in SplashScreenActivity - Integrate LocaleHelper in all activities for consistent language support - Update LanguageActivity to handle first-launch navigation - Add language selection tracking using SaveState - Support for 10 languages: English, Chinese, Hindi, Spanish, Arabic, French, Bengali, Portuguese, Russian, Urdu --- .../updateapp/Helpers/LocaleHelper.java | 1 + .../updateapp/UpdateAppApplication.java | 1 + .../updateapp/adapters/LanguageAdapter.java | 1 + .../updateapp/models/LanguageModel.java | 1 + .../views/activites/ForgetActivity.java | 7 ++++++ .../views/activites/LanguageActivity.java | 18 +++++++++++++- .../views/activites/LoginActivity.java | 9 ++++++- .../views/activites/NewUpdateActivity.java | 7 ++++++ .../views/activites/OTPActivity.java | 6 +++++ .../views/activites/OnboardingActivity.java | 7 ++++++ .../views/activites/SignUpActivity.java | 7 ++++++ .../views/activites/SplashScreenActivity.java | 24 ++++++++++++++++--- app/src/main/res/layout/item_language.xml | 1 + app/src/main/res/values-ar/strings.xml | 1 + app/src/main/res/values-bn/strings.xml | 1 + app/src/main/res/values-es/strings.xml | 1 + app/src/main/res/values-fr/strings.xml | 1 + app/src/main/res/values-hi/strings.xml | 1 + app/src/main/res/values-pt/strings.xml | 1 + app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values-ur/strings.xml | 1 + app/src/main/res/values-zh/strings.xml | 1 + 22 files changed, 94 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java b/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java index 202a88c..8e25e43 100644 --- a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java +++ b/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java @@ -51,3 +51,4 @@ public static String getSavedLanguage(Context context) { return prefs.getString(KEY_LANGUAGE, "en"); // Default to English } } + diff --git a/app/src/main/java/com/example/updateapp/UpdateAppApplication.java b/app/src/main/java/com/example/updateapp/UpdateAppApplication.java index fcd5e7a..d734aa6 100644 --- a/app/src/main/java/com/example/updateapp/UpdateAppApplication.java +++ b/app/src/main/java/com/example/updateapp/UpdateAppApplication.java @@ -11,3 +11,4 @@ protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.attachBaseContext(base)); } } + diff --git a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java index 5593c37..c83a3f4 100644 --- a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java +++ b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java @@ -71,3 +71,4 @@ public ViewHolder(@NonNull View itemView) { } } } + diff --git a/app/src/main/java/com/example/updateapp/models/LanguageModel.java b/app/src/main/java/com/example/updateapp/models/LanguageModel.java index 0b6e8ea..b19132f 100644 --- a/app/src/main/java/com/example/updateapp/models/LanguageModel.java +++ b/app/src/main/java/com/example/updateapp/models/LanguageModel.java @@ -35,3 +35,4 @@ public void setSelected(boolean selected) { isSelected = selected; } } + diff --git a/app/src/main/java/com/example/updateapp/views/activites/ForgetActivity.java b/app/src/main/java/com/example/updateapp/views/activites/ForgetActivity.java index 3eb8195..16fc476 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/ForgetActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/ForgetActivity.java @@ -1,6 +1,7 @@ package com.example.updateapp.views.activites; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; @@ -9,6 +10,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.databinding.ActivityForgetBinding; import com.google.android.gms.tasks.OnCompleteListener; import com.google.android.gms.tasks.Task; @@ -81,4 +83,9 @@ public void onClick(View v) { } }); } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java index 1b8ab25..6c5f949 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java @@ -16,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView; import com.example.updateapp.Helpers.LocaleHelper; +import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.R; import com.example.updateapp.adapters.LanguageAdapter; import com.example.updateapp.models.LanguageModel; @@ -59,7 +60,18 @@ protected void onCreate(Bundle savedInstanceState) { adapter.updateSelection(currentLanguageCode); // Done button click handler - doneButton.setOnClickListener(v -> finish()); + doneButton.setOnClickListener(v -> { + // Check if this is first launch + boolean isFirstLaunch = getIntent().getBooleanExtra("isFirstLaunch", false); + if (isFirstLaunch) { + // Mark language as selected and go to onboarding + SaveState languageState = new SaveState(this, "LANGUAGE_SELECTED"); + languageState.setState(1); + Intent intent = new Intent(LanguageActivity.this, OnboardingActivity.class); + startActivity(intent); + } + finish(); + }); // Set title titleText.setText(getString(R.string.language)); @@ -96,6 +108,10 @@ private void onLanguageSelected(LanguageModel language) { // Save and apply new language LocaleHelper.setLocale(this, selectedLanguageCode); + // Mark language as selected (for first launch) + SaveState languageState = new SaveState(this, "LANGUAGE_SELECTED"); + languageState.setState(1); + // Update current language currentLanguageCode = selectedLanguageCode; diff --git a/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java index a441f8d..f5e9b1f 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java @@ -1,6 +1,7 @@ package com.example.updateapp.views.activites; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.View; @@ -11,6 +12,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.MainActivity; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivityLoginBinding; @@ -220,8 +222,13 @@ public void onComplete(@NonNull Task task) { this, "Google Sign-In Error: " + e.getStatusCode() + "\n" + e.getMessage(), Toast.LENGTH_LONG - ).show(); + ) .show(); } } } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java b/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java index 9282df4..74d470c 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java @@ -1,5 +1,6 @@ package com.example.updateapp.views.activites; +import android.content.Context; import android.os.Bundle; import android.view.View; import android.view.WindowManager; @@ -10,6 +11,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivityNewUpdateBinding; @@ -33,4 +35,9 @@ public void onClick(View view) { } }); } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java b/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java index 0909505..c5d8bd8 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java @@ -1,6 +1,7 @@ package com.example.updateapp.views.activites; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.Editable; @@ -15,6 +16,7 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.MainActivity; import com.example.updateapp.databinding.ActivityOtpactivityBinding; import com.example.updateapp.models.UserModel; @@ -225,4 +227,8 @@ private void saveUserToFirestoreAndContinue(String uid, String name, String emai }); } + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java b/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java index 413f1e6..732ca9a 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java @@ -1,5 +1,6 @@ package com.example.updateapp.views.activites; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.text.Html; @@ -12,6 +13,7 @@ import androidx.cardview.widget.CardView; import androidx.viewpager.widget.ViewPager; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.R; import com.example.updateapp.adapters.OnboardingAdapter; @@ -113,4 +115,9 @@ public void onPageScrollStateChanged(int state) { } }; + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java b/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java index b638804..22830ac 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java @@ -1,6 +1,7 @@ package com.example.updateapp.views.activites; import android.app.ProgressDialog; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.WindowManager; @@ -10,6 +11,7 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivitySignUpBinding; import com.google.firebase.FirebaseException; @@ -161,4 +163,9 @@ private void goToOtpScreen(String name, String email, String number, String pass startActivity(intent); } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java b/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java index 5c416f4..681595d 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java @@ -1,5 +1,6 @@ package com.example.updateapp.views.activites; +import android.content.Context; import android.content.Intent; import android.os.Bundle; import android.view.WindowManager; @@ -10,6 +11,8 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; +import com.example.updateapp.Helpers.LocaleHelper; +import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.R; import java.util.Timer; @@ -26,6 +29,9 @@ protected void onCreate(Bundle savedInstanceState) { ); setContentView(R.layout.activity_splash_screen); + // Check if language has been selected before + SaveState languageState = new SaveState(this, "LANGUAGE_SELECTED"); + boolean languageSelected = languageState.getState() == 1; new Timer().schedule(new TimerTask() { @Override @@ -33,13 +39,25 @@ public void run() { runOnUiThread(new Runnable() { @Override public void run() { - Intent intent = new Intent(); - intent.setClass(SplashScreenActivity.this, OnboardingActivity.class); + Intent intent; + if (!languageSelected) { + // Show language selection screen on first launch + intent = new Intent(SplashScreenActivity.this, LanguageActivity.class); + intent.putExtra("isFirstLaunch", true); + } else { + // Go to onboarding + intent = new Intent(SplashScreenActivity.this, OnboardingActivity.class); + } startActivity(intent); finish(); } }); } - },500); + }, 500); + } + + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); } } \ No newline at end of file diff --git a/app/src/main/res/layout/item_language.xml b/app/src/main/res/layout/item_language.xml index d9130f7..8aadc7c 100644 --- a/app/src/main/res/layout/item_language.xml +++ b/app/src/main/res/layout/item_language.xml @@ -24,3 +24,4 @@ android:visibility="gone" /> + diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 4bff932..d2217e7 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -14,3 +14,4 @@ الروسية الأردية + diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index d918930..04b3ff0 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -14,3 +14,4 @@ রাশিয়ান উর্দু + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 03a1f32..cb4d125 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -14,3 +14,4 @@ Ruso Urdu + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 4e053ba..951c4c6 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -14,3 +14,4 @@ Russe Ourdou + diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 8bcf1f7..7910cf6 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -14,3 +14,4 @@ रूसी उर्दू + diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 481ee7f..74e1618 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -14,3 +14,4 @@ Russo Urdu + diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 369c07e..82d878c 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -14,3 +14,4 @@ Русский Урду + diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 05e84b3..a39702f 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -14,3 +14,4 @@ روسی اردو + diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index de359fc..ba3cf69 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -14,3 +14,4 @@ 俄语 乌尔都语 + From 0e4d5c3f7117ab0a2cbcf700968a67781ade0d4e Mon Sep 17 00:00:00 2001 From: Gyanu Date: Tue, 23 Dec 2025 22:10:16 +0530 Subject: [PATCH 3/4] Fix multi-language support: correct typo, remove deprecated methods, improve back button handling - Fix typo: rev_langauge -> rev_language in layout and Java file - Remove deprecated updateConfiguration() call from LocaleHelper.setLocale() - Remove unused Resources import - Replace deprecated onBackPressed() with OnBackPressedCallback - Prevent back navigation on first launch (user must select language) - All language translations verified complete --- .../example/updateapp/Helpers/LocaleHelper.java | 13 +++---------- .../views/activites/LanguageActivity.java | 14 +++++++++++++- app/src/main/res/layout/activity_language.xml | 2 +- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java b/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java index 8e25e43..7dab015 100644 --- a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java +++ b/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java @@ -3,7 +3,6 @@ import android.content.Context; import android.content.SharedPreferences; import android.content.res.Configuration; -import android.content.res.Resources; import android.os.Build; import java.util.Locale; @@ -16,18 +15,12 @@ public static void setLocale(Context context, String languageCode) { Locale locale = new Locale(languageCode); Locale.setDefault(locale); - Configuration configuration = context.getResources().getConfiguration(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - configuration.setLocale(locale); - } else { - configuration.locale = locale; - } - - context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); - // Save language preference SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); prefs.edit().putString(KEY_LANGUAGE, languageCode).apply(); + + // Note: Configuration update is handled by attachBaseContext when activity is recreated + // This avoids using deprecated updateConfiguration method } public static Context attachBaseContext(Context context) { diff --git a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java index 6c5f949..809923b 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.activity.EdgeToEdge; +import androidx.activity.OnBackPressedCallback; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; @@ -43,7 +44,7 @@ protected void onCreate(Bundle savedInstanceState) { }); // Initialize views - recyclerView = findViewById(R.id.rev_langauge); + recyclerView = findViewById(R.id.rev_language); TextView titleText = findViewById(R.id.txt_title); ImageView doneButton = findViewById(R.id.img_done); @@ -75,6 +76,17 @@ protected void onCreate(Bundle savedInstanceState) { // Set title titleText.setText(getString(R.string.language)); + + // Handle back button behavior + boolean isFirstLaunch = getIntent().getBooleanExtra("isFirstLaunch", false); + OnBackPressedCallback callback = new OnBackPressedCallback(!isFirstLaunch) { + @Override + public void handleOnBackPressed() { + // For normal access, allow back navigation + finish(); + } + }; + getOnBackPressedDispatcher().addCallback(this, callback); } private List createLanguageList() { diff --git a/app/src/main/res/layout/activity_language.xml b/app/src/main/res/layout/activity_language.xml index 0a894f9..3d97f6f 100644 --- a/app/src/main/res/layout/activity_language.xml +++ b/app/src/main/res/layout/activity_language.xml @@ -73,7 +73,7 @@ android:layout_below="@+id/rel_top"> Date: Mon, 31 Aug 2026 18:27:30 +0530 Subject: [PATCH 4/4] Fix app-wide locale and English fallback Keep a single LocaleHelper, persist English as en with no country, and apply it through AppCompatDelegate plus a full-task restart so every screen follows the choice. Move remaining hardcoded copy into strings.xml for all locales and give the language list a selected state. --- .../updateapp/Helpers/LocaleHelper.java | 47 ---- .../com/example/updateapp/MainActivity.java | 1 - .../updateapp/UpdateAppApplication.java | 14 -- .../example/updateapp/UpdateApplication.java | 10 + .../updateapp/adapters/LanguageAdapter.java | 26 ++- .../updateapp/adapters/OnboardingAdapter.java | 43 ++-- .../example/updateapp/utils/LocaleHelper.java | 128 ++++++----- .../views/activites/LanguageActivity.java | 95 ++++---- .../views/activites/LoginActivity.java | 1 - .../views/activites/NewUpdateActivity.java | 1 - .../views/activites/OTPActivity.java | 3 +- .../views/activites/OnboardingActivity.java | 1 - .../views/activites/SignUpActivity.java | 1 - .../views/activites/SplashScreenActivity.java | 46 ++-- .../views/fragments/ChatbotFragment.java | 11 +- .../main/res/drawable/bg_language_item.xml | 6 + .../drawable/bg_language_item_selected.xml | 9 + app/src/main/res/layout/activity_forget.xml | 2 +- app/src/main/res/layout/activity_language.xml | 204 +++++------------- .../main/res/layout/activity_new_update.xml | 4 +- .../res/layout/activity_splash_screen.xml | 4 +- app/src/main/res/layout/fragment_chatbot.xml | 2 +- app/src/main/res/layout/item_language.xml | 36 ++-- app/src/main/res/layout/item_message.xml | 6 +- app/src/main/res/layout/slide.xml | 4 +- app/src/main/res/menu/bottom_menu.xml | 4 +- app/src/main/res/values-ar/strings.xml | 14 ++ app/src/main/res/values-bn/strings.xml | 14 ++ app/src/main/res/values-es/strings.xml | 14 ++ app/src/main/res/values-fr/strings.xml | 14 ++ app/src/main/res/values-hi/strings.xml | 14 ++ app/src/main/res/values-pt/strings.xml | 14 ++ app/src/main/res/values-ru/strings.xml | 14 ++ app/src/main/res/values-ur/strings.xml | 14 ++ app/src/main/res/values-zh/strings.xml | 14 ++ app/src/main/res/values/strings.xml | 14 ++ 36 files changed, 424 insertions(+), 425 deletions(-) delete mode 100644 app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java delete mode 100644 app/src/main/java/com/example/updateapp/UpdateAppApplication.java create mode 100644 app/src/main/res/drawable/bg_language_item.xml create mode 100644 app/src/main/res/drawable/bg_language_item_selected.xml diff --git a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java b/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java deleted file mode 100644 index 7dab015..0000000 --- a/app/src/main/java/com/example/updateapp/Helpers/LocaleHelper.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.example.updateapp.Helpers; - -import android.content.Context; -import android.content.SharedPreferences; -import android.content.res.Configuration; -import android.os.Build; - -import java.util.Locale; - -public class LocaleHelper { - private static final String PREFS_NAME = "app_prefs"; - private static final String KEY_LANGUAGE = "selected_language"; - - public static void setLocale(Context context, String languageCode) { - Locale locale = new Locale(languageCode); - Locale.setDefault(locale); - - // Save language preference - SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - prefs.edit().putString(KEY_LANGUAGE, languageCode).apply(); - - // Note: Configuration update is handled by attachBaseContext when activity is recreated - // This avoids using deprecated updateConfiguration method - } - - public static Context attachBaseContext(Context context) { - String languageCode = getSavedLanguage(context); - Locale locale = new Locale(languageCode); - Locale.setDefault(locale); - - Configuration configuration = context.getResources().getConfiguration(); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - configuration.setLocale(locale); - return context.createConfigurationContext(configuration); - } else { - configuration.locale = locale; - context.getResources().updateConfiguration(configuration, context.getResources().getDisplayMetrics()); - return context; - } - } - - public static String getSavedLanguage(Context context) { - SharedPreferences prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - return prefs.getString(KEY_LANGUAGE, "en"); // Default to English - } -} - diff --git a/app/src/main/java/com/example/updateapp/MainActivity.java b/app/src/main/java/com/example/updateapp/MainActivity.java index 1994849..e3aa67d 100644 --- a/app/src/main/java/com/example/updateapp/MainActivity.java +++ b/app/src/main/java/com/example/updateapp/MainActivity.java @@ -5,7 +5,6 @@ import androidx.appcompat.app.AppCompatActivity; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentTransaction; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.databinding.ActivityMainBinding; import com.example.updateapp.utils.LocaleHelper; import com.example.updateapp.views.fragments.ChatbotFragment; diff --git a/app/src/main/java/com/example/updateapp/UpdateAppApplication.java b/app/src/main/java/com/example/updateapp/UpdateAppApplication.java deleted file mode 100644 index d734aa6..0000000 --- a/app/src/main/java/com/example/updateapp/UpdateAppApplication.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.example.updateapp; - -import android.app.Application; -import android.content.Context; - -import com.example.updateapp.Helpers.LocaleHelper; - -public class UpdateAppApplication extends Application { - @Override - protected void attachBaseContext(Context base) { - super.attachBaseContext(LocaleHelper.attachBaseContext(base)); - } -} - diff --git a/app/src/main/java/com/example/updateapp/UpdateApplication.java b/app/src/main/java/com/example/updateapp/UpdateApplication.java index 71de640..4d22ba3 100644 --- a/app/src/main/java/com/example/updateapp/UpdateApplication.java +++ b/app/src/main/java/com/example/updateapp/UpdateApplication.java @@ -11,4 +11,14 @@ public class UpdateApplication extends Application { protected void attachBaseContext(Context base) { super.attachBaseContext(LocaleHelper.onAttach(base, "en")); } + + @Override + public void onCreate() { + super.onCreate(); + LocaleHelper.setLocale( + this, + LocaleHelper.getLanguage(this), + LocaleHelper.getCountry(this) + ); + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java index b4f3246..0d5a5fb 100644 --- a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java +++ b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java @@ -8,6 +8,7 @@ import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.content.ContextCompat; import androidx.recyclerview.widget.RecyclerView; import com.example.updateapp.R; @@ -17,9 +18,9 @@ public class LanguageAdapter extends RecyclerView.Adapter { - private Context context; - private List languageList; - private OnLanguageSelectedListener listener; + private final Context context; + private final List languageList; + private final OnLanguageSelectedListener listener; public interface OnLanguageSelectedListener { void onLanguageSelected(LanguageModel language, int position); @@ -41,18 +42,21 @@ public LanguageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int view @Override public void onBindViewHolder(@NonNull LanguageViewHolder holder, int position) { LanguageModel language = languageList.get(position); - holder.txtLanguageName.setText(language.getLanguageName()); - - if (language.isSelected()) { - holder.imgSelected.setVisibility(View.VISIBLE); - } else { - holder.imgSelected.setVisibility(View.GONE); - } + + boolean selected = language.isSelected(); + holder.itemView.setBackgroundResource( + selected ? R.drawable.bg_language_item_selected : R.drawable.bg_language_item + ); + holder.imgSelected.setVisibility(selected ? View.VISIBLE : View.INVISIBLE); + holder.txtLanguageName.setTextColor( + ContextCompat.getColor(context, selected ? R.color.themeColor : R.color.black) + ); + holder.itemView.setSelected(selected); holder.itemView.setOnClickListener(v -> { if (listener != null) { - listener.onLanguageSelected(language, position); + listener.onLanguageSelected(language, holder.getBindingAdapterPosition()); } }); } diff --git a/app/src/main/java/com/example/updateapp/adapters/OnboardingAdapter.java b/app/src/main/java/com/example/updateapp/adapters/OnboardingAdapter.java index 065c59d..06bf04d 100644 --- a/app/src/main/java/com/example/updateapp/adapters/OnboardingAdapter.java +++ b/app/src/main/java/com/example/updateapp/adapters/OnboardingAdapter.java @@ -8,38 +8,36 @@ import android.widget.TextView; import androidx.annotation.NonNull; -import androidx.constraintlayout.widget.ConstraintLayout; import androidx.viewpager.widget.PagerAdapter; import com.example.updateapp.R; public class OnboardingAdapter extends PagerAdapter { - Context context; - LayoutInflater layoutInflater; + private final Context context; - public OnboardingAdapter(Context context) { - this.context = context; - } - - String titles[] = { - "Welcome to FinTrack", - "Track • Analyze • Improve", - "Build Better Money Habits" + private final int[] titles = { + R.string.onboarding_title_1, + R.string.onboarding_title_2, + R.string.onboarding_title_3 }; - String subtitles[] ={ - "Your all-in-one AI companion for smarter spending,\nbetter savings, and complete financial clarity." , - "Understand your expenses with clean visuals, smart insights, and real-time spending patterns\nthat keep you in control.", - "Set budgets, stay organized, and make confident \nfinancial decisions with powerful AI-Chatbot tools." + private final int[] subtitles = { + R.string.onboarding_subtitle_1, + R.string.onboarding_subtitle_2, + R.string.onboarding_subtitle_3 }; - int images[] = { + private final int[] images = { R.drawable.bg_1, R.drawable.bg_2, R.drawable.bg_3 }; + public OnboardingAdapter(Context context) { + this.context = context; + } + @Override public int getCount() { return titles.length; @@ -47,31 +45,28 @@ public int getCount() { @Override public boolean isViewFromObject(@NonNull View view, @NonNull Object object) { - return view == (ConstraintLayout) object; + return view == object; } @NonNull @Override public Object instantiateItem(@NonNull ViewGroup container, int position) { - layoutInflater = (LayoutInflater) context.getSystemService(context.LAYOUT_INFLATER_SERVICE); - View v = layoutInflater.inflate(R.layout.slide, container, false); + View v = LayoutInflater.from(context).inflate(R.layout.slide, container, false); ImageView image = v.findViewById(R.id.slideImg); TextView title = v.findViewById(R.id.sliderTitle); TextView subtitle = v.findViewById(R.id.sliderSubTitle); image.setImageResource(images[position]); - title.setText(titles[position]); - subtitle.setText(subtitles[position]); + title.setText(context.getString(titles[position])); + subtitle.setText(context.getString(subtitles[position])); container.addView(v); - return v; - } @Override public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) { - container.removeView((ConstraintLayout) object); + container.removeView((View) object); } } diff --git a/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java b/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java index fab2da9..173a76b 100644 --- a/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java +++ b/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java @@ -5,99 +5,113 @@ import android.content.res.Configuration; import android.content.res.Resources; import android.os.Build; +import android.os.LocaleList; + +import androidx.appcompat.app.AppCompatDelegate; +import androidx.core.os.LocaleListCompat; import java.util.Locale; -public class LocaleHelper { - private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; - private static final String SELECTED_COUNTRY = "Locale.Helper.Selected.Country"; +/** + * Single source of truth for the in-app language. + * English is stored and applied as {@code en} with no country, so Android falls + * back to {@code values/} instead of hunting for {@code values-en-rUS}. + */ +public final class LocaleHelper { + private static final String PREFS_NAME = "app_prefs"; + private static final String KEY_LANGUAGE = "Locale.Helper.Selected.Language"; + private static final String KEY_COUNTRY = "Locale.Helper.Selected.Country"; + public static final String DEFAULT_LANGUAGE = "en"; + + private LocaleHelper() {} public static Context onAttach(Context context) { - String lang = getPersistedData(context, "en"); - String country = getPersistedCountry(context, ""); - return setLocale(context, lang, country); + return onAttach(context, DEFAULT_LANGUAGE); } public static Context onAttach(Context context, String defaultLanguage) { - String lang = getPersistedData(context, defaultLanguage); - String country = getPersistedCountry(context, ""); - return setLocale(context, lang, country); + String lang = getLanguage(context, defaultLanguage); + String country = getCountry(context); + return updateResources(context, lang, country); } public static String getLanguage(Context context) { - return getPersistedData(context, "en"); + return getLanguage(context, DEFAULT_LANGUAGE); } - public static Context setLocale(Context context, String language, String country) { - persist(context, language, country); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - return updateResources(context, language, country); + public static String getLanguage(Context context, String defaultLanguage) { + SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + String lang = preferences.getString(KEY_LANGUAGE, defaultLanguage); + if (lang == null || lang.isEmpty()) { + return defaultLanguage; } - - return updateResourcesLegacy(context, language, country); + return lang; } - private static String getPersistedData(Context context, String defaultLanguage) { + public static String getCountry(Context context) { SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); + String country = preferences.getString(KEY_COUNTRY, ""); + return country == null ? "" : country; } - private static String getPersistedCountry(Context context, String defaultCountry) { - SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - return preferences.getString(SELECTED_COUNTRY, defaultCountry); + public static boolean isEnglish(String language) { + return language == null || language.isEmpty() || language.equalsIgnoreCase(DEFAULT_LANGUAGE); } - private static void persist(Context context, String language, String country) { - SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString(SELECTED_LANGUAGE, language); - editor.putString(SELECTED_COUNTRY, country); - editor.apply(); + public static Context setLocale(Context context, String language, String country) { + String lang = isEnglish(language) ? DEFAULT_LANGUAGE : language; + String region = isEnglish(lang) ? "" : (country == null ? "" : country); + persist(context, lang, region); + applyAppLocales(lang, region); + Context app = context.getApplicationContext(); + if (app != null && app != context) { + updateResources(app, lang, region); + } + return updateResources(context, lang, region); } - private static Context updateResources(Context context, String language, String country) { - Locale locale; + public static Locale toLocale(String language, String country) { + if (isEnglish(language)) { + return Locale.ENGLISH; + } if (country != null && !country.isEmpty()) { - locale = new Locale(language, country); - } else { - locale = new Locale(language); + return new Locale(language, country); } - Locale.setDefault(locale); + return new Locale(language); + } - Configuration configuration = context.getResources().getConfiguration(); - configuration.setLocale(locale); - configuration.setLayoutDirection(locale); + private static void persist(Context context, String language, String country) { + SharedPreferences.Editor editor = + context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE).edit(); + editor.putString(KEY_LANGUAGE, language); + editor.putString(KEY_COUNTRY, country == null ? "" : country); + editor.apply(); + } - return context.createConfigurationContext(configuration); + private static void applyAppLocales(String language, String country) { + String tag = isEnglish(language) + ? "en" + : (country != null && !country.isEmpty() ? language + "-" + country : language); + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tag)); } - private static Context updateResourcesLegacy(Context context, String language, String country) { - Locale locale; - if (country != null && !country.isEmpty()) { - locale = new Locale(language, country); - } else { - locale = new Locale(language); - } + private static Context updateResources(Context context, String language, String country) { + Locale locale = toLocale(language, country); Locale.setDefault(locale); Resources resources = context.getResources(); - Configuration configuration = resources.getConfiguration(); - configuration.locale = locale; - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) { + Configuration configuration = new Configuration(resources.getConfiguration()); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + configuration.setLocale(locale); + configuration.setLocales(new LocaleList(locale)); configuration.setLayoutDirection(locale); + return context.createConfigurationContext(configuration); } + configuration.locale = locale; + configuration.setLayoutDirection(locale); resources.updateConfiguration(configuration, resources.getDisplayMetrics()); return context; } - - public static void clearLanguagePreference(Context context) { - SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.remove(SELECTED_LANGUAGE); - editor.remove(SELECTED_COUNTRY); - editor.apply(); - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java index 6242f5d..ac7a654 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LanguageActivity.java @@ -1,13 +1,14 @@ package com.example.updateapp.views.activites; +import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.view.View; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; -import androidx.activity.OnBackPressedCallback; import androidx.appcompat.app.AppCompatActivity; import androidx.core.graphics.Insets; import androidx.core.view.ViewCompat; @@ -15,6 +16,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.MainActivity; import com.example.updateapp.R; import com.example.updateapp.adapters.LanguageAdapter; @@ -29,14 +31,17 @@ public class LanguageActivity extends AppCompatActivity implements LanguageAdapt private RecyclerView recyclerView; private LanguageAdapter languageAdapter; private List languageList; - private ImageView imgDone, imgBack; + private ImageView imgDone; + private ImageView imgBack; private TextView txtTitle; + private TextView txtSubtitle; private int selectedPosition = 0; + private boolean isFirstLaunch; - private RecyclerView recyclerView; - private LanguageAdapter adapter; - private List languageList; - private String currentLanguageCode; + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.onAttach(newBase)); + } @Override protected void onCreate(Bundle savedInstanceState) { @@ -49,6 +54,8 @@ protected void onCreate(Bundle savedInstanceState) { return insets; }); + isFirstLaunch = getIntent().getBooleanExtra("isFirstLaunch", false); + initViews(); setupLanguageList(); setupRecyclerView(); @@ -56,23 +63,25 @@ protected void onCreate(Bundle savedInstanceState) { } private void initViews() { - recyclerView = findViewById(R.id.rev_langauge); + recyclerView = findViewById(R.id.rev_language); imgDone = findViewById(R.id.img_done); imgBack = findViewById(R.id.img_back); txtTitle = findViewById(R.id.txt_title); - - // Set title from string resource - txtTitle.setText(getString(R.string.language)); - - // Show back button - imgBack.setVisibility(android.view.View.VISIBLE); + txtSubtitle = findViewById(R.id.txt_subtitle); + + txtTitle.setText(getString(R.string.select_language)); + if (txtSubtitle != null) { + txtSubtitle.setText(getString(R.string.choose_language)); + } + + imgDone.setContentDescription(getString(R.string.done)); + imgBack.setContentDescription(getString(R.string.back)); + imgBack.setVisibility(isFirstLaunch ? View.GONE : View.VISIBLE); } private void setupLanguageList() { languageList = new ArrayList<>(); - - // Add all 10 supported languages - languageList.add(new LanguageModel(getString(R.string.lang_english), "en", "US")); + languageList.add(new LanguageModel(getString(R.string.lang_english), "en", "")); languageList.add(new LanguageModel(getString(R.string.lang_chinese), "zh", "CN")); languageList.add(new LanguageModel(getString(R.string.lang_hindi), "hi", "IN")); languageList.add(new LanguageModel(getString(R.string.lang_spanish), "es", "ES")); @@ -83,18 +92,16 @@ private void setupLanguageList() { languageList.add(new LanguageModel(getString(R.string.lang_russian), "ru", "RU")); languageList.add(new LanguageModel(getString(R.string.lang_urdu), "ur", "PK")); - // Set current language as selected String currentLanguage = LocaleHelper.getLanguage(this); + selectedPosition = 0; for (int i = 0; i < languageList.size(); i++) { - if (languageList.get(i).getLanguageCode().equals(currentLanguage)) { - languageList.get(i).setSelected(true); + boolean match = languageList.get(i).getLanguageCode().equalsIgnoreCase(currentLanguage); + languageList.get(i).setSelected(match); + if (match) { selectedPosition = i; - break; } } - - // If no match found, default to English (position 0) - if (selectedPosition == 0 && !currentLanguage.equals("en")) { + if (!languageList.get(selectedPosition).isSelected()) { languageList.get(0).setSelected(true); selectedPosition = 0; } @@ -104,12 +111,12 @@ private void setupRecyclerView() { languageAdapter = new LanguageAdapter(this, languageList, this); recyclerView.setLayoutManager(new LinearLayoutManager(this)); recyclerView.setAdapter(languageAdapter); + recyclerView.setHasFixedSize(true); } private void setupClickListeners() { imgDone.setOnClickListener(v -> applyLanguageChange()); - - imgBack.setOnClickListener(v -> onBackPressed()); + imgBack.setOnClickListener(v -> getOnBackPressedDispatcher().onBackPressed()); } @Override @@ -119,33 +126,25 @@ public void onLanguageSelected(LanguageModel language, int position) { } private void applyLanguageChange() { - if (selectedPosition >= 0 && selectedPosition < languageList.size()) { - LanguageModel selectedLanguage = languageList.get(selectedPosition); - - // Apply the language change immediately - LocaleHelper.setLocale(this, selectedLanguage.getLanguageCode(), selectedLanguage.getCountryCode()); - - // Show success message - Toast.makeText(this, getString(R.string.language_changed), Toast.LENGTH_SHORT).show(); - - // Restart the main activity to apply changes completely - restartApp(); - } + LanguageModel selectedLanguage = languageList.get(selectedPosition); + LocaleHelper.setLocale( + this, + selectedLanguage.getLanguageCode(), + selectedLanguage.getCountryCode() + ); + + new SaveState(this, "LANGUAGE_SELECTED").setState(1); + Toast.makeText(this, getString(R.string.language_changed), Toast.LENGTH_SHORT).show(); + restartApp(); } private void restartApp() { - // Create intent to restart the main activity - Intent intent = new Intent(this, MainActivity.class); - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); + Intent intent = isFirstLaunch + ? new Intent(this, OnboardingActivity.class) + : new Intent(this, MainActivity.class); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); startActivity(intent); finish(); - - // Apply transition animation overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out); } - - @Override - protected void attachBaseContext(android.content.Context newBase) { - super.attachBaseContext(LocaleHelper.onAttach(newBase)); - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java b/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java index cae6563..e289845 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/LoginActivity.java @@ -12,7 +12,6 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.MainActivity; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivityLoginBinding; diff --git a/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java b/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java index 4dbfc74..864daf2 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/NewUpdateActivity.java @@ -11,7 +11,6 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivityNewUpdateBinding; import com.example.updateapp.utils.LocaleHelper; diff --git a/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java b/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java index becd5e8..6d96226 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java @@ -16,7 +16,6 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.MainActivity; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivityOtpactivityBinding; @@ -225,7 +224,7 @@ private void saveUserToFirestoreAndContinue(String uid, String name, String emai }) .addOnFailureListener(e -> { if (dialog.isShowing()) dialog.dismiss(); - Toast.makeText(OTPActivity.this, "Failed to save user data: " + e.getMessage(), Toast.LENGTH_LONG).show(); + Toast.makeText(OTPActivity.this, getString(R.string.failed_save_user, e.getMessage()), Toast.LENGTH_LONG).show(); }); } diff --git a/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java b/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java index 7c9d11d..8f7312e 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/OnboardingActivity.java @@ -13,7 +13,6 @@ import androidx.cardview.widget.CardView; import androidx.viewpager.widget.ViewPager; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.R; import com.example.updateapp.adapters.OnboardingAdapter; diff --git a/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java b/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java index b128ac8..7829cf7 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/SignUpActivity.java @@ -11,7 +11,6 @@ import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.R; import com.example.updateapp.databinding.ActivitySignUpBinding; import com.example.updateapp.utils.LocaleHelper; diff --git a/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java b/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java index d964788..565a348 100644 --- a/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java +++ b/app/src/main/java/com/example/updateapp/views/activites/SplashScreenActivity.java @@ -5,13 +5,8 @@ import android.os.Bundle; import android.view.WindowManager; -import androidx.activity.EdgeToEdge; import androidx.appcompat.app.AppCompatActivity; -import androidx.core.graphics.Insets; -import androidx.core.view.ViewCompat; -import androidx.core.view.WindowInsetsCompat; -import com.example.updateapp.Helpers.LocaleHelper; import com.example.updateapp.Helpers.SaveState; import com.example.updateapp.R; import com.example.updateapp.utils.LocaleHelper; @@ -21,6 +16,11 @@ public class SplashScreenActivity extends AppCompatActivity { + @Override + protected void attachBaseContext(Context newBase) { + super.attachBaseContext(LocaleHelper.onAttach(newBase)); + } + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -30,40 +30,24 @@ protected void onCreate(Bundle savedInstanceState) { ); setContentView(R.layout.activity_splash_screen); - // Check if language has been selected before SaveState languageState = new SaveState(this, "LANGUAGE_SELECTED"); boolean languageSelected = languageState.getState() == 1; new Timer().schedule(new TimerTask() { @Override public void run() { - runOnUiThread(new Runnable() { - @Override - public void run() { - Intent intent; - if (!languageSelected) { - // Show language selection screen on first launch - intent = new Intent(SplashScreenActivity.this, LanguageActivity.class); - intent.putExtra("isFirstLaunch", true); - } else { - // Go to onboarding - intent = new Intent(SplashScreenActivity.this, OnboardingActivity.class); - } - startActivity(intent); - finish(); + runOnUiThread(() -> { + Intent intent; + if (!languageSelected) { + intent = new Intent(SplashScreenActivity.this, LanguageActivity.class); + intent.putExtra("isFirstLaunch", true); + } else { + intent = new Intent(SplashScreenActivity.this, OnboardingActivity.class); } + startActivity(intent); + finish(); }); } }, 500); } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(LocaleHelper.attachBaseContext(newBase)); - } - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(LocaleHelper.onAttach(newBase)); - } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/example/updateapp/views/fragments/ChatbotFragment.java b/app/src/main/java/com/example/updateapp/views/fragments/ChatbotFragment.java index 6ba8cb1..9218e8a 100644 --- a/app/src/main/java/com/example/updateapp/views/fragments/ChatbotFragment.java +++ b/app/src/main/java/com/example/updateapp/views/fragments/ChatbotFragment.java @@ -16,6 +16,7 @@ import android.widget.ImageView; import android.widget.Toast; +import com.example.updateapp.R; import com.example.updateapp.adapters.MessageAdapter; import com.example.updateapp.databinding.FragmentChatbotBinding; import com.example.updateapp.models.MessageModel; @@ -60,21 +61,21 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c binding.mic.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Toast.makeText(getContext(), "coming soon", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); binding.btnHistory.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Toast.makeText(getContext(), "coming soon", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); binding.file.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Toast.makeText(getContext(), "coming soon", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); @@ -99,14 +100,14 @@ public void onResponse(String response) { public void onError(Throwable throwable) { if (getActivity() != null) { getActivity().runOnUiThread(() -> { - addToChat("Error: " + throwable.getMessage(), MessageModel.SENT_BY_BOT); + addToChat(getString(R.string.error_message, throwable.getMessage()), MessageModel.SENT_BY_BOT); }); } } }); } else { - Toast.makeText(getContext(), "write something", Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(R.string.write_something), Toast.LENGTH_SHORT).show(); } }); diff --git a/app/src/main/res/drawable/bg_language_item.xml b/app/src/main/res/drawable/bg_language_item.xml new file mode 100644 index 0000000..620a5e1 --- /dev/null +++ b/app/src/main/res/drawable/bg_language_item.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/app/src/main/res/drawable/bg_language_item_selected.xml b/app/src/main/res/drawable/bg_language_item_selected.xml new file mode 100644 index 0000000..1aaea5b --- /dev/null +++ b/app/src/main/res/drawable/bg_language_item_selected.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/app/src/main/res/layout/activity_forget.xml b/app/src/main/res/layout/activity_forget.xml index 0a9947b..cb35f94 100644 --- a/app/src/main/res/layout/activity_forget.xml +++ b/app/src/main/res/layout/activity_forget.xml @@ -68,7 +68,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" - android:text="login" + android:text="@string/log_in" android:textColor="#FF5722" android:textStyle="bold" app:layout_constraintStart_toEndOf="@+id/textView6" diff --git a/app/src/main/res/layout/activity_language.xml b/app/src/main/res/layout/activity_language.xml index 5cf0495..ba62c06 100644 --- a/app/src/main/res/layout/activity_language.xml +++ b/app/src/main/res/layout/activity_language.xml @@ -1,172 +1,80 @@ - > - - - + android:layout_height="wrap_content" + android:background="@android:color/white" + android:gravity="center_vertical" + android:orientation="horizontal" + android:paddingStart="4dp" + android:paddingTop="8dp" + android:paddingEnd="12dp" + android:paddingBottom="8dp"> + android:padding="8dp" + android:src="@drawable/ic_back_arrow" + android:visibility="gone" /> - - - + android:layout_weight="1" + android:orientation="vertical" + android:paddingStart="8dp" + android:paddingEnd="8dp"> - + + + - - - - - + android:padding="4dp" + android:src="@drawable/ic_done_24" /> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file + android:layout_below="@id/rel_top" + android:clipToPadding="false" + android:paddingStart="12dp" + android:paddingTop="12dp" + android:paddingEnd="12dp" + android:paddingBottom="24dp" + tools:listitem="@layout/item_language" /> + diff --git a/app/src/main/res/layout/activity_new_update.xml b/app/src/main/res/layout/activity_new_update.xml index 42b6bd7..a652dfd 100644 --- a/app/src/main/res/layout/activity_new_update.xml +++ b/app/src/main/res/layout/activity_new_update.xml @@ -31,7 +31,7 @@ android:gravity="center_vertical" android:paddingTop="5dp" android:textStyle="bold" - android:text="Check what a new" + android:text="@string/check_new" android:textColor="@color/black" android:textSize="17sp"> @@ -93,7 +93,7 @@ android:layout_height="wrap_content" android:layout_centerInParent="true" android:gravity="center" - android:text="Advertisement Space" + android:text="@string/advertisement_space" android:textColor="@color/black" android:textSize="14sp" /> diff --git a/app/src/main/res/layout/activity_splash_screen.xml b/app/src/main/res/layout/activity_splash_screen.xml index a6f35b6..f9f90f6 100644 --- a/app/src/main/res/layout/activity_splash_screen.xml +++ b/app/src/main/res/layout/activity_splash_screen.xml @@ -88,7 +88,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="24dp" - android:text="AI-Powered Expense\nManager App" + android:text="@string/splash_title" android:textStyle="bold" android:textColor="@color/black" android:textSize="32dp" @@ -100,7 +100,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="2dp" - android:text="Track, manage, and analyze your finances\neffortlessly with AI-driven insights" + android:text="@string/splash_subtitle" android:textSize="16sp" app:layout_constraintStart_toStartOf="@+id/textView3" app:layout_constraintTop_toBottomOf="@+id/textView3" /> diff --git a/app/src/main/res/layout/fragment_chatbot.xml b/app/src/main/res/layout/fragment_chatbot.xml index 2d04a79..8cf8478 100644 --- a/app/src/main/res/layout/fragment_chatbot.xml +++ b/app/src/main/res/layout/fragment_chatbot.xml @@ -36,7 +36,7 @@ android:layout_marginEnd="100dp" android:layout_toStartOf="@+id/mic" android:layout_toEndOf="@+id/btnHistory" - android:text="Chatbot" + android:text="@string/chatbot" android:layout_centerVertical="true" android:singleLine="true" android:textSize="20sp" diff --git a/app/src/main/res/layout/item_language.xml b/app/src/main/res/layout/item_language.xml index 89d3ce4..8a1aeb9 100644 --- a/app/src/main/res/layout/item_language.xml +++ b/app/src/main/res/layout/item_language.xml @@ -1,13 +1,15 @@ + android:paddingStart="16dp" + android:paddingTop="14dp" + android:paddingEnd="16dp" + android:paddingBottom="14dp"> + tools:text="@string/lang_english" /> - - - + android:tint="@color/themeColor" + android:visibility="invisible" /> diff --git a/app/src/main/res/layout/item_message.xml b/app/src/main/res/layout/item_message.xml index 6855283..3a72eb7 100644 --- a/app/src/main/res/layout/item_message.xml +++ b/app/src/main/res/layout/item_message.xml @@ -29,7 +29,8 @@ android:layout_height="wrap_content" android:background="@drawable/send_message_back" android:padding="10dp" - android:text="How can I assist you today?" /> + android:text="" + tools:text="@string/chat_placeholder" /> + android:text="" + tools:text="@string/chat_placeholder" /> + android:title="@string/chatbot"/> + android:title="@string/profile"/> \ No newline at end of file diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index d32a553..e519f96 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -6,6 +6,7 @@ اللغة اختر اللغة + اختر اللغة التي تريد استخدامها English @@ -106,4 +107,17 @@ العودة إلى نسيت كلمة المرور يرجى التحقق من بريدك الإلكتروني + اكتب شيئاً + فشل حفظ المستخدم: %1$s + روبوت الدردشة + مساحة إعلانية + كيف يمكنني مساعدتك اليوم؟ + تطبيق إدارة المصروفات\nبالذكاء الاصطناعي + تتبع أموالك وأدرها وحلّلها\nبسهولة مع رؤى مدعومة بالذكاء الاصطناعي + مرحباً بك في FinTrack + تتبع • حلّل • حسّن + ابنِ عادات مالية أفضل + رفيقك الذكي لإنفاق أذكى،\nوتوفير أفضل، ووضوح مالي كامل. + افهم مصروفاتك عبر رسوم واضحة ورؤى ذكية وأنماط إنفاق فورية\nتبقيك مسيطراً. + حدد الميزانيات، وابقَ منظماً، واتخذ قرارات مالية\nواثقة باستخدام روبوت الدردشة الذكي. diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index a642fdb..d75072e 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -6,6 +6,7 @@ ভাষা ভাষা নির্বাচন করুন + আপনি যে ভাষা ব্যবহার করতে চান তা বেছে নিন English @@ -106,4 +107,17 @@ ফিরে যান পাসওয়ার্ড ভুলে গেছেন অনুগ্রহ করে আপনার ইমেইল চেক করুন + কিছু লিখুন + ব্যবহারকারী সংরক্ষণ করতে ব্যর্থ: %1$s + চ্যাটবট + বিজ্ঞাপনের স্থান + আজ আমি আপনাকে কীভাবে সাহায্য করতে পারি? + AI-চালিত খরচ\nব্যবস্থাপক অ্যাপ + AI অন্তর্দৃষ্টি দিয়ে আপনার অর্থ সহজে\nট্র্যাক, পরিচালনা ও বিশ্লেষণ করুন + FinTrack-এ স্বাগতম + ট্র্যাক • বিশ্লেষণ • উন্নতি + ভালো অর্থ অভ্যাস গড়ুন + স্মার্ট খরচ, ভালো সঞ্চয় এবং পূর্ণ আর্থিক স্বচ্ছতার জন্য আপনার অল-ইন-ওয়ান AI সঙ্গী। + পরিষ্কার ভিজ্যুয়াল, স্মার্ট অন্তর্দৃষ্টি এবং রিয়েল-টাইম খরচের ধরন দিয়ে\nআপনার ব্যয় বুঝুন যা আপনাকে নিয়ন্ত্রণে রাখে। + বাজেট সেট করুন, সংগঠিত থাকুন, এবং শক্তিশালী AI-চ্যাটবট দিয়ে\nআত্মবিশ্বাসের সাথে আর্থিক সিদ্ধান্ত নিন। diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 79339b8..0a1b00b 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -6,6 +6,7 @@ Idioma Seleccionar idioma + Elige el idioma que quieres usar English @@ -106,4 +107,17 @@ Volver a OLVIDÉ MI CONTRASEÑA Por Favor Revisa Tu Email + Escribe algo + No se pudo guardar el usuario: %1$s + Chatbot + Espacio publicitario + ¿Cómo puedo ayudarte hoy? + Gestor de gastos\ncon IA + Controla, gestiona y analiza tus finanzas\nsin esfuerzo con información impulsada por IA + Bienvenido a FinTrack + Registra • Analiza • Mejora + Mejores hábitos con el dinero + Tu compañero de IA para gastar mejor,\nahorrar más y tener claridad financiera. + Entiende tus gastos con visuales claros, ideas inteligentes y patrones en tiempo real\nque te mantienen al control. + Define presupuestos, organízate y toma decisiones financieras\ncon confianza usando el chatbot de IA. diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 0e2eb60..a3a0dd7 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -6,6 +6,7 @@ Langue Sélectionner la langue + Choisissez la langue que vous souhaitez utiliser English @@ -106,4 +107,17 @@ Retour à MOT DE PASSE OUBLIÉ Veuillez Vérifier Votre Email + Écrivez quelque chose + Échec de l\'enregistrement de l\'utilisateur : %1$s + Chatbot + Espace publicitaire + Comment puis-je vous aider aujourd\'hui ? + Gestionnaire de dépenses\nalimenté par l\'IA + Suivez, gérez et analysez vos finances\nsans effort grâce à l\'IA + Bienvenue sur FinTrack + Suivre • Analyser • Améliorer + De meilleures habitudes d\'argent + Votre compagnon IA pour dépenser plus intelligemment,\nmieux épargner et y voir clair. + Comprenez vos dépenses avec des visuels clairs, des insights et des tendances en temps réel\npour rester maître de vos finances. + Fixez des budgets, restez organisé et prenez des décisions financières\nen toute confiance avec le chatbot IA. diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 125a9f1..36217e6 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -6,6 +6,7 @@ भाषा भाषा चुनें + वह भाषा चुनें जिसका आप उपयोग करना चाहते हैं English @@ -106,4 +107,17 @@ वापस जाएं पासवर्ड भूल गए कृपया अपना ईमेल जांचें + कुछ लिखें + उपयोगकर्ता सहेजने में विफल: %1$s + चैटबॉट + विज्ञापन स्थान + आज मैं आपकी कैसे मदद कर सकता हूँ? + AI-संचालित खर्च\nप्रबंधक ऐप + AI अंतर्दृष्टि के साथ अपने वित्त को\nआसानी से ट्रैक, प्रबंधित और विश्लेषित करें + FinTrack में आपका स्वागत है + ट्रैक • विश्लेषण • सुधार + बेहतर पैसे की आदतें बनाएं + समझदारी से खर्च, बेहतर बचत और पूरी वित्तीय स्पष्टता के लिए आपका ऑल-इन-वन AI साथी। + साफ विज़ुअल, स्मार्ट अंतर्दृष्टि और रियल-टाइम खर्च पैटर्न से अपने खर्च को समझें\nजो आपको नियंत्रण में रखते हैं। + बजट सेट करें, व्यवस्थित रहें, और शक्तिशाली AI-चैटबॉट टूल से\nआत्मविश्वास के साथ वित्तीय निर्णय लें। diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 2eada52..407e199 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -6,6 +6,7 @@ Idioma Selecionar idioma + Escolha o idioma que deseja usar English @@ -106,4 +107,17 @@ Voltar para ESQUECI A SENHA Por Favor Verifique Seu Email + Escreva algo + Falha ao salvar o usuário: %1$s + Chatbot + Espaço publicitário + Como posso ajudar hoje? + Gestor de despesas\ncom IA + Acompanhe, gerencie e analise suas finanças\nsem esforço com insights de IA + Bem-vindo ao FinTrack + Registrar • Analisar • Melhorar + Melhores hábitos com dinheiro + Seu companheiro de IA para gastar melhor,\npoupar mais e ter clareza financeira. + Entenda seus gastos com visuais claros, insights e padrões em tempo real\nque mantêm você no controle. + Defina orçamentos, organize-se e tome decisões financeiras\ncom confiança usando o chatbot de IA. diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 5a64647..d596d67 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -6,6 +6,7 @@ Язык Выберите язык + Выберите язык, который хотите использовать English @@ -106,4 +107,17 @@ Вернуться к ЗАБЫЛИ ПАРОЛЬ Пожалуйста, Проверьте Ваш Email + Напишите что-нибудь + Не удалось сохранить пользователя: %1$s + Чат-бот + Рекламное место + Чем могу помочь сегодня? + Приложение для учёта\nрасходов с ИИ + Отслеживайте, управляйте и анализируйте финансы\nбез усилий с помощью ИИ + Добро пожаловать в FinTrack + Учёт • Анализ • Рост + Лучшие денежные привычки + Ваш ИИ-помощник для разумных трат,\nлучшей экономии и полной финансовой ясности. + Понимайте расходы с помощью наглядных графиков, умных подсказок и данных в реальном времени,\nчтобы всё держать под контролем. + Задавайте бюджеты, будьте организованны и принимайте уверенные финансовые решения\nс помощью ИИ-чата. diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 6095c7d..3ca6948 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -6,6 +6,7 @@ زبان زبان منتخب کریں + وہ زبان منتخب کریں جسے آپ استعمال کرنا چاہتے ہیں English @@ -106,4 +107,17 @@ واپس جائیں پاس ورڈ بھول گئے براہ کرم اپنا ای میل چیک کریں + کچھ لکھیں + صارف محفوظ کرنے میں ناکامی: %1$s + چیٹ بوٹ + اشتہاری جگہ + آج میں آپ کی کیسے مدد کر سکتا ہوں؟ + AI سے چلنے والا خرچ\nمینیجر ایپ + AI بصیرت کے ساتھ اپنے مالیات کو\nآسانی سے ٹریک، منظم اور تجزیہ کریں + FinTrack میں خوش آمدید + ٹریک • تجزیہ • بہتری + بہتر پیسے کی عادتیں بنائیں + ہوشیار خرچ، بہتر بچت اور مکمل مالی وضاحت کے لیے آپ کا آل ان ون AI ساتھی۔ + صاف بصری، اسمارٹ بصیرت اور حقیقی وقت کے خرچ کے انداز سے اپنے اخراجات سمجھیں\nجو آپ کو کنٹرول میں رکھتے ہیں۔ + بجٹ مقرر کریں، منظم رہیں، اور طاقتور AI-چیٹ بوٹ سے\nاعتماد کے ساتھ مالی فیصلے کریں۔ diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 4e7d2ea..86bcd04 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -7,6 +7,7 @@ 语言 选择语言 + 选择您要使用的语言 English @@ -106,4 +107,17 @@ 验证码验证失败 验证码错误: %1$s 身份验证错误:登录后未找到用户 + 请输入内容 + 保存用户失败:%1$s + 聊天机器人 + 广告位 + 今天我能帮您什么? + AI 驱动的\n支出管理应用 + 借助 AI 洞察,轻松跟踪、管理和分析您的财务 + 欢迎使用 FinTrack + 记录 • 分析 • 改进 + 养成更好的理财习惯 + 您的一站式 AI 助手,帮您更聪明地消费、\n更好地储蓄,并看清财务全貌。 + 通过清晰图表、智能洞察和实时消费趋势\n了解支出,让一切尽在掌握。 + 设定预算、保持条理,并借助强大的 AI 聊天工具\n自信地做出财务决策。 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 472e9d5..0940832 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,6 +6,7 @@ Language Select Language + Choose the language you want to use English @@ -105,4 +106,17 @@ Back to FORGET PASSWORD Please Check Your Email + Write something + Failed to save user: %1$s + Chatbot + Advertisement Space + How can I assist you today? + AI-Powered Expense\nManager App + Track, manage, and analyze your finances\neffortlessly with AI-driven insights + Welcome to FinTrack + Track • Analyze • Improve + Build Better Money Habits + Your all-in-one AI companion for smarter spending,\nbetter savings, and complete financial clarity. + Understand your expenses with clean visuals, smart insights, and real-time spending patterns\nthat keep you in control. + Set budgets, stay organized, and make confident \nfinancial decisions with powerful AI-Chatbot tools. \ No newline at end of file