From 58b551265c45e14e07d6e5ace7bac8821b4f72c4 Mon Sep 17 00:00:00 2001 From: Vitor Pamplona Date: Fri, 26 Jun 2026 14:47:23 -0400 Subject: [PATCH 1/2] fix: delete per-account dir on account removal + sweep orphans at startup Account deletion cleaned up the saved-accounts list and encrypted prefs but never removed the on-disk files/accounts// directory (the MLS/Marmot stores created in AccountCacheState.loadAccount). Every deleted or logged-out account leaked its folder, so the on-disk account count drifted far above the number of accounts shown in the switcher (16 dirs vs 6 saved on a test device). - AccountCacheState: add deleteAccountFiles(pubkey) to remove the directory and pruneOrphanAccountDirs(keepPubkeys) to clear dirs no longer backed by a saved account. - AccountSessionManager.logOff: delete the files in both delete branches. - AppModules: one-time startup sweep, keyed by the hex of every saved account, to clean up folders leaked before this fix. - LocalPreferences.savedAccounts(): make the lazy init race-safe with a dedicated mutex + double-checked locking. Multiple startup coroutines (account load, always-on notification service, the new orphan sweep) call it concurrently; the old check-then-act could run the IO read in parallel and double-write ALL_ACCOUNT_INFO during the legacy migration. Verified on-device: 16 -> 6 account dirs after one launch, stable across restarts, no startup regressions. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../com/vitorpamplona/amethyst/AppModules.kt | 13 ++++ .../amethyst/LocalPreferences.kt | 69 +++++++++++-------- .../model/accountsCache/AccountCacheState.kt | 33 +++++++++ .../ui/screen/AccountSessionManager.kt | 2 + 4 files changed, 88 insertions(+), 29 deletions(-) diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt index 4b0d1eeac6..766b24794c 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/AppModules.kt @@ -113,6 +113,7 @@ import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinBackend import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinCoreRpcClient import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.TOR_ELECTRUMX_SERVERS +import com.vitorpamplona.quartz.nip19Bech32.decodePublicKeyAsHexOrNull import com.vitorpamplona.quartz.nipB7Blossom.BlossomServersEvent import com.vitorpamplona.quartz.nipBCOnchainZaps.chain.CachingOnchainBackend import com.vitorpamplona.quartz.nipBCOnchainZaps.chain.EsploraBackend @@ -760,6 +761,18 @@ class AppModules( sessionManager.loginWithDefaultAccountIfLoggedOff() } + // One-time hygiene: remove per-account directories (MLS/Marmot stores) left behind + // by accounts that are no longer saved — account deletion historically didn't clean + // them up, so they leaked disk across every add/remove. + applicationIOScope.launch { + val keep = + LocalPreferences + .allSavedAccounts() + .mapNotNull { decodePublicKeyAsHexOrNull(it.npub) } + .toSet() + accountsCache.pruneOrphanAccountDirs(keep) + } + // forces initialization of uiPrefs in the main thread to avoid blinking themes uiPrefs diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt index 7daa5f13c9..09864df91f 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/LocalPreferences.kt @@ -183,6 +183,12 @@ object LocalPreferences { private var currentAccount: String? = null private val savedAccounts: MutableStateFlow?> = MutableStateFlow(null) + + // Guards the one-time lazy population of [savedAccounts]. Without it, concurrent callers + // of savedAccounts() (e.g. the account-load path, the always-on notification service, and + // the orphan-dir sweep, all launched at startup) would each see a null value, run the IO + // read in parallel, and the migration branch could double-write ALL_ACCOUNT_INFO. + private val savedAccountsMutex = Mutex() private val cachedAccounts: MutableMap = mutableMapOf() suspend fun currentAccount(): String? { @@ -212,41 +218,46 @@ object LocalPreferences { } private suspend fun savedAccounts(): List { - if (savedAccounts.value == null) { - withContext(Dispatchers.IO) { - with(encryptedPreferences()) { - val newSystemOfAccounts = - getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let { - JsonMapper.fromJson>(it) - } + // Fast path: already populated, no lock needed. + savedAccounts.value?.let { return it } - if (!newSystemOfAccounts.isNullOrEmpty()) { - savedAccounts.emit(newSystemOfAccounts) - } else { - val oldAccounts = getString(PrefKeys.SAVED_ACCOUNTS, null)?.split(COMMA) ?: listOf() + return savedAccountsMutex.withLock { + // Re-check under the lock: another coroutine may have populated it while we waited. + savedAccounts.value ?: loadSavedAccountsFromStorage().also { savedAccounts.emit(it) } + } + } - val migrated = - oldAccounts.map { npub -> - AccountInfo( - npub, - encryptedPreferences(npub).getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false), - (encryptedPreferences(npub).getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "").isNotBlank(), - false, - ) - } - - savedAccounts.emit(migrated) - - edit { - putString(PrefKeys.ALL_ACCOUNT_INFO, JsonMapper.toJson(migrated)) - } + private suspend fun loadSavedAccountsFromStorage(): List = + withContext(Dispatchers.IO) { + with(encryptedPreferences()) { + val newSystemOfAccounts = + getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let { + JsonMapper.fromJson>(it) } + + if (!newSystemOfAccounts.isNullOrEmpty()) { + newSystemOfAccounts + } else { + val oldAccounts = getString(PrefKeys.SAVED_ACCOUNTS, null)?.split(COMMA) ?: listOf() + + val migrated = + oldAccounts.map { npub -> + AccountInfo( + npub, + encryptedPreferences(npub).getBoolean(PrefKeys.LOGIN_WITH_EXTERNAL_SIGNER, false), + (encryptedPreferences(npub).getString(PrefKeys.NOSTR_PRIVKEY, "") ?: "").isNotBlank(), + false, + ) + } + + edit { + putString(PrefKeys.ALL_ACCOUNT_INFO, JsonMapper.toJson(migrated)) + } + + migrated } } } - // it's always not null when it gets here. - return savedAccounts.value!! - } fun accountsFlow() = savedAccounts diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt index 8a84e0dbbc..d307f3a07b 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/model/accountsCache/AccountCacheState.kt @@ -108,6 +108,39 @@ class AccountCacheState( } } + /** The on-disk root that [loadAccount] creates a per-account directory under. */ + private fun accountsRootDir() = File(rootFilesDir(), "accounts") + + /** + * Deletes the on-disk per-account directory (the MLS/Marmot stores created in + * [loadAccount]). Call only on permanent account deletion — [removeAccount] just + * drops the in-memory copy and leaves these files behind. + */ + fun deleteAccountFiles(pubkey: HexKey) { + val dir = File(accountsRootDir(), pubkey) + if (dir.exists() && !dir.deleteRecursively()) { + Log.w("AccountCacheState", "Failed to delete account directory ${dir.absolutePath}") + } + } + + /** + * Removes per-account directories left behind by accounts that are no longer saved + * (e.g. deleted before [deleteAccountFiles] existed). Keeps only [keepPubkeys]. Safe to + * run alongside [loadAccount]: it only loads saved accounts, whose pubkeys are kept. + */ + fun pruneOrphanAccountDirs(keepPubkeys: Set) { + val children = accountsRootDir().listFiles() ?: return + children.forEach { child -> + if (child.isDirectory && child.name !in keepPubkeys) { + if (child.deleteRecursively()) { + Log.d("AccountCacheState") { "Pruned orphan account dir ${child.name.take(8)}…" } + } else { + Log.w("AccountCacheState", "Failed to prune orphan account dir ${child.absolutePath}") + } + } + } + } + fun loadAccount(accountSettings: AccountSettings): Account = loadAccount( signer = diff --git a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt index e4db4c00a6..0c85dc7081 100644 --- a/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt +++ b/amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/AccountSessionManager.kt @@ -386,12 +386,14 @@ class AccountSessionManager( // log off and relogin with the 0 account localPreferences.deleteAccount(accountInfo) accountsCache.removeAccount(hex) + accountsCache.deleteAccountFiles(hex) Amethyst.instance.scheduledPostStore.removeForAccount(hex) loginWithDefaultAccount() } else { // delete without switching logins localPreferences.deleteAccount(accountInfo) accountsCache.removeAccount(hex) + accountsCache.deleteAccountFiles(hex) Amethyst.instance.scheduledPostStore.removeForAccount(hex) } } From 5a297f17a1d76be49e265072c98440a72b83a6d1 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 26 Jun 2026 18:58:08 +0000 Subject: [PATCH 2/2] fix: move orphaned browser/napplet translations to :commons The browser/napplet strings (browser_address_hint, browser_console_title, browser_console_title_short, browser_console_clear, napplet_untitled) were moved to :commons, but their per-locale translations were left behind in amethyst's values-*/strings.xml. With the default keys gone from amethyst, lint flagged them as ExtraTranslation (80 errors across 16 locales). Move the translations into commons/src/androidMain/res/values-*/strings.xml so the default key and its translations live in the same module, preserving the existing translation work. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01Uza7sGxYPZtY43Ln2yH8FQ --- amethyst/src/main/res/values-cs/strings.xml | 5 ----- amethyst/src/main/res/values-de/strings.xml | 5 ----- amethyst/src/main/res/values-eo/strings.xml | 5 ----- amethyst/src/main/res/values-es/strings.xml | 5 ----- amethyst/src/main/res/values-fa/strings.xml | 5 ----- amethyst/src/main/res/values-fr/strings.xml | 5 ----- amethyst/src/main/res/values-in/strings.xml | 5 ----- amethyst/src/main/res/values-ja/strings.xml | 5 ----- amethyst/src/main/res/values-nl-rBE/strings.xml | 5 ----- amethyst/src/main/res/values-nl/strings.xml | 5 ----- amethyst/src/main/res/values-ru/strings.xml | 5 ----- amethyst/src/main/res/values-ta/strings.xml | 5 ----- amethyst/src/main/res/values-th/strings.xml | 5 ----- amethyst/src/main/res/values-tr/strings.xml | 5 ----- amethyst/src/main/res/values-uk/strings.xml | 5 ----- amethyst/src/main/res/values-zh/strings.xml | 5 ----- commons/src/androidMain/res/values-cs/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-de/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-eo/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-es/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-fa/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-fr/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-in/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-ja/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-nl-rBE/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-nl/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-ru/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-ta/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-th/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-tr/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-uk/strings.xml | 8 ++++++++ commons/src/androidMain/res/values-zh/strings.xml | 8 ++++++++ 32 files changed, 128 insertions(+), 80 deletions(-) create mode 100644 commons/src/androidMain/res/values-cs/strings.xml create mode 100644 commons/src/androidMain/res/values-de/strings.xml create mode 100644 commons/src/androidMain/res/values-eo/strings.xml create mode 100644 commons/src/androidMain/res/values-es/strings.xml create mode 100644 commons/src/androidMain/res/values-fa/strings.xml create mode 100644 commons/src/androidMain/res/values-fr/strings.xml create mode 100644 commons/src/androidMain/res/values-in/strings.xml create mode 100644 commons/src/androidMain/res/values-ja/strings.xml create mode 100644 commons/src/androidMain/res/values-nl-rBE/strings.xml create mode 100644 commons/src/androidMain/res/values-nl/strings.xml create mode 100644 commons/src/androidMain/res/values-ru/strings.xml create mode 100644 commons/src/androidMain/res/values-ta/strings.xml create mode 100644 commons/src/androidMain/res/values-th/strings.xml create mode 100644 commons/src/androidMain/res/values-tr/strings.xml create mode 100644 commons/src/androidMain/res/values-uk/strings.xml create mode 100644 commons/src/androidMain/res/values-zh/strings.xml diff --git a/amethyst/src/main/res/values-cs/strings.xml b/amethyst/src/main/res/values-cs/strings.xml index d8dec8be97..c8d6a6cc09 100644 --- a/amethyst/src/main/res/values-cs/strings.xml +++ b/amethyst/src/main/res/values-cs/strings.xml @@ -4873,15 +4873,11 @@ Prohlížeč -Hledat nebo zadat adresu Vymazat -Vymazat -Konzola (%1$d) -Konzola Oblíbené @@ -5273,7 +5269,6 @@ Odebrat -Nepojmenovaný nApplet nApplets diff --git a/amethyst/src/main/res/values-de/strings.xml b/amethyst/src/main/res/values-de/strings.xml index b83e2f53dc..d6ee190771 100644 --- a/amethyst/src/main/res/values-de/strings.xml +++ b/amethyst/src/main/res/values-de/strings.xml @@ -4782,15 +4782,11 @@ anz der Bedingungen ist erforderlich Browser -Suchen oder Adresse eingeben Löschen -Löschen -Konsole (%1$d) -Konsole Favoriten @@ -5182,7 +5178,6 @@ anz der Bedingungen ist erforderlich Widerrufen -Unbenanntes nApplet nApplets diff --git a/amethyst/src/main/res/values-eo/strings.xml b/amethyst/src/main/res/values-eo/strings.xml index 8647b0c059..82720eabfe 100644 --- a/amethyst/src/main/res/values-eo/strings.xml +++ b/amethyst/src/main/res/values-eo/strings.xml @@ -726,11 +726,7 @@ nSite-oj Ankoraŭ neniuj nSite-oj trovitaj. Retumilo -Serĉi aŭ enigi adreson Reŝargi -Konzolo -Konzolo (%1$d) -Viŝi Ŝargante per Tor. Klaku por uzi la malferma reton. Ŝargante per la malferma reto. Klaku por uzi Tor. La en-aplikaĵa retumilo bezonas Android 11 aŭ pli novan. @@ -763,7 +759,6 @@ Forgesi ĉi tiun nApplet-on Blokita Revoki -Sennoma nApplet Ankoraŭ neniuj nApplet-oj trovitaj. nApplet %1$s… Ŝelo diff --git a/amethyst/src/main/res/values-es/strings.xml b/amethyst/src/main/res/values-es/strings.xml index d377ab3fee..efc8db68ef 100644 --- a/amethyst/src/main/res/values-es/strings.xml +++ b/amethyst/src/main/res/values-es/strings.xml @@ -1085,7 +1085,6 @@ Revocar -NApplet sin título No se han encontrado nApplets todavía. @@ -3333,15 +3332,11 @@ Navegador -Buscar o introducir dirección Recargar -Consola -Consola (%1$d) -Borrar Cargando a través de Tor. Toca para usar la web abierta. diff --git a/amethyst/src/main/res/values-fa/strings.xml b/amethyst/src/main/res/values-fa/strings.xml index 4e28d87bf8..aeec1af6bf 100644 --- a/amethyst/src/main/res/values-fa/strings.xml +++ b/amethyst/src/main/res/values-fa/strings.xml @@ -4725,15 +4725,11 @@ مرورگر - جستجو یا وارد کردن آدرس بارگذاری مجدد - کنسول - کنسول (%1$d) - پاک کردن بارگذاری از طریق Tor. برای استفاده از وب باز ضربه بزنید. @@ -4799,7 +4795,6 @@ لغو - nApplet بی‌عنوان هنوز هیچ nApplet ای یافت نشد. diff --git a/amethyst/src/main/res/values-fr/strings.xml b/amethyst/src/main/res/values-fr/strings.xml index e0603887b5..9b8c797b55 100644 --- a/amethyst/src/main/res/values-fr/strings.xml +++ b/amethyst/src/main/res/values-fr/strings.xml @@ -2788,15 +2788,11 @@ Navigateur -Rechercher ou saisir une adresse Recharger -Console -Console (%1$d) -Effacer Chargement via Tor. Appuyer pour utiliser le web ouvert. @@ -2862,7 +2858,6 @@ Révoquer -nApplet sans titre Aucun nApplet trouvé pour l\'instant. diff --git a/amethyst/src/main/res/values-in/strings.xml b/amethyst/src/main/res/values-in/strings.xml index ad51ec6ed5..26491e9405 100644 --- a/amethyst/src/main/res/values-in/strings.xml +++ b/amethyst/src/main/res/values-in/strings.xml @@ -5173,15 +5173,11 @@ Browser - Cari atau masukkan alamat Muat ulang - Konsol - Konsol (%1$d) - Hapus Memuat melalui Tor. Ketuk untuk menggunakan web terbuka. @@ -5247,7 +5243,6 @@ Cabut - nApplet Tanpa Judul Belum ada nApplet ditemukan. diff --git a/amethyst/src/main/res/values-ja/strings.xml b/amethyst/src/main/res/values-ja/strings.xml index bf36947301..72d88c5695 100644 --- a/amethyst/src/main/res/values-ja/strings.xml +++ b/amethyst/src/main/res/values-ja/strings.xml @@ -5280,15 +5280,11 @@ ブラウザ - 検索またはアドレスを入力 再読み込み - コンソール - コンソール(%1$d) - クリア Tor経由で読み込み中。タップしてオープンウェブを使用します。 @@ -5354,7 +5350,6 @@ 取り消す - 無題の nApplet nApplet はまだ見つかりません。 diff --git a/amethyst/src/main/res/values-nl-rBE/strings.xml b/amethyst/src/main/res/values-nl-rBE/strings.xml index e59ab6f8c4..9066679569 100644 --- a/amethyst/src/main/res/values-nl-rBE/strings.xml +++ b/amethyst/src/main/res/values-nl-rBE/strings.xml @@ -5321,15 +5321,11 @@ Browser -Zoeken of adres invoeren Herladen -Console -Console (%1$d) -Wissen Laden via Tor. Tik om het open web te gebruiken. @@ -5395,7 +5391,6 @@ Intrekken -Naamloze nApplet Nog geen nApplets gevonden. diff --git a/amethyst/src/main/res/values-nl/strings.xml b/amethyst/src/main/res/values-nl/strings.xml index 174206ad53..e6de54a4a4 100644 --- a/amethyst/src/main/res/values-nl/strings.xml +++ b/amethyst/src/main/res/values-nl/strings.xml @@ -4603,15 +4603,11 @@ Browser -Zoeken of adres invoeren Herladen -Console -Console (%1$d) -Wissen Laden via Tor. Tik om het open web te gebruiken. @@ -4677,7 +4673,6 @@ Intrekken -Naamloze nApplet Nog geen nApplets gevonden. diff --git a/amethyst/src/main/res/values-ru/strings.xml b/amethyst/src/main/res/values-ru/strings.xml index 92be83a987..72f693a61a 100644 --- a/amethyst/src/main/res/values-ru/strings.xml +++ b/amethyst/src/main/res/values-ru/strings.xml @@ -4871,15 +4871,11 @@ Браузер - Поиск или введите адрес Обновить - Консоль - Консоль (%1$d) - Очистить Загрузка через Tor. Нажмите, чтобы использовать открытую сеть. @@ -4945,7 +4941,6 @@ Отозвать - nApplet без названия nApplets пока не найдены. diff --git a/amethyst/src/main/res/values-ta/strings.xml b/amethyst/src/main/res/values-ta/strings.xml index 8678969e79..a2e1dc0211 100644 --- a/amethyst/src/main/res/values-ta/strings.xml +++ b/amethyst/src/main/res/values-ta/strings.xml @@ -677,11 +677,7 @@ nSites இன்னும் nSites எதுவும் கிடைக்கவில்லை. உலாவி -தேடவும் அல்லது முகவரியை உள்ளிடவும் மீண்டும் ஏற்று -கன்சோல் -கன்சோல் (%1$d) -அழிக்கவும் Tor மூலம் ஏற்றுகிறது. திறந்த வலையை பயன்படுத்த தட்டவும். திறந்த வலை மூலம் ஏற்றுகிறது. Tor ஐ பயன்படுத்த தட்டவும். உள்-பயன்பாட்டு உலாவிக்கு Android 11 அல்லது புதியது தேவை. @@ -714,7 +710,6 @@ இந்த nApplet ஐ மறக்கவும் தடுக்கப்பட்டது திரும்பப் பெறவும் -தலைப்பற்ற nApplet இன்னும் nApplets எதுவும் கிடைக்கவில்லை. nApplet %1$s… Shell diff --git a/amethyst/src/main/res/values-th/strings.xml b/amethyst/src/main/res/values-th/strings.xml index 73b7fa5b5c..89c439c3c8 100644 --- a/amethyst/src/main/res/values-th/strings.xml +++ b/amethyst/src/main/res/values-th/strings.xml @@ -4845,15 +4845,11 @@ เบราว์เซอร์ - ค้นหาหรือป้อนที่อยู่ โหลดใหม่ - คอนโซล - คอนโซล (%1$d) - ล้าง กำลังโหลดผ่าน Tor แตะเพื่อใช้เว็บแบบเปิด @@ -4919,7 +4915,6 @@ เพิกถอน - nApplet ไม่มีชื่อ ยังไม่พบ nApplets diff --git a/amethyst/src/main/res/values-tr/strings.xml b/amethyst/src/main/res/values-tr/strings.xml index 00d20314c6..4efdc65c58 100644 --- a/amethyst/src/main/res/values-tr/strings.xml +++ b/amethyst/src/main/res/values-tr/strings.xml @@ -5600,15 +5600,11 @@ Tarayıcı - Ara veya adres gir Yenile - Konsol - Konsol (%1$d) - Temizle Tor üzerinden yükleniyor. Açık web\'i kullanmak için dokun. @@ -5674,7 +5670,6 @@ İptal et - Başlıksız nApplet Henüz hiç nApplet bulunamadı. diff --git a/amethyst/src/main/res/values-uk/strings.xml b/amethyst/src/main/res/values-uk/strings.xml index 670dcaf419..06ec9725a3 100644 --- a/amethyst/src/main/res/values-uk/strings.xml +++ b/amethyst/src/main/res/values-uk/strings.xml @@ -5291,15 +5291,11 @@ Браузер - Пошук або введіть адресу Оновити - Консоль - Консоль (%1$d) - Очистити Завантаження через Tor. Торкніться, щоб використати відкриту мережу. @@ -5365,7 +5361,6 @@ Відкликати - NApplet без назви nApplets ще не знайдено. diff --git a/amethyst/src/main/res/values-zh/strings.xml b/amethyst/src/main/res/values-zh/strings.xml index 0b33d1f557..82df1937c8 100644 --- a/amethyst/src/main/res/values-zh/strings.xml +++ b/amethyst/src/main/res/values-zh/strings.xml @@ -1048,15 +1048,11 @@ 浏览器 -搜索或输入地址 重新加载 -控制台 -控制台(%1$d) -清除 正通过 Tor 加载。点击使用 open web。 @@ -1122,7 +1118,6 @@ 撤销 -未命名nApplet 尚未找到 nApplets 。 diff --git a/commons/src/androidMain/res/values-cs/strings.xml b/commons/src/androidMain/res/values-cs/strings.xml new file mode 100644 index 0000000000..5f44e45f8a --- /dev/null +++ b/commons/src/androidMain/res/values-cs/strings.xml @@ -0,0 +1,8 @@ + + + Hledat nebo zadat adresu + Konzola + Konzola (%1$d) + Vymazat + Nepojmenovaný nApplet + diff --git a/commons/src/androidMain/res/values-de/strings.xml b/commons/src/androidMain/res/values-de/strings.xml new file mode 100644 index 0000000000..f0e0a4a109 --- /dev/null +++ b/commons/src/androidMain/res/values-de/strings.xml @@ -0,0 +1,8 @@ + + + Suchen oder Adresse eingeben + Konsole + Konsole (%1$d) + Löschen + Unbenanntes nApplet + diff --git a/commons/src/androidMain/res/values-eo/strings.xml b/commons/src/androidMain/res/values-eo/strings.xml new file mode 100644 index 0000000000..80b6f40eab --- /dev/null +++ b/commons/src/androidMain/res/values-eo/strings.xml @@ -0,0 +1,8 @@ + + + Serĉi aŭ enigi adreson + Konzolo + Konzolo (%1$d) + Viŝi + Sennoma nApplet + diff --git a/commons/src/androidMain/res/values-es/strings.xml b/commons/src/androidMain/res/values-es/strings.xml new file mode 100644 index 0000000000..7f147af20c --- /dev/null +++ b/commons/src/androidMain/res/values-es/strings.xml @@ -0,0 +1,8 @@ + + + Buscar o introducir dirección + Consola + Consola (%1$d) + Borrar + NApplet sin título + diff --git a/commons/src/androidMain/res/values-fa/strings.xml b/commons/src/androidMain/res/values-fa/strings.xml new file mode 100644 index 0000000000..8d0225caaa --- /dev/null +++ b/commons/src/androidMain/res/values-fa/strings.xml @@ -0,0 +1,8 @@ + + + جستجو یا وارد کردن آدرس + کنسول + کنسول (%1$d) + پاک کردن + nApplet بی‌عنوان + diff --git a/commons/src/androidMain/res/values-fr/strings.xml b/commons/src/androidMain/res/values-fr/strings.xml new file mode 100644 index 0000000000..5ffc725fb2 --- /dev/null +++ b/commons/src/androidMain/res/values-fr/strings.xml @@ -0,0 +1,8 @@ + + + Rechercher ou saisir une adresse + Console + Console (%1$d) + Effacer + nApplet sans titre + diff --git a/commons/src/androidMain/res/values-in/strings.xml b/commons/src/androidMain/res/values-in/strings.xml new file mode 100644 index 0000000000..07e44d86b4 --- /dev/null +++ b/commons/src/androidMain/res/values-in/strings.xml @@ -0,0 +1,8 @@ + + + Cari atau masukkan alamat + Konsol + Konsol (%1$d) + Hapus + nApplet Tanpa Judul + diff --git a/commons/src/androidMain/res/values-ja/strings.xml b/commons/src/androidMain/res/values-ja/strings.xml new file mode 100644 index 0000000000..05fd97f20e --- /dev/null +++ b/commons/src/androidMain/res/values-ja/strings.xml @@ -0,0 +1,8 @@ + + + 検索またはアドレスを入力 + コンソール + コンソール(%1$d) + クリア + 無題の nApplet + diff --git a/commons/src/androidMain/res/values-nl-rBE/strings.xml b/commons/src/androidMain/res/values-nl-rBE/strings.xml new file mode 100644 index 0000000000..dda484f403 --- /dev/null +++ b/commons/src/androidMain/res/values-nl-rBE/strings.xml @@ -0,0 +1,8 @@ + + + Zoeken of adres invoeren + Console + Console (%1$d) + Wissen + Naamloze nApplet + diff --git a/commons/src/androidMain/res/values-nl/strings.xml b/commons/src/androidMain/res/values-nl/strings.xml new file mode 100644 index 0000000000..dda484f403 --- /dev/null +++ b/commons/src/androidMain/res/values-nl/strings.xml @@ -0,0 +1,8 @@ + + + Zoeken of adres invoeren + Console + Console (%1$d) + Wissen + Naamloze nApplet + diff --git a/commons/src/androidMain/res/values-ru/strings.xml b/commons/src/androidMain/res/values-ru/strings.xml new file mode 100644 index 0000000000..325c7e0f8b --- /dev/null +++ b/commons/src/androidMain/res/values-ru/strings.xml @@ -0,0 +1,8 @@ + + + Поиск или введите адрес + Консоль + Консоль (%1$d) + Очистить + nApplet без названия + diff --git a/commons/src/androidMain/res/values-ta/strings.xml b/commons/src/androidMain/res/values-ta/strings.xml new file mode 100644 index 0000000000..a673854729 --- /dev/null +++ b/commons/src/androidMain/res/values-ta/strings.xml @@ -0,0 +1,8 @@ + + + தேடவும் அல்லது முகவரியை உள்ளிடவும் + கன்சோல் + கன்சோல் (%1$d) + அழிக்கவும் + தலைப்பற்ற nApplet + diff --git a/commons/src/androidMain/res/values-th/strings.xml b/commons/src/androidMain/res/values-th/strings.xml new file mode 100644 index 0000000000..d37a7c9fb6 --- /dev/null +++ b/commons/src/androidMain/res/values-th/strings.xml @@ -0,0 +1,8 @@ + + + ค้นหาหรือป้อนที่อยู่ + คอนโซล + คอนโซล (%1$d) + ล้าง + nApplet ไม่มีชื่อ + diff --git a/commons/src/androidMain/res/values-tr/strings.xml b/commons/src/androidMain/res/values-tr/strings.xml new file mode 100644 index 0000000000..334283f141 --- /dev/null +++ b/commons/src/androidMain/res/values-tr/strings.xml @@ -0,0 +1,8 @@ + + + Ara veya adres gir + Konsol + Konsol (%1$d) + Temizle + Başlıksız nApplet + diff --git a/commons/src/androidMain/res/values-uk/strings.xml b/commons/src/androidMain/res/values-uk/strings.xml new file mode 100644 index 0000000000..b1f6137196 --- /dev/null +++ b/commons/src/androidMain/res/values-uk/strings.xml @@ -0,0 +1,8 @@ + + + Пошук або введіть адресу + Консоль + Консоль (%1$d) + Очистити + NApplet без назви + diff --git a/commons/src/androidMain/res/values-zh/strings.xml b/commons/src/androidMain/res/values-zh/strings.xml new file mode 100644 index 0000000000..0305a7cb4e --- /dev/null +++ b/commons/src/androidMain/res/values-zh/strings.xml @@ -0,0 +1,8 @@ + + + 搜索或输入地址 + 控制台 + 控制台(%1$d) + 清除 + 未命名nApplet +