Merge remote-tracking branch 'origin/main' into claude/nsite-napplet-icons-okz5y6

This commit is contained in:
Claude
2026-06-26 19:11:40 +00:00
36 changed files with 216 additions and 109 deletions
@@ -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
@@ -183,6 +183,12 @@ object LocalPreferences {
private var currentAccount: String? = null
private val savedAccounts: MutableStateFlow<List<AccountInfo>?> = 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<String, AccountSettings?> = mutableMapOf()
suspend fun currentAccount(): String? {
@@ -212,41 +218,46 @@ object LocalPreferences {
}
private suspend fun savedAccounts(): List<AccountInfo> {
if (savedAccounts.value == null) {
withContext(Dispatchers.IO) {
with(encryptedPreferences()) {
val newSystemOfAccounts =
getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let {
JsonMapper.fromJson<List<AccountInfo>>(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<AccountInfo> =
withContext(Dispatchers.IO) {
with(encryptedPreferences()) {
val newSystemOfAccounts =
getString(PrefKeys.ALL_ACCOUNT_INFO, "[]")?.let {
JsonMapper.fromJson<List<AccountInfo>>(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
@@ -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<HexKey>) {
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 =
@@ -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)
}
}
@@ -4873,15 +4873,11 @@
<string name="browser">Prohlížeč</string>
<string name="browser_address_hint">Hledat nebo zadat adresu</string>
<string name="browser_clear">Vymazat</string>
<string name="browser_console_clear">Vymazat</string>
<string name="browser_console_title">Konzola (%1$d)</string>
<string name="browser_console_title_short">Konzola</string>
<string name="browser_favorites">Oblíbené</string>
@@ -5273,7 +5269,6 @@
<string name="napplet_permissions_revoke">Odebrat</string>
<string name="napplet_untitled">Nepojmenovaný nApplet</string>
<string name="napplets">nApplets</string>
@@ -4782,15 +4782,11 @@ anz der Bedingungen ist erforderlich</string>
<string name="browser">Browser</string>
<string name="browser_address_hint">Suchen oder Adresse eingeben</string>
<string name="browser_clear">Löschen</string>
<string name="browser_console_clear">Löschen</string>
<string name="browser_console_title">Konsole (%1$d)</string>
<string name="browser_console_title_short">Konsole</string>
<string name="browser_favorites">Favoriten</string>
@@ -5182,7 +5178,6 @@ anz der Bedingungen ist erforderlich</string>
<string name="napplet_permissions_revoke">Widerrufen</string>
<string name="napplet_untitled">Unbenanntes nApplet</string>
<string name="napplets">nApplets</string>
@@ -726,11 +726,7 @@
<string name="nsites">nSite-oj</string>
<string name="nsite_none_found">Ankoraŭ neniuj nSite-oj trovitaj.</string>
<string name="browser">Retumilo</string>
<string name="browser_address_hint">Serĉi aŭ enigi adreson</string>
<string name="browser_reload">Reŝargi</string>
<string name="browser_console_title_short">Konzolo</string>
<string name="browser_console_title">Konzolo (%1$d)</string>
<string name="browser_console_clear">Viŝi</string>
<string name="browser_tor_on">Ŝargante per Tor. Klaku por uzi la malferma reton.</string>
<string name="browser_tor_off">Ŝargante per la malferma reto. Klaku por uzi Tor.</string>
<string name="browser_unsupported">La en-aplikaĵa retumilo bezonas Android 11 aŭ pli novan.</string>
@@ -763,7 +759,6 @@
<string name="napplet_permissions_forget">Forgesi ĉi tiun nApplet-on</string>
<string name="napplet_permissions_blocked">Blokita</string>
<string name="napplet_permissions_revoke">Revoki</string>
<string name="napplet_untitled">Sennoma nApplet</string>
<string name="napplet_none_found">Ankoraŭ neniuj nApplet-oj trovitaj.</string>
<string name="napplet_fallback_title">nApplet %1$s…</string>
<string name="napplet_cap_shell">Ŝelo</string>
@@ -1085,7 +1085,6 @@
<string name="napplet_permissions_revoke">Revocar</string>
<string name="napplet_untitled">NApplet sin título</string>
<string name="napplet_none_found">No se han encontrado nApplets todavía.</string>
@@ -3333,15 +3332,11 @@
<string name="browser">Navegador</string>
<string name="browser_address_hint">Buscar o introducir dirección</string>
<string name="browser_reload">Recargar</string>
<string name="browser_console_title_short">Consola</string>
<string name="browser_console_title">Consola (%1$d)</string>
<string name="browser_console_clear">Borrar</string>
<string name="browser_tor_on">Cargando a través de Tor. Toca para usar la web abierta.</string>
@@ -4725,15 +4725,11 @@
<string name="browser">مرورگر</string>
<string name="browser_address_hint">جستجو یا وارد کردن آدرس</string>
<string name="browser_reload">بارگذاری مجدد</string>
<string name="browser_console_title_short">کنسول</string>
<string name="browser_console_title">کنسول (%1$d)</string>
<string name="browser_console_clear">پاک کردن</string>
<string name="browser_tor_on">بارگذاری از طریق Tor. برای استفاده از وب باز ضربه بزنید.</string>
@@ -4799,7 +4795,6 @@
<string name="napplet_permissions_revoke">لغو</string>
<string name="napplet_untitled">nApplet بی‌عنوان</string>
<string name="napplet_none_found">هنوز هیچ nApplet ای یافت نشد.</string>
@@ -2788,15 +2788,11 @@
<string name="browser">Navigateur</string>
<string name="browser_address_hint">Rechercher ou saisir une adresse</string>
<string name="browser_reload">Recharger</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Effacer</string>
<string name="browser_tor_on">Chargement via Tor. Appuyer pour utiliser le web ouvert.</string>
@@ -2862,7 +2858,6 @@
<string name="napplet_permissions_revoke">Révoquer</string>
<string name="napplet_untitled">nApplet sans titre</string>
<string name="napplet_none_found">Aucun nApplet trouvé pour l\'instant.</string>
@@ -5173,15 +5173,11 @@
<string name="browser">Browser</string>
<string name="browser_address_hint">Cari atau masukkan alamat</string>
<string name="browser_reload">Muat ulang</string>
<string name="browser_console_title_short">Konsol</string>
<string name="browser_console_title">Konsol (%1$d)</string>
<string name="browser_console_clear">Hapus</string>
<string name="browser_tor_on">Memuat melalui Tor. Ketuk untuk menggunakan web terbuka.</string>
@@ -5247,7 +5243,6 @@
<string name="napplet_permissions_revoke">Cabut</string>
<string name="napplet_untitled">nApplet Tanpa Judul</string>
<string name="napplet_none_found">Belum ada nApplet ditemukan.</string>
@@ -5280,15 +5280,11 @@
<string name="browser">ブラウザ</string>
<string name="browser_address_hint">検索またはアドレスを入力</string>
<string name="browser_reload">再読み込み</string>
<string name="browser_console_title_short">コンソール</string>
<string name="browser_console_title">コンソール(%1$d</string>
<string name="browser_console_clear">クリア</string>
<string name="browser_tor_on">Tor経由で読み込み中。タップしてオープンウェブを使用します。</string>
@@ -5354,7 +5350,6 @@
<string name="napplet_permissions_revoke">取り消す</string>
<string name="napplet_untitled">無題の nApplet</string>
<string name="napplet_none_found">nApplet はまだ見つかりません。</string>
@@ -5321,15 +5321,11 @@
<string name="browser">Browser</string>
<string name="browser_address_hint">Zoeken of adres invoeren</string>
<string name="browser_reload">Herladen</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Wissen</string>
<string name="browser_tor_on">Laden via Tor. Tik om het open web te gebruiken.</string>
@@ -5395,7 +5391,6 @@
<string name="napplet_permissions_revoke">Intrekken</string>
<string name="napplet_untitled">Naamloze nApplet</string>
<string name="napplet_none_found">Nog geen nApplets gevonden.</string>
@@ -4603,15 +4603,11 @@
<string name="browser">Browser</string>
<string name="browser_address_hint">Zoeken of adres invoeren</string>
<string name="browser_reload">Herladen</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Wissen</string>
<string name="browser_tor_on">Laden via Tor. Tik om het open web te gebruiken.</string>
@@ -4677,7 +4673,6 @@
<string name="napplet_permissions_revoke">Intrekken</string>
<string name="napplet_untitled">Naamloze nApplet</string>
<string name="napplet_none_found">Nog geen nApplets gevonden.</string>
@@ -4871,15 +4871,11 @@
<string name="browser">Браузер</string>
<string name="browser_address_hint">Поиск или введите адрес</string>
<string name="browser_reload">Обновить</string>
<string name="browser_console_title_short">Консоль</string>
<string name="browser_console_title">Консоль (%1$d)</string>
<string name="browser_console_clear">Очистить</string>
<string name="browser_tor_on">Загрузка через Tor. Нажмите, чтобы использовать открытую сеть.</string>
@@ -4945,7 +4941,6 @@
<string name="napplet_permissions_revoke">Отозвать</string>
<string name="napplet_untitled">nApplet без названия</string>
<string name="napplet_none_found">nApplets пока не найдены.</string>
@@ -677,11 +677,7 @@
<string name="nsites">nSites</string>
<string name="nsite_none_found">இன்னும் nSites எதுவும் கிடைக்கவில்லை.</string>
<string name="browser">உலாவி</string>
<string name="browser_address_hint">தேடவும் அல்லது முகவரியை உள்ளிடவும்</string>
<string name="browser_reload">மீண்டும் ஏற்று</string>
<string name="browser_console_title_short">கன்சோல்</string>
<string name="browser_console_title">கன்சோல் (%1$d)</string>
<string name="browser_console_clear">அழிக்கவும்</string>
<string name="browser_tor_on">Tor மூலம் ஏற்றுகிறது. திறந்த வலையை பயன்படுத்த தட்டவும்.</string>
<string name="browser_tor_off">திறந்த வலை மூலம் ஏற்றுகிறது. Tor ஐ பயன்படுத்த தட்டவும்.</string>
<string name="browser_unsupported">உள்-பயன்பாட்டு உலாவிக்கு Android 11 அல்லது புதியது தேவை.</string>
@@ -714,7 +710,6 @@
<string name="napplet_permissions_forget">இந்த nApplet ஐ மறக்கவும்</string>
<string name="napplet_permissions_blocked">தடுக்கப்பட்டது</string>
<string name="napplet_permissions_revoke">திரும்பப் பெறவும்</string>
<string name="napplet_untitled">தலைப்பற்ற nApplet</string>
<string name="napplet_none_found">இன்னும் nApplets எதுவும் கிடைக்கவில்லை.</string>
<string name="napplet_fallback_title">nApplet %1$s…</string>
<string name="napplet_cap_shell">Shell</string>
@@ -4845,15 +4845,11 @@
<string name="browser">เบราว์เซอร์</string>
<string name="browser_address_hint">ค้นหาหรือป้อนที่อยู่</string>
<string name="browser_reload">โหลดใหม่</string>
<string name="browser_console_title_short">คอนโซล</string>
<string name="browser_console_title">คอนโซล (%1$d)</string>
<string name="browser_console_clear">ล้าง</string>
<string name="browser_tor_on">กำลังโหลดผ่าน Tor แตะเพื่อใช้เว็บแบบเปิด</string>
@@ -4919,7 +4915,6 @@
<string name="napplet_permissions_revoke">เพิกถอน</string>
<string name="napplet_untitled">nApplet ไม่มีชื่อ</string>
<string name="napplet_none_found">ยังไม่พบ nApplets</string>
@@ -5600,15 +5600,11 @@
<string name="browser">Tarayıcı</string>
<string name="browser_address_hint">Ara veya adres gir</string>
<string name="browser_reload">Yenile</string>
<string name="browser_console_title_short">Konsol</string>
<string name="browser_console_title">Konsol (%1$d)</string>
<string name="browser_console_clear">Temizle</string>
<string name="browser_tor_on">Tor üzerinden yükleniyor. Açık web\'i kullanmak için dokun.</string>
@@ -5674,7 +5670,6 @@
<string name="napplet_permissions_revoke">İptal et</string>
<string name="napplet_untitled">Başlıksız nApplet</string>
<string name="napplet_none_found">Henüz hiç nApplet bulunamadı.</string>
@@ -5291,15 +5291,11 @@
<string name="browser">Браузер</string>
<string name="browser_address_hint">Пошук або введіть адресу</string>
<string name="browser_reload">Оновити</string>
<string name="browser_console_title_short">Консоль</string>
<string name="browser_console_title">Консоль (%1$d)</string>
<string name="browser_console_clear">Очистити</string>
<string name="browser_tor_on">Завантаження через Tor. Торкніться, щоб використати відкриту мережу.</string>
@@ -5365,7 +5361,6 @@
<string name="napplet_permissions_revoke">Відкликати</string>
<string name="napplet_untitled">NApplet без назви</string>
<string name="napplet_none_found">nApplets ще не знайдено.</string>
@@ -1048,15 +1048,11 @@
<string name="browser">浏览器</string>
<string name="browser_address_hint">搜索或输入地址</string>
<string name="browser_reload">重新加载</string>
<string name="browser_console_title_short">控制台</string>
<string name="browser_console_title">控制台(%1$d)</string>
<string name="browser_console_clear">清除</string>
<string name="browser_tor_on">正通过 Tor 加载。点击使用 open web。</string>
@@ -1122,7 +1118,6 @@
<string name="napplet_permissions_revoke">撤销</string>
<string name="napplet_untitled">未命名nApplet</string>
<string name="napplet_none_found">尚未找到 nApplets 。</string>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Hledat nebo zadat adresu</string>
<string name="browser_console_title_short">Konzola</string>
<string name="browser_console_title">Konzola (%1$d)</string>
<string name="browser_console_clear">Vymazat</string>
<string name="napplet_untitled">Nepojmenovaný nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Suchen oder Adresse eingeben</string>
<string name="browser_console_title_short">Konsole</string>
<string name="browser_console_title">Konsole (%1$d)</string>
<string name="browser_console_clear">Löschen</string>
<string name="napplet_untitled">Unbenanntes nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Serĉi aŭ enigi adreson</string>
<string name="browser_console_title_short">Konzolo</string>
<string name="browser_console_title">Konzolo (%1$d)</string>
<string name="browser_console_clear">Viŝi</string>
<string name="napplet_untitled">Sennoma nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Buscar o introducir dirección</string>
<string name="browser_console_title_short">Consola</string>
<string name="browser_console_title">Consola (%1$d)</string>
<string name="browser_console_clear">Borrar</string>
<string name="napplet_untitled">NApplet sin título</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">جستجو یا وارد کردن آدرس</string>
<string name="browser_console_title_short">کنسول</string>
<string name="browser_console_title">کنسول (%1$d)</string>
<string name="browser_console_clear">پاک کردن</string>
<string name="napplet_untitled">nApplet بی‌عنوان</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Rechercher ou saisir une adresse</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Effacer</string>
<string name="napplet_untitled">nApplet sans titre</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Cari atau masukkan alamat</string>
<string name="browser_console_title_short">Konsol</string>
<string name="browser_console_title">Konsol (%1$d)</string>
<string name="browser_console_clear">Hapus</string>
<string name="napplet_untitled">nApplet Tanpa Judul</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">検索またはアドレスを入力</string>
<string name="browser_console_title_short">コンソール</string>
<string name="browser_console_title">コンソール(%1$d</string>
<string name="browser_console_clear">クリア</string>
<string name="napplet_untitled">無題の nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Zoeken of adres invoeren</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Wissen</string>
<string name="napplet_untitled">Naamloze nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Zoeken of adres invoeren</string>
<string name="browser_console_title_short">Console</string>
<string name="browser_console_title">Console (%1$d)</string>
<string name="browser_console_clear">Wissen</string>
<string name="napplet_untitled">Naamloze nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Поиск или введите адрес</string>
<string name="browser_console_title_short">Консоль</string>
<string name="browser_console_title">Консоль (%1$d)</string>
<string name="browser_console_clear">Очистить</string>
<string name="napplet_untitled">nApplet без названия</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">தேடவும் அல்லது முகவரியை உள்ளிடவும்</string>
<string name="browser_console_title_short">கன்சோல்</string>
<string name="browser_console_title">கன்சோல் (%1$d)</string>
<string name="browser_console_clear">அழிக்கவும்</string>
<string name="napplet_untitled">தலைப்பற்ற nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">ค้นหาหรือป้อนที่อยู่</string>
<string name="browser_console_title_short">คอนโซล</string>
<string name="browser_console_title">คอนโซล (%1$d)</string>
<string name="browser_console_clear">ล้าง</string>
<string name="napplet_untitled">nApplet ไม่มีชื่อ</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Ara veya adres gir</string>
<string name="browser_console_title_short">Konsol</string>
<string name="browser_console_title">Konsol (%1$d)</string>
<string name="browser_console_clear">Temizle</string>
<string name="napplet_untitled">Başlıksız nApplet</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">Пошук або введіть адресу</string>
<string name="browser_console_title_short">Консоль</string>
<string name="browser_console_title">Консоль (%1$d)</string>
<string name="browser_console_clear">Очистити</string>
<string name="napplet_untitled">NApplet без назви</string>
</resources>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="browser_address_hint">搜索或输入地址</string>
<string name="browser_console_title_short">控制台</string>
<string name="browser_console_title">控制台(%1$d)</string>
<string name="browser_console_clear">清除</string>
<string name="napplet_untitled">未命名nApplet</string>
</resources>