Sfoglia il codice sorgente

Worked on multi lingual, added 4 languages and working on it, created separate each resource qualifiers for each language, uptil now when selecting any language, settings heading text changes

Khubaib 8 mesi fa
parent
commit
1865354d44

+ 1 - 1
.idea/deploymentTargetSelector.xml

@@ -4,7 +4,7 @@
     <selectionStates>
       <SelectionState runConfigName="app">
         <option name="selectionMode" value="DROPDOWN" />
-        <DropdownSelection timestamp="2024-08-08T16:58:59.461731583Z">
+        <DropdownSelection timestamp="2024-08-09T10:30:45.536311501Z">
           <Target type="DEFAULT_BOOT">
             <handle>
               <DeviceId pluginId="LocalEmulator" identifier="path=/home/ubuntu/.android/avd/Television_1080p_API_31.avd" />

+ 12 - 0
app/src/main/AndroidManifest.xml

@@ -39,6 +39,7 @@
         android:supportsRtl="true"
         android:theme="@style/Theme.AppCompat.Light.NoActionBar.App"
         android:usesCleartextTraffic="true"
+        android:localeConfig="@xml/locales_config"
         tools:targetApi="31">
         <activity
             android:name=".activities.HomeActivityTV"
@@ -54,6 +55,7 @@
             android:exported="true"
             android:label="@string/app_name"
             android:launchMode="singleTop"
+            android:configChanges="locale|layoutDirection"
             android:theme="@style/Theme.AppCompat.Light.NoActionBar.App">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
@@ -168,6 +170,16 @@
             android:enabled="true"
             android:exported="true"
             android:foregroundServiceType="specialUse" />
+
+        <service
+            android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
+            android:enabled="false"
+            android:exported="false">
+            <meta-data
+                android:name="autoStoreLocales"
+                android:value="true" />
+        </service>
+
     </application>
 
 </manifest>

+ 3 - 0
app/src/main/java/com/vpn/fastestvpnservice/MainActivity.kt

@@ -1,5 +1,6 @@
 package com.vpn.fastestvpnservice
 
+import android.app.LocaleManager
 import android.content.Context
 import android.content.Intent
 import android.content.pm.ActivityInfo
@@ -8,6 +9,7 @@ import android.content.pm.PackageManager
 import android.net.Uri
 import android.os.Build
 import android.os.Bundle
+import android.os.LocaleList
 import android.util.Log
 import android.view.WindowInsets
 import android.view.WindowInsetsController
@@ -15,6 +17,7 @@ import android.view.WindowManager
 import android.widget.Toast
 import androidx.activity.compose.setContent
 import androidx.activity.viewModels
+import androidx.annotation.RequiresApi
 import androidx.compose.foundation.isSystemInDarkTheme
 import androidx.compose.runtime.getValue
 import androidx.compose.runtime.mutableStateOf

+ 6 - 1
app/src/main/java/com/vpn/fastestvpnservice/beans/Dark_Light_Theme.kt

@@ -4,7 +4,12 @@ import androidx.compose.runtime.MutableState
 import androidx.compose.runtime.mutableStateOf
 
 val themesList = listOf<String>(
-    "System Default", "Light Theme", "Dark Theme"
+    "System Default", "Light Mode", "Dark Mode"
+)
+
+val languages = listOf<Language>(
+    Language("English","en"), Language("French","fr"),
+    Language("German","de"), Language("Turkish","tr")
 )
 
 var isDarkTheme: MutableState<Boolean> = mutableStateOf(false)

+ 4 - 0
app/src/main/java/com/vpn/fastestvpnservice/beans/Protocol.kt

@@ -3,3 +3,7 @@ package com.vpn.fastestvpnservice.beans
 class Protocol(
     var full_name:String, var title: String, var index: Int
 )
+
+class Language(
+    var name:String, var code:String
+)

+ 186 - 2
app/src/main/java/com/vpn/fastestvpnservice/screens/bottomNavBarScreens/SettingsScreen.kt

@@ -1,11 +1,13 @@
 package com.vpn.fastestvpnservice.screens.bottomNavBarScreens
 
 import android.app.Activity
+import android.app.LocaleManager
 import android.content.Context
 import android.content.Intent
 import android.os.Build
 import android.os.Bundle
 import android.os.Handler
+import android.os.LocaleList
 import android.util.Log
 import android.widget.Toast
 import androidx.compose.foundation.ExperimentalFoundationApi
@@ -33,6 +35,7 @@ import androidx.compose.foundation.selection.selectable
 import androidx.compose.foundation.verticalScroll
 import androidx.compose.material.icons.Icons
 import androidx.compose.material.icons.filled.DarkMode
+import androidx.compose.material.icons.filled.Language
 import androidx.compose.material3.DockedSearchBar
 import androidx.compose.material3.ExperimentalMaterial3Api
 import androidx.compose.material3.Icon
@@ -85,6 +88,7 @@ import androidx.navigation.compose.rememberNavController
 import com.vpn.fastestvpnservice.R
 import com.vpn.fastestvpnservice.beans.Protocol
 import com.vpn.fastestvpnservice.beans.isDarkTheme
+import com.vpn.fastestvpnservice.beans.languages
 import com.vpn.fastestvpnservice.beans.themesList
 import com.vpn.fastestvpnservice.constants.AppEnum
 import com.vpn.fastestvpnservice.constants.smartConnect
@@ -141,7 +145,7 @@ fun Settings(navHostController: NavHostController) {
 
                 Spacer(modifier = Modifier.height(50.dp))
                 AddTextSettings(
-                    text = "Settings",
+                    text = context.resources.getString(R.string.settings),
                     size = 28.sp,
                     color = MaterialTheme.colorScheme.primary,
                     style = MaterialTheme.typography.headlineLarge
@@ -198,6 +202,8 @@ fun Settings(navHostController: NavHostController) {
                 AddRowDarkLightTheme(
                     icon = Icons.Default.DarkMode,
                     text = "Theme")
+
+                SelectLanguage(icon = Icons.Default.Language, text = "Language")
             }
         }
     }
@@ -774,6 +780,182 @@ fun AddRowDarkLightTheme(
     }
 }
 
+@OptIn(ExperimentalMaterial3Api::class)
+@Composable
+fun SelectLanguage(
+    icon: ImageVector,
+    text: String,
+) {
+    var isLanguageSheetOpen by remember { mutableStateOf(false) }
+    val sheetState = rememberModalBottomSheetState()
+    val context = LocalContext.current
+    val basePreferenceHelper = BasePreferenceHelper(context)
+
+    Row(
+        modifier = Modifier
+            .fillMaxWidth()
+            .padding(top = 40.dp, end = 27.dp)
+            .background(Color.Transparent)
+            .pointerInput(Unit) {
+                detectTapGestures {
+                    isLanguageSheetOpen = true
+                }
+            }
+            .height(24.dp),
+        horizontalArrangement = Arrangement.Start,
+        verticalAlignment = Alignment.CenterVertically
+    ) {
+
+        Surface(
+            modifier = Modifier.padding(start = 0.dp),
+            color = Color.Transparent
+        ) {
+            Image(
+                imageVector = icon,
+                contentDescription = "Select Language",
+                modifier = Modifier
+                    .padding(start = 0.dp)
+                    .size(24.dp)
+                    .weight(1f),
+                colorFilter = ColorFilter.tint(
+                    MaterialTheme.colorScheme.primary)                )
+        }
+
+        Surface(
+            modifier = Modifier.padding(start = 0.dp),
+            color = Color.Transparent
+        ) {
+            Text(text = text,
+                style = MaterialTheme.typography.titleMedium,
+                color = MaterialTheme.colorScheme.primary,
+                maxLines = 1,
+                modifier = Modifier
+                    .padding(start = 18.dp, end = 0.dp)
+                    .weight(1f)
+            )
+        }
+        Spacer(modifier = Modifier.weight(1f))
+
+        Surface(
+            modifier = Modifier
+                .padding(start = 15.dp)
+                .align(Alignment.CenterVertically),
+            color = Color.Transparent
+
+        ) {
+            Image(
+                painter = painterResource(id = R.drawable.frontarrow3x),
+                contentDescription = "Front_Arrow",
+                modifier = Modifier
+                    .padding(start = 0.dp, end = 0.dp)
+                    .size(10.dp, 18.dp)
+                    .weight(1f),
+                colorFilter = ColorFilter.tint(
+                    MaterialTheme.colorScheme.primary
+                )
+            )
+        }
+
+    }
+
+    if (isLanguageSheetOpen) {
+        ModalBottomSheet(
+            onDismissRequest = { isLanguageSheetOpen = false
+            },
+            sheetState = sheetState,
+            containerColor = MaterialTheme.colorScheme.onBackground
+        ) {
+            Box(modifier = Modifier
+                .background(Color.Transparent)
+                .fillMaxWidth()
+                .height(300.dp)
+                .padding(start = 0.dp, top = 10.dp),
+            ) {
+                Column(
+                    verticalArrangement = Arrangement.Top,
+                    horizontalAlignment = Alignment.Start
+                ) {
+                    AddTextSettings(
+                        text = "Language",
+                        size = 18.sp,
+                        color = MaterialTheme.colorScheme.primary,
+                        bottomPadding = 20.dp,
+                        startPadding = 16.dp,
+                        style = MaterialTheme.typography.titleSmall
+                    )
+                    languages.forEach { language ->
+
+                        Row(
+                            modifier = Modifier
+                                .fillMaxWidth()
+                                .background(Color.Transparent)
+                                .padding(start = 2.dp)
+                                .selectable(
+                                    selected = language == languages[0],
+                                    onClick = {
+                                      if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+                                          when (language.name) {
+                                              languages[0].name -> {
+                                                  context.getSystemService(LocaleManager::class.java).applicationLocales = LocaleList.forLanguageTags(language.code)
+                                              }
+                                              languages[1].name -> {
+                                                  context.getSystemService(LocaleManager::class.java).applicationLocales = LocaleList.forLanguageTags(language.code)
+                                              }
+                                              languages[2].name -> {
+                                                  context.getSystemService(LocaleManager::class.java).applicationLocales = LocaleList.forLanguageTags(language.code)
+                                              }
+                                              languages[3].name -> {
+                                                  context.getSystemService(LocaleManager::class.java).applicationLocales = LocaleList.forLanguageTags(language.code)
+                                              }
+                                          }
+                                      }
+                                        isLanguageSheetOpen = false
+                                    },
+                                )
+//                                    .indication(
+//                                        indication = null,
+//                                        interactionSource = remember {
+//                                            MutableInteractionSource()
+//                                        }
+//                                    )
+                            ,
+                            verticalAlignment = Alignment.CenterVertically
+                        ) {
+//                            val themeState = isSystemInDarkTheme()
+//                            val isSystemInDarkTheme by remember { mutableStateOf(themeState) }
+                            RadioButton(selected = language == languages[0],
+                                onClick = {
+//                                    selectedtheme.value = theme
+//                                    basePreferenceHelper.saveTheme(selectedtheme.value)
+
+//                                    if (selectedtheme.value == themesList[0])
+//                                    {
+//                                        Log.d("test_theme", "true: -> $systemTheme")
+//                                        isDarkTheme.value = systemTheme
+//                                    }
+//                                    else {
+//                                        Log.d("test_theme", "false: -> $systemTheme")
+//                                        isDarkTheme.value = selectedtheme.value == themesList[2]
+//                                    }
+                                    isLanguageSheetOpen = false
+                                },
+                                colors = RadioButtonDefaults.colors(
+                                    selectedColor = colorResource(id = R.color.radio_button_blue),
+                                    unselectedColor = colorResource(id = R.color.gray_icon),)
+                            )
+                            Text(text = language.name,
+                                modifier = Modifier.padding(start = 12.dp),
+                                style = MaterialTheme.typography.bodySmall,
+                                color = MaterialTheme.colorScheme.primary
+                            )
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
 @OptIn(ExperimentalMaterial3Api::class, ExperimentalFoundationApi::class)
 @Composable
 fun ColumnScope.AddRowSettingsSmart(
@@ -974,7 +1156,9 @@ fun ColumnScope.AddRowSettingsSmart(
             },
             sheetState = sheetStateAny,
             containerColor = MaterialTheme.colorScheme.onBackground,
-            modifier = Modifier.padding(top = 15.dp).fillMaxSize()
+            modifier = Modifier
+                .padding(top = 15.dp)
+                .fillMaxSize()
         ) {
             Box(modifier = Modifier
                 .background(Color.Transparent)

+ 5 - 0
app/src/main/res/values-de/strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">FastestVPN</string>
+    <string name="settings">Einstellungen</string>
+</resources>

+ 5 - 0
app/src/main/res/values-fr/strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">FastestVPN</string>
+    <string name="settings">Paramètres</string>
+</resources>

+ 5 - 0
app/src/main/res/values-tr/strings.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+    <string name="app_name">FastestVPN</string>
+    <string name="settings">Ayarlar</string>
+</resources>

+ 2 - 1
app/src/main/res/values/strings.xml

@@ -405,7 +405,6 @@
     <string name="upgrade">Upgrade</string>
     <string name="upgrade_account">Upgrade Your Account</string>
     <string name="favourite_locations">Favorite Locations</string>
-    <string name="settings">Settings</string>
     <string name="change_password">Change Password</string>
     <string name="chat">Chat</string>
     <string name="help_faq">Help &amp; FAQ</string>
@@ -532,5 +531,7 @@
     <string name="add_widget">Add widget</string>
     <string name="app_widget_description">This is an app widget description</string>
 
+    <!-- Multi Lingual - (English-en) -->
+    <string name="settings">Settings</string>
 
 </resources>

+ 6 - 0
app/src/main/res/xml/locales_config.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
+    <locale android:name = "en" />
+    <locale android:name = "fr" />
+    <locale android:name = "de" />
+</locale-config>