From 60c243ba20e5cefade7f1e55d4c1480de66fcf1d Mon Sep 17 00:00:00 2001 From: Gyanu Date: Sun, 21 Dec 2025 19:01:08 +0530 Subject: [PATCH 1/5] 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/5] 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/5] 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/5] 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 From 2d9dea2840e77286702285a04f8fe766dacb19ca Mon Sep 17 00:00:00 2001 From: Gyanu Mayank Date: Thu, 3 Sep 2026 10:02:18 +0530 Subject: [PATCH 5/5] Apply selected language to the whole app, not just LanguageActivity. Persist English without a country tag so switching back from Hindi works, and move remaining hardcoded UI copy into translated string resources. --- .../example/updateapp/UpdateApplication.java | 8 +- .../updateapp/adapters/LanguageAdapter.java | 3 + .../example/updateapp/utils/LocaleHelper.java | 119 ++++------ .../views/activites/LanguageActivity.java | 88 ++++---- .../views/activites/OTPActivity.java | 8 +- .../views/fragments/ChatbotFragment.java | 11 +- app/src/main/res/layout/activity_language.xml | 203 +++++++++++++----- .../main/res/layout/activity_new_update.xml | 2 +- app/src/main/res/layout/fragment_chatbot.xml | 2 +- app/src/main/res/layout/item_language.xml | 39 ++-- app/src/main/res/layout/item_message.xml | 6 +- app/src/main/res/values-ar/strings.xml | 29 ++- app/src/main/res/values-bn/strings.xml | 29 ++- app/src/main/res/values-es/strings.xml | 31 +-- app/src/main/res/values-fr/strings.xml | 29 ++- app/src/main/res/values-hi/strings.xml | 29 ++- app/src/main/res/values-pt/strings.xml | 31 +-- app/src/main/res/values-ru/strings.xml | 31 +-- app/src/main/res/values-ur/strings.xml | 31 +-- app/src/main/res/values-zh/strings.xml | 31 +-- app/src/main/res/values/strings.xml | 15 +- 21 files changed, 454 insertions(+), 321 deletions(-) diff --git a/app/src/main/java/com/example/updateapp/UpdateApplication.java b/app/src/main/java/com/example/updateapp/UpdateApplication.java index 4d22ba3..42bab78 100644 --- a/app/src/main/java/com/example/updateapp/UpdateApplication.java +++ b/app/src/main/java/com/example/updateapp/UpdateApplication.java @@ -15,10 +15,6 @@ protected void attachBaseContext(Context base) { @Override public void onCreate() { super.onCreate(); - LocaleHelper.setLocale( - this, - LocaleHelper.getLanguage(this), - LocaleHelper.getCountry(this) - ); + LocaleHelper.applyPersistedLocales(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 0d5a5fb..9f2417b 100644 --- a/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java +++ b/app/src/main/java/com/example/updateapp/adapters/LanguageAdapter.java @@ -49,6 +49,9 @@ public void onBindViewHolder(@NonNull LanguageViewHolder holder, int position) { selected ? R.drawable.bg_language_item_selected : R.drawable.bg_language_item ); holder.imgSelected.setVisibility(selected ? View.VISIBLE : View.INVISIBLE); + holder.imgSelected.setContentDescription( + selected ? context.getString(R.string.selected_language) : null + ); holder.txtLanguageName.setTextColor( ContextCompat.getColor(context, selected ? R.color.themeColor : R.color.black) ); 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 173a76b..522c7aa 100644 --- a/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java +++ b/app/src/main/java/com/example/updateapp/utils/LocaleHelper.java @@ -4,114 +4,89 @@ import android.content.SharedPreferences; 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; -/** - * 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 { - +public class LocaleHelper { + private static final String SELECTED_LANGUAGE = "Locale.Helper.Selected.Language"; + private static final String SELECTED_COUNTRY = "Locale.Helper.Selected.Country"; 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) { - return onAttach(context, DEFAULT_LANGUAGE); + return onAttach(context, "en"); } public static Context onAttach(Context context, String defaultLanguage) { - String lang = getLanguage(context, defaultLanguage); - String country = getCountry(context); - return updateResources(context, lang, country); + String lang = getPersistedData(context, defaultLanguage); + String country = getPersistedCountry(context, ""); + return wrap(context, lang, country); } public static String getLanguage(Context context) { - return getLanguage(context, DEFAULT_LANGUAGE); - } - - 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 lang; + return getPersistedData(context, "en"); } public static String getCountry(Context context) { - SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); - String country = preferences.getString(KEY_COUNTRY, ""); - return country == null ? "" : country; + return getPersistedCountry(context, ""); } - public static boolean isEnglish(String language) { - return language == null || language.isEmpty() || language.equalsIgnoreCase(DEFAULT_LANGUAGE); + public static void applyPersistedLocales(Context context) { + applyAppLocales(getLanguage(context), getCountry(context)); } 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); + if (language == null || language.isEmpty()) { + language = "en"; } - return updateResources(context, lang, region); + if (country == null || "en".equals(language)) { + country = ""; + } + persist(context, language, country); + applyAppLocales(language, country); + return wrap(context, language, country); } - public static Locale toLocale(String language, String country) { - if (isEnglish(language)) { - return Locale.ENGLISH; - } - if (country != null && !country.isEmpty()) { - return new Locale(language, country); - } - return new Locale(language); + private static void applyAppLocales(String language, String country) { + String tag = (country == null || country.isEmpty()) + ? language + : language + "-" + country; + AppCompatDelegate.setApplicationLocales(LocaleListCompat.forLanguageTags(tag)); } - 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(); + private static String getPersistedData(Context context, String defaultLanguage) { + SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + return preferences.getString(SELECTED_LANGUAGE, defaultLanguage); } - 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 String getPersistedCountry(Context context, String defaultCountry) { + SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE); + return preferences.getString(SELECTED_COUNTRY, defaultCountry); + } + + 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 == null ? "" : country); + editor.apply(); } - private static Context updateResources(Context context, String language, String country) { - Locale locale = toLocale(language, country); + private static Context wrap(Context context, String language, String country) { + Locale locale; + if (country != null && !country.isEmpty()) { + locale = new Locale(language, country); + } else { + locale = new Locale(language); + } Locale.setDefault(locale); Resources resources = context.getResources(); 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.setLocale(locale); configuration.setLayoutDirection(locale); - resources.updateConfiguration(configuration, resources.getDisplayMetrics()); - return context; + return context.createConfigurationContext(configuration); } } 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 ac7a654..cc6d30d 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,9 +1,7 @@ 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; @@ -16,7 +14,6 @@ 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; @@ -31,17 +28,9 @@ public class LanguageActivity extends AppCompatActivity implements LanguageAdapt private RecyclerView recyclerView; private LanguageAdapter languageAdapter; private List languageList; - private ImageView imgDone; - private ImageView imgBack; + private ImageView imgDone, imgBack; private TextView txtTitle; - private TextView txtSubtitle; private int selectedPosition = 0; - private boolean isFirstLaunch; - - @Override - protected void attachBaseContext(Context newBase) { - super.attachBaseContext(LocaleHelper.onAttach(newBase)); - } @Override protected void onCreate(Bundle savedInstanceState) { @@ -54,8 +43,6 @@ protected void onCreate(Bundle savedInstanceState) { return insets; }); - isFirstLaunch = getIntent().getBooleanExtra("isFirstLaunch", false); - initViews(); setupLanguageList(); setupRecyclerView(); @@ -63,24 +50,22 @@ protected void onCreate(Bundle savedInstanceState) { } private void initViews() { - recyclerView = findViewById(R.id.rev_language); + recyclerView = findViewById(R.id.rev_langauge); imgDone = findViewById(R.id.img_done); imgBack = findViewById(R.id.img_back); txtTitle = findViewById(R.id.txt_title); - 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); + + // Set title from string resource + txtTitle.setText(getString(R.string.language)); + + // Show back button + imgBack.setVisibility(android.view.View.VISIBLE); } private void setupLanguageList() { languageList = new ArrayList<>(); + + // Add all 10 supported languages 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")); @@ -93,15 +78,16 @@ private void setupLanguageList() { languageList.add(new LanguageModel(getString(R.string.lang_urdu), "ur", "PK")); String currentLanguage = LocaleHelper.getLanguage(this); - selectedPosition = 0; + boolean found = false; for (int i = 0; i < languageList.size(); i++) { - boolean match = languageList.get(i).getLanguageCode().equalsIgnoreCase(currentLanguage); - languageList.get(i).setSelected(match); - if (match) { + if (languageList.get(i).getLanguageCode().equals(currentLanguage)) { + languageList.get(i).setSelected(true); selectedPosition = i; + found = true; + break; } } - if (!languageList.get(selectedPosition).isSelected()) { + if (!found) { languageList.get(0).setSelected(true); selectedPosition = 0; } @@ -111,12 +97,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 -> getOnBackPressedDispatcher().onBackPressed()); + + imgBack.setOnClickListener(v -> onBackPressed()); } @Override @@ -126,25 +112,33 @@ public void onLanguageSelected(LanguageModel language, int position) { } private void applyLanguageChange() { - 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(); + 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(); + } } private void restartApp() { - 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); + // 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); 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/OTPActivity.java b/app/src/main/java/com/example/updateapp/views/activites/OTPActivity.java index 6d96226..e2db30b 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 @@ -183,15 +183,15 @@ private void verifyCredential(PhoneAuthCredential credential) { dialog.dismiss(); Exception e = linkTask.getException(); - String msg = e != null ? e.getMessage() : "Unknown linking error"; + String msg = e != null ? e.getMessage() : getString(R.string.unknown_linking_error); if (e instanceof FirebaseAuthUserCollisionException) { Toast.makeText(OTPActivity.this, - "This email is already registered with a different account. Please login with that email or use another email.", + getString(R.string.email_already_registered_different), Toast.LENGTH_LONG).show(); } else { Toast.makeText(OTPActivity.this, - "Failed to link email: " + msg, + getString(R.string.failed_to_link_email, msg), Toast.LENGTH_LONG).show(); } } @@ -224,7 +224,7 @@ private void saveUserToFirestoreAndContinue(String uid, String name, String emai }) .addOnFailureListener(e -> { if (dialog.isShowing()) dialog.dismiss(); - Toast.makeText(OTPActivity.this, getString(R.string.failed_save_user, e.getMessage()), Toast.LENGTH_LONG).show(); + Toast.makeText(OTPActivity.this, getString(R.string.failed_to_save_user, e.getMessage()), Toast.LENGTH_LONG).show(); }); } 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 9218e8a..f4ef31e 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,7 +16,6 @@ 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; @@ -61,21 +60,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(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(com.example.updateapp.R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); binding.btnHistory.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Toast.makeText(getContext(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(com.example.updateapp.R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); binding.file.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - Toast.makeText(getContext(), getString(R.string.coming_soon), Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(com.example.updateapp.R.string.coming_soon), Toast.LENGTH_SHORT).show(); } }); @@ -100,14 +99,14 @@ public void onResponse(String response) { public void onError(Throwable throwable) { if (getActivity() != null) { getActivity().runOnUiThread(() -> { - addToChat(getString(R.string.error_message, throwable.getMessage()), MessageModel.SENT_BY_BOT); + addToChat(getString(com.example.updateapp.R.string.error_message, throwable.getMessage()), MessageModel.SENT_BY_BOT); }); } } }); } else { - Toast.makeText(getContext(), getString(R.string.write_something), Toast.LENGTH_SHORT).show(); + Toast.makeText(getContext(), getString(com.example.updateapp.R.string.write_something), Toast.LENGTH_SHORT).show(); } }); diff --git a/app/src/main/res/layout/activity_language.xml b/app/src/main/res/layout/activity_language.xml index ba62c06..72f8eca 100644 --- a/app/src/main/res/layout/activity_language.xml +++ b/app/src/main/res/layout/activity_language.xml @@ -1,80 +1,173 @@ + android:background="#ffffff" - + + + + android:layout_height="35dp"> + android:gravity="center" + android:maxLines="1" + android:padding="5dp" + android:visibility="gone" + android:src="@drawable/ic_back_arrow" /> - + android:gravity="center|start" + android:layout_centerVertical="true" + android:layout_toEndOf="@+id/img_back" + android:layout_toStartOf="@+id/img_done" + android:text="@string/language" + android:textStyle="bold" + android:textColor="@color/black" + android:textSize="21sp" + > - + - - - + android:background="@drawable/bg_lang_done"> + + + - + + - + android:background="#F3F4F8" + android:layout_below="@+id/rel_top"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_new_update.xml b/app/src/main/res/layout/activity_new_update.xml index a652dfd..76ebadc 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="@string/check_new" + android:text="@string/check_whats_new" android:textColor="@color/black" android:textSize="17sp"> diff --git a/app/src/main/res/layout/fragment_chatbot.xml b/app/src/main/res/layout/fragment_chatbot.xml index 8cf8478..c2b357d 100644 --- a/app/src/main/res/layout/fragment_chatbot.xml +++ b/app/src/main/res/layout/fragment_chatbot.xml @@ -90,7 +90,7 @@ android:layout_height="wrap_content" android:minHeight="35dp" android:maxHeight="100dp" - android:hint="Message ..." + android:hint="@string/message_hint" android:padding="10dp"/> + android:paddingStart="20dp" + android:paddingTop="16dp" + android:paddingEnd="20dp" + android:paddingBottom="16dp"> + android:fontFamily="sans-serif-medium" /> - + android:tint="#4CAF50" + android:visibility="gone" /> + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_message.xml b/app/src/main/res/layout/item_message.xml index 3a72eb7..bf8830a 100644 --- a/app/src/main/res/layout/item_message.xml +++ b/app/src/main/res/layout/item_message.xml @@ -29,8 +29,7 @@ android:layout_height="wrap_content" android:background="@drawable/send_message_back" android:padding="10dp" - android:text="" - tools:text="@string/chat_placeholder" /> + android:text="@string/how_can_i_assist" /> + android:text="@string/how_can_i_assist" /> اللغة اختر اللغة - اختر اللغة التي تريد استخدامها English @@ -107,17 +106,25 @@ العودة إلى نسيت كلمة المرور يرجى التحقق من بريدك الإلكتروني + + الدردشة + رسالة ... اكتب شيئاً - فشل حفظ المستخدم: %1$s - روبوت الدردشة - مساحة إعلانية - كيف يمكنني مساعدتك اليوم؟ - تطبيق إدارة المصروفات\nبالذكاء الاصطناعي - تتبع أموالك وأدرها وحلّلها\nبسهولة مع رؤى مدعومة بالذكاء الاصطناعي + تطبيق إدارة مصروفات\nمدعوم بالذكاء الاصطناعي + تتبع أموالك وأدرها وحلّلها بسهولة\nبمساعدة الذكاء الاصطناعي مرحباً بك في FinTrack تتبع • حلّل • حسّن ابنِ عادات مالية أفضل - رفيقك الذكي لإنفاق أذكى،\nوتوفير أفضل، ووضوح مالي كامل. - افهم مصروفاتك عبر رسوم واضحة ورؤى ذكية وأنماط إنفاق فورية\nتبقيك مسيطراً. - حدد الميزانيات، وابقَ منظماً، واتخذ قرارات مالية\nواثقة باستخدام روبوت الدردشة الذكي. - + رفيقك بالذكاء الاصطناعي لإنفاق أذكى\nوتوفير أوضح. + افهم مصروفاتك برسوم واضحة ورؤى ذكية. + حدد الميزانيات ونظّم قراراتك مع روبوت الدردشة. + مساحة إعلانية + اطلع على الجديد + كيف يمكنني مساعدتك اليوم؟ + هذا البريد مسجّل بحساب آخر. سجّل الدخول به أو استخدم بريداً آخر. + تعذر ربط البريد: %1$s + تعذر حفظ بيانات المستخدم: %1$s + خطأ ربط غير معروف + اللغة المحددة + + \ No newline at end of file diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index d75072e..68f90ae 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -6,7 +6,6 @@ ভাষা ভাষা নির্বাচন করুন - আপনি যে ভাষা ব্যবহার করতে চান তা বেছে নিন English @@ -107,17 +106,25 @@ ফিরে যান পাসওয়ার্ড ভুলে গেছেন অনুগ্রহ করে আপনার ইমেইল চেক করুন - কিছু লিখুন - ব্যবহারকারী সংরক্ষণ করতে ব্যর্থ: %1$s + চ্যাটবট - বিজ্ঞাপনের স্থান - আজ আমি আপনাকে কীভাবে সাহায্য করতে পারি? - AI-চালিত খরচ\nব্যবস্থাপক অ্যাপ - AI অন্তর্দৃষ্টি দিয়ে আপনার অর্থ সহজে\nট্র্যাক, পরিচালনা ও বিশ্লেষণ করুন + বার্তা ... + কিছু লিখুন + এআই-চালিত খরচ\nম্যানেজার অ্যাপ + এআই অন্তর্দৃষ্টি দিয়ে আপনার অর্থ ট্র্যাক,\nপরিচালনা ও বিশ্লেষণ করুন FinTrack-এ স্বাগতম ট্র্যাক • বিশ্লেষণ • উন্নতি ভালো অর্থ অভ্যাস গড়ুন - স্মার্ট খরচ, ভালো সঞ্চয় এবং পূর্ণ আর্থিক স্বচ্ছতার জন্য আপনার অল-ইন-ওয়ান AI সঙ্গী। - পরিষ্কার ভিজ্যুয়াল, স্মার্ট অন্তর্দৃষ্টি এবং রিয়েল-টাইম খরচের ধরন দিয়ে\nআপনার ব্যয় বুঝুন যা আপনাকে নিয়ন্ত্রণে রাখে। - বাজেট সেট করুন, সংগঠিত থাকুন, এবং শক্তিশালী AI-চ্যাটবট দিয়ে\nআত্মবিশ্বাসের সাথে আর্থিক সিদ্ধান্ত নিন। - + স্মার্ট খরচ, ভালো সঞ্চয় ও স্পষ্ট আর্থিক ধারণার\nজন্য আপনার এআই সঙ্গী। + পরিষ্কার ভিজ্যুয়াল ও স্মার্ট ইনসাইট দিয়ে খরচ বুঝুন। + বাজেট ঠিক করুন এবং এআই চ্যাটবট দিয়ে সিদ্ধান্ত নিন। + বিজ্ঞাপনের স্থান + নতুন কী দেখুন + আজ আমি কীভাবে সাহায্য করতে পারি? + এই ইমেইল অন্য অ্যাকাউন্টে নিবন্ধিত। সেই ইমেইল দিয়ে লগইন করুন বা অন্য ইমেইল ব্যবহার করুন। + ইমেইল লিঙ্ক করা যায়নি: %1$s + ব্যবহারকারীর তথ্য সংরক্ষণ যায়নি: %1$s + অজানা লিঙ্ক ত্রুটি + নির্বাচিত ভাষা + + \ No newline at end of file diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 0a1b00b..6582af9 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -6,7 +6,6 @@ Idioma Seleccionar idioma - Elige el idioma que quieres usar English @@ -107,17 +106,25 @@ 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 + Mensaje ... + Escribe algo + App de gastos\ncon IA + Controla, gestiona y analiza tus finanzas\ncon información impulsada por IA Bienvenido a FinTrack - Registra • Analiza • Mejora + Controla • 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. - + Tu compañero de IA para gastar mejor,\nahorrar más y ver tus finanzas con claridad. + Entiende tus gastos con gráficos claros,\ninsights y patrones en tiempo real. + Define presupuestos, organízate y decide\ncon el chatbot de IA. + Espacio publicitario + Ver novedades + ¿Cómo puedo ayudarte hoy? + Este correo ya está registrado en otra cuenta. Inicia sesión con ese correo o usa otro. + No se pudo vincular el correo: %1$s + No se pudieron guardar los datos: %1$s + Error de vinculación desconocido + Idioma seleccionado + + \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index a3a0dd7..bd05f49 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -6,7 +6,6 @@ Langue Sélectionner la langue - Choisissez la langue que vous souhaitez utiliser English @@ -107,17 +106,25 @@ 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 + Message ... + Écrivez quelque chose + Application de dépenses\npropulsée par l\'IA + Suivez, gérez et analysez vos finances\navec des insights 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. - + Votre compagnon IA pour dépenser plus malin\net voir vos finances clairement. + Comprenez vos dépenses avec des visuels clairs\net des insights en temps réel. + Fixez des budgets et décidez sereinement\navec le chatbot IA. + Espace publicitaire + Voir les nouveautés + Comment puis-je vous aider aujourd\'hui ? + Cet e-mail est déjà lié à un autre compte. Connectez-vous avec cet e-mail ou utilisez-en un autre. + Impossible de lier l\'e-mail : %1$s + Impossible d\'enregistrer les données : %1$s + Erreur de liaison inconnue + Langue sélectionnée + + \ No newline at end of file diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 36217e6..a7217e5 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -6,7 +6,6 @@ भाषा भाषा चुनें - वह भाषा चुनें जिसका आप उपयोग करना चाहते हैं English @@ -107,17 +106,25 @@ वापस जाएं पासवर्ड भूल गए कृपया अपना ईमेल जांचें - कुछ लिखें - उपयोगकर्ता सहेजने में विफल: %1$s + चैटबॉट - विज्ञापन स्थान - आज मैं आपकी कैसे मदद कर सकता हूँ? - AI-संचालित खर्च\nप्रबंधक ऐप - AI अंतर्दृष्टि के साथ अपने वित्त को\nआसानी से ट्रैक, प्रबंधित और विश्लेषित करें + संदेश ... + कुछ लिखें + एआई-संचालित खर्च\nप्रबंधक ऐप + एआई अंतर्दृष्टि के साथ अपने वित्त को ट्रैक, प्रबंधित\nऔर विश्लेषण करें FinTrack में आपका स्वागत है ट्रैक • विश्लेषण • सुधार बेहतर पैसे की आदतें बनाएं - समझदारी से खर्च, बेहतर बचत और पूरी वित्तीय स्पष्टता के लिए आपका ऑल-इन-वन AI साथी। - साफ विज़ुअल, स्मार्ट अंतर्दृष्टि और रियल-टाइम खर्च पैटर्न से अपने खर्च को समझें\nजो आपको नियंत्रण में रखते हैं। - बजट सेट करें, व्यवस्थित रहें, और शक्तिशाली AI-चैटबॉट टूल से\nआत्मविश्वास के साथ वित्तीय निर्णय लें। - + स्मार्ट खर्च, बेहतर बचत और स्पष्ट वित्तीय समझ\nके लिए आपका एआई साथी। + साफ विज़ुअल, स्मार्ट अंतर्दृष्टि और खर्च पैटर्न से\nअपने खर्च को समझें। + बजट तय करें, व्यवस्थित रहें और एआई चैटबॉट से\nआत्मविश्वास से फैसले लें। + विज्ञापन स्थान + नया क्या है देखें + आज मैं आपकी कैसे मदद कर सकता हूँ? + यह ईमेल किसी दूसरे खाते से जुड़ा है। कृपया उसी ईमेल से लॉगिन करें या दूसरा ईमेल उपयोग करें। + ईमेल लिंक नहीं हो सका: %1$s + उपयोगकर्ता डेटा सहेजा नहीं जा सका: %1$s + अज्ञात लिंक त्रुटि + चयनित भाषा + + \ No newline at end of file diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 407e199..135a9d7 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -6,7 +6,6 @@ Idioma Selecionar idioma - Escolha o idioma que deseja usar English @@ -107,17 +106,25 @@ 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 + Mensagem ... + Escreva algo + App de despesas\ncom IA + Acompanhe, gerencie e analise suas finanças\ncom insights de IA Bem-vindo ao FinTrack - Registrar • Analisar • Melhorar + Acompanhe • Analise • Melhore 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. - + Seu companheiro de IA para gastar melhor\ne ver as finanças com clareza. + Entenda seus gastos com visuais claros\ne insights em tempo real. + Defina orçamentos e decida com confiança\ncom o chatbot de IA. + Espaço publicitário + Veja as novidades + Como posso ajudar hoje? + Este e-mail já está em outra conta. Entre com esse e-mail ou use outro. + Falha ao vincular o e-mail: %1$s + Falha ao salvar os dados: %1$s + Erro de vinculação desconhecido + Idioma selecionado + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index d596d67..d6e4ee6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -6,7 +6,6 @@ Язык Выберите язык - Выберите язык, который хотите использовать English @@ -107,17 +106,25 @@ Вернуться к ЗАБЫЛИ ПАРОЛЬ Пожалуйста, Проверьте Ваш Email - Напишите что-нибудь - Не удалось сохранить пользователя: %1$s + Чат-бот - Рекламное место - Чем могу помочь сегодня? - Приложение для учёта\nрасходов с ИИ - Отслеживайте, управляйте и анализируйте финансы\nбез усилий с помощью ИИ + Сообщение ... + Напишите что-нибудь + Приложение для расходов\nна базе ИИ + Отслеживайте, управляйте и анализируйте финансы\nс помощью ИИ Добро пожаловать в FinTrack - Учёт • Анализ • Рост + Учёт • Анализ • Улучшение Лучшие денежные привычки - Ваш ИИ-помощник для разумных трат,\nлучшей экономии и полной финансовой ясности. - Понимайте расходы с помощью наглядных графиков, умных подсказок и данных в реальном времени,\nчтобы всё держать под контролем. - Задавайте бюджеты, будьте организованны и принимайте уверенные финансовые решения\nс помощью ИИ-чата. - + ИИ-помощник для разумных трат,\nнакоплений и ясности в финансах. + Понимайте расходы через графики\nи актуальные инсайты. + Задавайте бюджеты и принимайте решения\nс ИИ-чатботом. + Рекламное место + Что нового + Чем я могу помочь сегодня? + Эта почта уже привязана к другому аккаунту. Войдите с ней или используйте другую. + Не удалось привязать почту: %1$s + Не удалось сохранить данные: %1$s + Неизвестная ошибка привязки + Выбранный язык + + \ No newline at end of file diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 3ca6948..38a0358 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -6,7 +6,6 @@ زبان زبان منتخب کریں - وہ زبان منتخب کریں جسے آپ استعمال کرنا چاہتے ہیں English @@ -107,17 +106,25 @@ واپس جائیں پاس ورڈ بھول گئے براہ کرم اپنا ای میل چیک کریں - کچھ لکھیں - صارف محفوظ کرنے میں ناکامی: %1$s + چیٹ بوٹ - اشتہاری جگہ - آج میں آپ کی کیسے مدد کر سکتا ہوں؟ - AI سے چلنے والا خرچ\nمینیجر ایپ - AI بصیرت کے ساتھ اپنے مالیات کو\nآسانی سے ٹریک، منظم اور تجزیہ کریں + پیغام ... + کچھ لکھیں + اے آئی سے چلنے والی\nخرچ ایپ + اے آئی کی مدد سے اپنے مالیات کو ٹریک،\nمنظم اور جانچیں FinTrack میں خوش آمدید ٹریک • تجزیہ • بہتری - بہتر پیسے کی عادتیں بنائیں - ہوشیار خرچ، بہتر بچت اور مکمل مالی وضاحت کے لیے آپ کا آل ان ون AI ساتھی۔ - صاف بصری، اسمارٹ بصیرت اور حقیقی وقت کے خرچ کے انداز سے اپنے اخراجات سمجھیں\nجو آپ کو کنٹرول میں رکھتے ہیں۔ - بجٹ مقرر کریں، منظم رہیں، اور طاقتور AI-چیٹ بوٹ سے\nاعتماد کے ساتھ مالی فیصلے کریں۔ - + بہتر مالی عادات بنائیں + سمارٹ خرچ، بہتر بچت اور واضح مالیات کے لیے\nآپ کا اے آئی ساتھی۔ + صاف بصری اور سمارٹ بصیرت سے اپنے اخراجات سمجھیں۔ + بجٹ طے کریں اور اے آئی چیٹ بوٹ سے فیصلے کریں۔ + اشتہاری جگہ + نیا کیا ہے دیکھیں + آج میں آپ کی کیسے مدد کر سکتا ہوں؟ + یہ ای میل دوسرے اکاؤنٹ سے منسلک ہے۔ اسی ای میل سے لاگ ان کریں یا دوسری استعمال کریں۔ + ای میل منسلک نہیں ہو سکی: %1$s + یوزر ڈیٹا محفوظ نہیں ہو سکا: %1$s + نامعلوم لنک خرابی + منتخب زبان + + \ No newline at end of file diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 86bcd04..967b167 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -7,7 +7,6 @@ 语言 选择语言 - 选择您要使用的语言 English @@ -107,17 +106,25 @@ 验证码验证失败 验证码错误: %1$s 身份验证错误:登录后未找到用户 - 请输入内容 - 保存用户失败:%1$s + 聊天机器人 - 广告位 - 今天我能帮您什么? - AI 驱动的\n支出管理应用 - 借助 AI 洞察,轻松跟踪、管理和分析您的财务 + 消息 ... + 请输入内容 + AI 驱动的支出\n管理应用 + 借助 AI 洞察轻松跟踪、管理和分析你的财务 欢迎使用 FinTrack - 记录 • 分析 • 改进 + 跟踪 • 分析 • 改善 养成更好的理财习惯 - 您的一站式 AI 助手,帮您更聪明地消费、\n更好地储蓄,并看清财务全貌。 - 通过清晰图表、智能洞察和实时消费趋势\n了解支出,让一切尽在掌握。 - 设定预算、保持条理,并借助强大的 AI 聊天工具\n自信地做出财务决策。 - + 智能支出、更好储蓄和清晰财务的一站式 AI 助手。 + 用清晰图表、智能洞察和实时支出模式掌控财务。 + 设定预算、保持条理,并用 AI 聊天工具自信决策。 + 广告位 + 查看新内容 + 今天我能为你做什么? + 该邮箱已注册到其他账户。请用该邮箱登录或换一个邮箱。 + 无法关联邮箱:%1$s + 无法保存用户数据:%1$s + 未知关联错误 + 已选语言 + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0940832..63b7d66 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -6,7 +6,6 @@ Language Select Language - Choose the language you want to use English @@ -106,11 +105,9 @@ 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? + Message ... + Write something AI-Powered Expense\nManager App Track, manage, and analyze your finances\neffortlessly with AI-driven insights Welcome to FinTrack @@ -119,4 +116,12 @@ 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. + Advertisement Space + Check what\'s new + How can I assist you today? + This email is already registered with a different account. Please login with that email or use another email. + Failed to link email: %1$s + Failed to save user data: %1$s + Unknown linking error + Selected language \ No newline at end of file