diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0c71b94c..8d51136a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -80,11 +80,21 @@ android:dataExtractionRules="@xml/data_extraction_rules" android:fullBackupContent="@xml/backup_rules" android:icon="@mipmap/ic_launcher" + android:localeConfig="@xml/locales_config" android:roundIcon="@mipmap/ic_launcher_round" android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/Theme.BitchatAndroid" - tools:targetApi="31"> + tools:targetApi="33"> + + + + , + selectedLanguageTag: String, + onLanguageSelected: (String) -> Unit, + onDismiss: () -> Unit, +) { + AlertDialog( + onDismissRequest = onDismiss, + title = { Text(stringResource(R.string.about_select_language)) }, + text = { + LazyColumn(modifier = Modifier.fillMaxWidth()) { + item(key = "system") { + LanguageOptionRow( + label = stringResource(R.string.about_system_default), + selected = selectedLanguageTag.isEmpty(), + onClick = { onLanguageSelected("") }, + ) + } + items( + count = languages.size, + key = { index -> languages[index].languageTag }, + ) { index -> + val language = languages[index] + LanguageOptionRow( + label = language.endonym, + selected = selectedLanguageTag == language.languageTag, + onClick = { onLanguageSelected(language.languageTag) }, + ) + } + } + }, + confirmButton = { + TextButton(onClick = onDismiss) { + Text(stringResource(android.R.string.cancel)) + } + }, + ) +} + +@Composable +private fun LanguageOptionRow( + label: String, + selected: Boolean, + onClick: () -> Unit, +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(vertical = 8.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + RadioButton( + selected = selected, + onClick = null, + ) + Spacer(modifier = Modifier.width(12.dp)) + Text( + text = label, + style = MaterialTheme.typography.bodyLarge, + ) + } +} + +@Composable +private fun LanguageSettingsRow( + selectedLanguageName: String, + onClick: () -> Unit, +) { + Row( + modifier = Modifier + .fillMaxWidth() + .clickable(onClick = onClick) + .padding(horizontal = 16.dp, vertical = 13.dp), + verticalAlignment = Alignment.CenterVertically, + ) { + Icon( + imageVector = Icons.Filled.Language, + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.size(22.dp), + ) + Spacer(modifier = Modifier.width(16.dp)) + Text( + text = stringResource(R.string.about_language), + style = MaterialTheme.typography.bodyMedium, + fontWeight = FontWeight.Medium, + modifier = Modifier.weight(1f), + ) + Text( + text = selectedLanguageName, + style = MaterialTheme.typography.bodyMedium, + color = MaterialTheme.colorScheme.onSurfaceVariant, + maxLines = 1, + overflow = TextOverflow.Ellipsis, + modifier = Modifier.weight(1f, fill = false), + ) + Spacer(modifier = Modifier.width(8.dp)) + Icon( + imageVector = Icons.Filled.ChevronRight, + contentDescription = null, + tint = MaterialTheme.colorScheme.onSurfaceVariant, + modifier = Modifier.size(20.dp), + ) + } +} + /** * Unified settings toggle row with icon, title, subtitle, and switch * Apple-like design with proper spacing @@ -259,6 +369,28 @@ fun AboutSheet( val colorScheme = MaterialTheme.colorScheme val palette = LocalBitchatPalette.current var selectedTab by remember { mutableStateOf(AboutTab.Info) } + val supportedLanguages = remember(context) { + LanguagePreferenceManager.supportedLanguages(context) + } + var selectedLanguageTag by remember { + mutableStateOf(LanguagePreferenceManager.currentLanguageTag()) + } + var showLanguagePicker by remember { mutableStateOf(false) } + + if (showLanguagePicker) { + LanguagePickerDialog( + languages = supportedLanguages, + selectedLanguageTag = selectedLanguageTag, + onLanguageSelected = { languageTag -> + showLanguagePicker = false + if (languageTag != selectedLanguageTag) { + selectedLanguageTag = languageTag + LanguagePreferenceManager.setLanguage(languageTag) + } + }, + onDismiss = { showLanguagePicker = false }, + ) + } if (isPresented) { BitchatBottomSheet( @@ -342,6 +474,29 @@ fun AboutSheet( } } + item(key = "language") { + val selectedLanguageName = supportedLanguages + .firstOrNull { it.languageTag == selectedLanguageTag } + ?.endonym + ?: stringResource(R.string.about_system_default) + + Column { + AboutSectionLabel(text = stringResource(R.string.about_language)) + Surface( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = AboutHorizontalPadding), + color = colorScheme.surface, + shape = AboutCardShape, + ) { + LanguageSettingsRow( + selectedLanguageName = selectedLanguageName, + onClick = { showLanguagePicker = true }, + ) + } + } + } + // Settings Section - Unified Card with Toggles item(key = "settings") { LaunchedEffect(Unit) { PoWPreferenceManager.init(context) } diff --git a/app/src/main/java/com/bitchat/android/ui/LanguagePreferenceManager.kt b/app/src/main/java/com/bitchat/android/ui/LanguagePreferenceManager.kt new file mode 100644 index 00000000..91d2719e --- /dev/null +++ b/app/src/main/java/com/bitchat/android/ui/LanguagePreferenceManager.kt @@ -0,0 +1,61 @@ +package com.bitchat.android.ui + +import android.content.Context +import androidx.annotation.XmlRes +import androidx.appcompat.app.AppCompatDelegate +import androidx.core.os.LocaleListCompat +import com.bitchat.android.R +import org.xmlpull.v1.XmlPullParser +import java.util.Locale + +data class AppLanguage( + val languageTag: String, + val endonym: String, +) + +object LanguagePreferenceManager { + fun currentLanguageTag(): String = + AppCompatDelegate.getApplicationLocales().toLanguageTags() + + fun setLanguage(languageTag: String) { + AppCompatDelegate.setApplicationLocales( + LocaleListCompat.forLanguageTags(languageTag) + ) + } + + fun supportedLanguages( + context: Context, + @XmlRes localeConfig: Int = R.xml.locales_config, + ): List = readLanguageTags(context, localeConfig) + .map { languageTag -> + val locale = Locale.forLanguageTag(languageTag) + AppLanguage( + languageTag = languageTag, + endonym = locale.getDisplayName(locale) + .replaceFirstChar { first -> + if (first.isLowerCase()) first.titlecase(locale) else first.toString() + }, + ) + } + .sortedWith(compareBy(String.CASE_INSENSITIVE_ORDER) { it.endonym }) + + internal fun readLanguageTags( + context: Context, + @XmlRes localeConfig: Int, + ): List { + val parser = context.resources.getXml(localeConfig) + return buildList { + var event = parser.eventType + while (event != XmlPullParser.END_DOCUMENT) { + if (event == XmlPullParser.START_TAG && parser.name == "locale") { + parser.getAttributeValue(ANDROID_NAMESPACE, "name") + ?.takeIf(String::isNotBlank) + ?.let(::add) + } + event = parser.next() + } + } + } + + private const val ANDROID_NAMESPACE = "http://schemas.android.com/apk/res/android" +} diff --git a/app/src/main/java/com/bitchat/android/ui/OrientationAwareActivity.kt b/app/src/main/java/com/bitchat/android/ui/OrientationAwareActivity.kt index 82d8feaa..a3914c90 100644 --- a/app/src/main/java/com/bitchat/android/ui/OrientationAwareActivity.kt +++ b/app/src/main/java/com/bitchat/android/ui/OrientationAwareActivity.kt @@ -2,14 +2,14 @@ package com.bitchat.android.ui import android.content.pm.ActivityInfo import android.os.Bundle -import androidx.activity.ComponentActivity +import androidx.appcompat.app.AppCompatActivity import com.bitchat.android.utils.DeviceUtils /** * Base activity that automatically sets orientation based on device type. * Tablets can rotate to landscape, phones are locked to portrait. */ -abstract class OrientationAwareActivity : ComponentActivity() { +abstract class OrientationAwareActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index 13c8d51c..5ff9e58b 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -389,4 +389,7 @@ تحقّق من الملاحظات المتروكة هنا تُركت ملاحظة واحدة هنا — انقر للقراءة تُركت %d ملاحظات هنا — انقر للقراءة + اللغة + إعداد النظام الافتراضي + اختر اللغة diff --git a/app/src/main/res/values-bn/strings.xml b/app/src/main/res/values-bn/strings.xml index 7c2617a4..6a68b222 100644 --- a/app/src/main/res/values-bn/strings.xml +++ b/app/src/main/res/values-bn/strings.xml @@ -376,4 +376,7 @@ এখানে রাখা নোট আছে কি না দেখুন এখানে 1টি নোট রাখা আছে — পড়তে ট্যাপ করুন এখানে %dটি নোট রাখা আছে — পড়তে ট্যাপ করুন + ভাষা + সিস্টেম ডিফল্ট + ভাষা নির্বাচন করুন diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index b13fb001..eb613160 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -390,4 +390,7 @@ nachsehen, ob hier notizen hinterlassen wurden 1 notiz hier hinterlassen — tippen zum lesen %d notizen hier hinterlassen — tippen zum lesen + Sprache + Systemstandard + Sprache auswählen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index e1ac2c2b..fe5a9cc7 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -389,4 +389,7 @@ buscar notas dejadas aquí 1 nota dejada aquí — toca para leer %d notas dejadas aquí — toca para leer + Idioma + Predeterminado del sistema + Seleccionar idioma diff --git a/app/src/main/res/values-fa/strings.xml b/app/src/main/res/values-fa/strings.xml index a3e81d29..e15eea5b 100644 --- a/app/src/main/res/values-fa/strings.xml +++ b/app/src/main/res/values-fa/strings.xml @@ -376,4 +376,7 @@ یادداشت‌های باقی‌مانده در اینجا را بررسی کنید ۱ یادداشت اینجا باقی مانده — برای خواندن ضربه بزنید %d یادداشت اینجا باقی مانده — برای خواندن ضربه بزنید + زبان + پیش‌فرض سیستم + انتخاب زبان diff --git a/app/src/main/res/values-fil/strings.xml b/app/src/main/res/values-fil/strings.xml index 1da03f06..dba9aea1 100644 --- a/app/src/main/res/values-fil/strings.xml +++ b/app/src/main/res/values-fil/strings.xml @@ -393,4 +393,7 @@ tingnan kung may mga note na naiwan dito 1 note ang naiwan dito — i-tap para basahin %d note ang naiwan dito — i-tap para basahin + Wika + Default ng system + Pumili ng wika diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index e632bdb8..4c53c77f 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -407,4 +407,7 @@ vérifier s\'il y a des notes laissées ici 1 note laissée ici — appuyez pour lire %d notes laissées ici — appuyez pour lire + Langue + Langue du système + Choisir la langue diff --git a/app/src/main/res/values-he/strings.xml b/app/src/main/res/values-he/strings.xml index 3793942b..54712e1b 100644 --- a/app/src/main/res/values-he/strings.xml +++ b/app/src/main/res/values-he/strings.xml @@ -57,4 +57,7 @@ בדיקה אם הושארו כאן פתקים פתק אחד הושאר כאן — הקש לקריאה %d פתקים הושארו כאן — הקש לקריאה + שפה + ברירת המחדל של המערכת + בחירת שפה diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 1a393f38..13a40c68 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -389,4 +389,7 @@ देखें कि यहाँ नोट छोड़े गए हैं या नहीं यहाँ 1 नोट छोड़ा गया है — पढ़ने के लिए टैप करें यहाँ %d नोट छोड़े गए हैं — पढ़ने के लिए टैप करें + भाषा + सिस्टम डिफ़ॉल्ट + भाषा चुनें diff --git a/app/src/main/res/values-id/strings.xml b/app/src/main/res/values-id/strings.xml index 934556e4..962af5b0 100644 --- a/app/src/main/res/values-id/strings.xml +++ b/app/src/main/res/values-id/strings.xml @@ -389,4 +389,7 @@ periksa catatan yang ditinggalkan di sini 1 catatan ditinggalkan di sini — ketuk untuk membaca %d catatan ditinggalkan di sini — ketuk untuk membaca + Bahasa + Default sistem + Pilih bahasa diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 7e67de6d..393a7f1c 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -422,4 +422,7 @@ controlla se ci sono note lasciate qui 1 nota lasciata qui — tocca per leggere %d note lasciate qui — tocca per leggere + Lingua + Predefinita di sistema + Seleziona lingua diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 1e7da71d..8d7ed0e6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -389,4 +389,7 @@ ここに残されたメモを確認 ここに1件のメモがあります — タップして読む ここに%d件のメモがあります — タップして読む + 言語 + システムのデフォルト + 言語を選択 diff --git a/app/src/main/res/values-ka/strings.xml b/app/src/main/res/values-ka/strings.xml index 4994f9cc..18753531 100644 --- a/app/src/main/res/values-ka/strings.xml +++ b/app/src/main/res/values-ka/strings.xml @@ -376,4 +376,7 @@ აქ დატოვებული ჩანაწერების შემოწმება აქ 1 ჩანაწერია დატოვებული — წასაკითხად შეეხეთ აქ %d ჩანაწერია დატოვებული — წასაკითხად შეეხეთ + ენა + სისტემის ნაგულისხმევი + ენის არჩევა diff --git a/app/src/main/res/values-ko/strings.xml b/app/src/main/res/values-ko/strings.xml index 7327257a..435691fa 100644 --- a/app/src/main/res/values-ko/strings.xml +++ b/app/src/main/res/values-ko/strings.xml @@ -389,4 +389,7 @@ 여기 남겨진 쪽지 확인 여기 남겨진 쪽지 1개 — 탭하여 읽기 여기 남겨진 쪽지 %d개 — 탭하여 읽기 + 언어 + 시스템 기본값 + 언어 선택 diff --git a/app/src/main/res/values-mg/strings.xml b/app/src/main/res/values-mg/strings.xml index 168eebe7..1dade6f0 100644 --- a/app/src/main/res/values-mg/strings.xml +++ b/app/src/main/res/values-mg/strings.xml @@ -402,4 +402,7 @@ hizaha raha misy naoty navela teto naoty 1 no navela teto — tsindrio raha hamaky naoty %d no navela teto — tsindrio raha hamaky + Fiteny + Fitenin’ny rafitra + Safidio ny fiteny diff --git a/app/src/main/res/values-ms/strings.xml b/app/src/main/res/values-ms/strings.xml index add7b467..0e673a37 100644 --- a/app/src/main/res/values-ms/strings.xml +++ b/app/src/main/res/values-ms/strings.xml @@ -44,4 +44,7 @@ semak nota yang ditinggalkan di sini 1 nota ditinggalkan di sini — ketik untuk baca %d nota ditinggalkan di sini — ketik untuk baca + Bahasa + Lalai sistem + Pilih bahasa diff --git a/app/src/main/res/values-ne/strings.xml b/app/src/main/res/values-ne/strings.xml index 48a7afbd..be59a559 100644 --- a/app/src/main/res/values-ne/strings.xml +++ b/app/src/main/res/values-ne/strings.xml @@ -393,4 +393,7 @@ यहाँ छोडिएका नोटहरू छन् कि हेर्नुहोस् यहाँ 1 नोट छोडिएको छ — पढ्न ट्याप गर्नुहोस् यहाँ %d नोटहरू छोडिएका छन् — पढ्न ट्याप गर्नुहोस् + भाषा + प्रणालीको पूर्वनिर्धारित + भाषा छान्नुहोस् diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 0eeaec55..ff35eae6 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -420,4 +420,7 @@ kijk of hier notities zijn achtergelaten 1 notitie hier achtergelaten — tik om te lezen %d notities hier achtergelaten — tik om te lezen + Taal + Systeemstandaard + Taal selecteren diff --git a/app/src/main/res/values-pa-rPK/strings.xml b/app/src/main/res/values-pa-rPK/strings.xml index 5f5f5f75..8d9ee0db 100644 --- a/app/src/main/res/values-pa-rPK/strings.xml +++ b/app/src/main/res/values-pa-rPK/strings.xml @@ -376,4 +376,7 @@ ایتھے چھڈے نوٹس ویکھو ایتھے 1 نوٹ چھڈیا گیا — پڑھݨ لئی ٹیپ کرو ایتھے %d نوٹس چھڈے گئے — پڑھݨ لئی ٹیپ کرو + بولی + سسٹم دی ڈیفالٹ + بولی چݨو diff --git a/app/src/main/res/values-pl/strings.xml b/app/src/main/res/values-pl/strings.xml index f1a67349..bde25680 100644 --- a/app/src/main/res/values-pl/strings.xml +++ b/app/src/main/res/values-pl/strings.xml @@ -57,4 +57,7 @@ sprawdź, czy zostawiono tutaj notatki 1 notatka zostawiona tutaj — stuknij, aby przeczytać %d notatek zostawionych tutaj — stuknij, aby przeczytać + Język + Domyślny systemu + Wybierz język diff --git a/app/src/main/res/values-pt-rBR/strings.xml b/app/src/main/res/values-pt-rBR/strings.xml index fd4901ef..3c2008b3 100644 --- a/app/src/main/res/values-pt-rBR/strings.xml +++ b/app/src/main/res/values-pt-rBR/strings.xml @@ -388,4 +388,7 @@ ver se há notas deixadas aqui 1 nota deixada aqui — toque para ler %d notas deixadas aqui — toque para ler + Idioma + Padrão do sistema + Selecionar idioma diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index 5247916e..76adeff2 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -389,4 +389,7 @@ ver se há notas deixadas aqui 1 nota deixada aqui — toque para ler %d notas deixadas aqui — toque para ler + Idioma + Predefinição do sistema + Selecionar idioma diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 4dc08928..77f9c1ff 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -383,4 +383,7 @@ проверить, есть ли здесь заметки здесь оставлена 1 заметка — нажмите, чтобы прочитать здесь оставлено заметок: %d — нажмите, чтобы прочитать + Язык + Системный язык + Выбрать язык diff --git a/app/src/main/res/values-sv/strings.xml b/app/src/main/res/values-sv/strings.xml index dcfda208..7b21fd60 100644 --- a/app/src/main/res/values-sv/strings.xml +++ b/app/src/main/res/values-sv/strings.xml @@ -381,4 +381,7 @@ kolla om anteckningar lämnats här 1 anteckning lämnad här — tryck för att läsa %d anteckningar lämnade här — tryck för att läsa + Språk + Systemstandard + Välj språk diff --git a/app/src/main/res/values-ta/strings.xml b/app/src/main/res/values-ta/strings.xml index 05bd4750..5a303157 100644 --- a/app/src/main/res/values-ta/strings.xml +++ b/app/src/main/res/values-ta/strings.xml @@ -44,4 +44,7 @@ இங்கே விடப்பட்ட குறிப்புகள் உள்ளதா எனப் பார்க்கவும் இங்கே 1 குறிப்பு விடப்பட்டுள்ளது — படிக்க தட்டவும் இங்கே %d குறிப்புகள் விடப்பட்டுள்ளன — படிக்க தட்டவும் + மொழி + கணினி இயல்புநிலை + மொழியைத் தேர்ந்தெடுக்கவும் diff --git a/app/src/main/res/values-th/strings.xml b/app/src/main/res/values-th/strings.xml index 7e1fc05a..7af338eb 100644 --- a/app/src/main/res/values-th/strings.xml +++ b/app/src/main/res/values-th/strings.xml @@ -376,4 +376,7 @@ ดูว่ามีโน้ตทิ้งไว้ที่นี่หรือไม่ มี 1 โน้ตทิ้งไว้ที่นี่ — แตะเพื่ออ่าน มี %d โน้ตทิ้งไว้ที่นี่ — แตะเพื่ออ่าน + ภาษา + ค่าเริ่มต้นของระบบ + เลือกภาษา diff --git a/app/src/main/res/values-tr/strings.xml b/app/src/main/res/values-tr/strings.xml index b81fdd08..6158fb08 100644 --- a/app/src/main/res/values-tr/strings.xml +++ b/app/src/main/res/values-tr/strings.xml @@ -381,4 +381,7 @@ buraya bırakılan notlara bak buraya 1 not bırakıldı — okumak için dokun buraya %d not bırakıldı — okumak için dokun + Dil + Sistem varsayılanı + Dil seçin diff --git a/app/src/main/res/values-uk/strings.xml b/app/src/main/res/values-uk/strings.xml index 9ca2d2d0..662890c0 100644 --- a/app/src/main/res/values-uk/strings.xml +++ b/app/src/main/res/values-uk/strings.xml @@ -44,4 +44,7 @@ перевірити, чи залишено тут нотатки тут залишено 1 нотатку — торкніться, щоб прочитати тут залишено %d нотаток — торкніться, щоб прочитати + Мова + Системна мова + Вибрати мову diff --git a/app/src/main/res/values-ur/strings.xml b/app/src/main/res/values-ur/strings.xml index 36c5265d..9cc214de 100644 --- a/app/src/main/res/values-ur/strings.xml +++ b/app/src/main/res/values-ur/strings.xml @@ -389,4 +389,7 @@ دیکھیں کہ یہاں نوٹ چھوڑے گئے ہیں یا نہیں یہاں 1 نوٹ چھوڑا گیا ہے — پڑھنے کے لیے تھپتھپائیں یہاں %d نوٹ چھوڑے گئے ہیں — پڑھنے کے لیے تھپتھپائیں + زبان + سسٹم ڈیفالٹ + زبان منتخب کریں diff --git a/app/src/main/res/values-vi/strings.xml b/app/src/main/res/values-vi/strings.xml index 20028f38..226eae82 100644 --- a/app/src/main/res/values-vi/strings.xml +++ b/app/src/main/res/values-vi/strings.xml @@ -376,4 +376,7 @@ kiểm tra ghi chú để lại ở đây có 1 ghi chú để lại ở đây — chạm để đọc có %d ghi chú để lại ở đây — chạm để đọc + Ngôn ngữ + Mặc định hệ thống + Chọn ngôn ngữ diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 438131b0..3a51c135 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -56,4 +56,7 @@ 查看这里留下的留言 这里留有 1 条留言 — 点按阅读 这里留有 %d 条留言 — 点按阅读 + 语言 + 跟随系统 + 选择语言 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 328696a0..ce778247 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -56,4 +56,7 @@ 查看這裡留下的留言 這裡留有 1 則留言 — 點按閱讀 這裡留有 %d 則留言 — 點按閱讀 + 語言 + 跟隨系統 + 選擇語言 diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index d6eada8c..b142e9d2 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -406,4 +406,7 @@ 查看这里留下的留言 这里留有 1 条留言 — 点按阅读 这里留有 %d 条留言 — 点按阅读 + 语言 + 跟随系统 + 选择语言 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a12482ca..c415a569 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -567,4 +567,7 @@ Bluetooth Recommended + Language + System default + Select language diff --git a/app/src/main/res/xml/locales_config.xml b/app/src/main/res/xml/locales_config.xml new file mode 100644 index 00000000..4bfd7251 --- /dev/null +++ b/app/src/main/res/xml/locales_config.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/test/kotlin/com/bitchat/android/ui/LanguageCatalogContractTest.kt b/app/src/test/kotlin/com/bitchat/android/ui/LanguageCatalogContractTest.kt new file mode 100644 index 00000000..1fa49ea8 --- /dev/null +++ b/app/src/test/kotlin/com/bitchat/android/ui/LanguageCatalogContractTest.kt @@ -0,0 +1,71 @@ +package com.bitchat.android.ui + +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Test +import java.io.File + +class LanguageCatalogContractTest { + private val resourcesDirectory = File("src/main/res") + + @Test + fun `locale config contains every shipped locale exactly once`() { + val shippedLanguageTags = resourcesDirectory + .listFiles() + .orEmpty() + .filter { it.isDirectory && it.name.startsWith("values-") } + .mapNotNull { directory -> directory.name.toLanguageTagOrNull() } + .toSet() + + val configuredLanguageTags = Regex("""android:name="([^"]+)"""") + .findAll(File(resourcesDirectory, "xml/locales_config.xml").readText()) + .map { match -> match.groupValues[1] } + .toList() + + assertEquals( + "Locale configuration must not contain duplicate entries", + configuredLanguageTags.toSet().size, + configuredLanguageTags.size, + ) + assertEquals(shippedLanguageTags, configuredLanguageTags.toSet()) + } + + @Test + fun `language picker strings exist in every locale pack`() { + val requiredKeys = setOf( + "about_language", + "about_system_default", + "about_select_language", + ) + + resourcesDirectory + .listFiles() + .orEmpty() + .filter { directory -> + directory.isDirectory && + (directory.name == "values" || directory.name.toLanguageTagOrNull() != null) + } + .forEach { directory -> + val strings = File(directory, "strings.xml").readText() + requiredKeys.forEach { key -> + assertTrue( + "$key is missing from ${directory.name}/strings.xml", + """name="$key""" in strings, + ) + } + } + } + + private fun String.toLanguageTagOrNull(): String? { + if (!startsWith("values-") || this == "values-night") return null + return removePrefix("values-") + .split("-") + .joinToString("-") { qualifier -> + if (qualifier.startsWith("r") && qualifier.length == 3) { + qualifier.drop(1) + } else { + qualifier + } + } + } +}