Merge branch 'main' into gossip-routing-2

This commit is contained in:
callebtc
2025-10-28 09:00:01 +01:00
111 changed files with 12637 additions and 799 deletions
+5 -2
View File
@@ -13,8 +13,8 @@ android {
applicationId = "com.bitchat.droid"
minSdk = libs.versions.minSdk.get().toInt()
targetSdk = libs.versions.targetSdk.get().toInt()
versionCode = 22
versionName = "1.3.1"
versionCode = 26
versionName = "1.5.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
@@ -104,6 +104,9 @@ dependencies {
// Security preferences
implementation(libs.androidx.security.crypto)
// EXIF orientation handling for images
implementation("androidx.exifinterface:exifinterface:1.3.7")
// Testing
testImplementation(libs.bundles.testing)
androidTestImplementation(platform(libs.androidx.compose.bom))
-2
View File
@@ -64,14 +64,12 @@
android:name=".ui.GeohashPickerActivity"
android:exported="false"
android:theme="@style/Theme.BitchatAndroid"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize" />
<activity
android:name=".MainActivity"
android:exported="true"
android:label="@string/app_name"
android:theme="@style/Theme.BitchatAndroid"
android:screenOrientation="portrait"
android:windowSoftInputMode="adjustResize"
android:launchMode="singleTop">
<intent-filter>
+266 -264
View File
@@ -1,275 +1,277 @@
Relay URL,Latitude,Longitude
nostr.tac.lol,47.4748,-122.273
relay.javi.space,43.4633,11.8796
nostr.einundzwanzig.space,50.1109,8.68213
nostr.kalf.org,52.3676,4.90414
wot.dtonon.com,43.6532,-79.3832
nostr-01.yakihonne.com,1.32123,103.695
wot.basspistol.org,49.4521,11.0767
relay.puresignal.news,43.6532,-79.3832
nostrelites.org,41.8781,-87.6298
nostr-relay.nextblockvending.com,47.674,-122.122
relay03.lnfi.network,39.0997,-94.5786
nproxy.kristapsk.lv,60.1699,24.9384
relay.toastr.net,40.8054,-74.0241
relay.davidebtc.me,51.5072,-0.127586
wot.nostr.net,43.6532,-79.3832
relay.mattybs.lol,43.6532,-79.3832
relay.zone667.com,60.1699,24.9384
nostr.kungfu-g.rip,33.7946,-84.4488
relay.mccormick.cx,52.3563,4.95714
relay.dwadziesciajeden.pl,52.2297,21.0122
nostr.data.haus,50.4754,12.3683
vitor.nostr1.com,40.7128,-74.006
purpura.cloud,43.6532,-79.3832
relay2.angor.io,48.1046,11.6002
nos.lol,50.4754,12.3683
nostr.rohoss.com,50.1109,8.68213
strfry.bonsai.com,37.8715,-122.273
relay.fountain.fm,39.0997,-94.5786
relay.npubhaus.com,43.6532,-79.3832
relay.nostr.wirednet.jp,34.706,135.493
soloco.nl,43.6532,-79.3832
shu01.shugur.net,21.4902,39.2246
nostr.davidebtc.me,51.5072,-0.127586
pyramid.fiatjaf.com,50.1109,8.68213
relay.ditto.pub,43.6532,-79.3832
relay.nostr.vet,52.6467,4.7395
relay.wavlake.com,41.2619,-95.8608
ribo.eu.nostria.app,52.3676,4.90414
relay.ngengine.org,43.6532,-79.3832
relay.bitcoinveneto.org,64.1466,-21.9426
no.str.cr,9.92857,-84.0528
relay.primal.net,43.6532,-79.3832
ynostr.yael.at,60.1699,24.9384
nostr.camalolo.com,24.1469,120.684
purplerelay.com,50.1109,8.68213
nostr-rs-relay-ishosta.phamthanh.me,43.6532,-79.3832
relay.internationalright-wing.org,-22.5022,-48.7114
wheat.happytavern.co,43.6532,-79.3832
nostr.lostr.space,43.6532,-79.3832
relay.tagayasu.xyz,43.6715,-79.38
relay.varke.eu,52.6921,6.19372
free.relayted.de,50.1109,8.68213
nostr.thebiglake.org,32.71,-96.6745
nostr.lojong.info,43.6532,-79.3832
nostr.now,36.55,139.733
relay.jmoose.rocks,60.1699,24.9384
relay.holzeis.me,43.6532,-79.3832
nostr.roundrockbitcoiners.com,40.8054,-74.0241
nostr-rs-relay.dev.fedibtc.com,39.0438,-77.4874
relay2.ngengine.org,43.6532,-79.3832
nostr.snowbla.de,60.1699,24.9384
4u2ni0zjbjvni.clorecloud.net,43.6532,-79.3832
shu04.shugur.net,25.2604,55.2989
relay.fr13nd5.com,52.5233,13.3426
nostr.vulpem.com,49.4543,11.0746
temp.iris.to,43.6532,-79.3832
x.kojira.io,43.6532,-79.3832
adre.su,59.9311,30.3609
nostr-dev.wellorder.net,45.5201,-122.99
nostr.mom,50.4754,12.3683
relay.nostr.place,32.7767,-96.797
wot.nostr.place,30.2672,-97.7431
nostr.carroarmato0.be,50.9928,3.26317
nostrelay.circum.space,51.2217,6.77616
relay.chorus.community,50.1109,8.68213
relay.nostr.net,50.4754,12.3683
relay.nostr-check.me,43.6532,-79.3832
relay.nostrhub.fr,48.1046,11.6002
relay.nostraddress.com,43.6532,-79.3832
nostr.rblb.it,43.4633,11.8796
nostr.red5d.dev,43.6532,-79.3832
santo.iguanatech.net,40.8302,-74.1299
relay02.lnfi.network,39.0997,-94.5786
relay.21e6.cz,50.1682,14.0546
a.nos.lol,50.4754,12.3683
shu02.shugur.net,21.4902,39.2246
schnorr.me,43.6532,-79.3832
nostr.n7ekb.net,47.4941,-122.294
wot.shaving.kiwi,43.6532,-79.3832
dev-nostr.bityacht.io,25.0797,121.234
relay.credenso.cafe,43.1149,-80.7228
relay-testnet.k8s.layer3.news,37.3387,-121.885
relay.mess.ch,47.3591,8.55292
inbox.azzamo.net,52.2633,21.0283
prl.plus,55.7623,37.6381
yabu.me,35.6092,139.73
relayrs.notoshi.win,43.6532,-79.3832
premium.primal.net,43.6532,-79.3832
nostr.coincrowd.fund,39.0438,-77.4874
nostr.2b9t.xyz,34.0549,-118.243
nostr.thaliyal.com,40.8218,-74.45
relay.exit.pub,50.4754,12.3683
nostr.jfischer.org,49.0291,8.35696
relay.origin.land,35.6673,139.751
nostr.myshosholoza.co.za,52.3676,4.90414
relay.nostriot.com,41.5695,-83.9786
relay.btcforplebs.com,43.6532,-79.3832
relay.chakany.systems,43.6532,-79.3832
nostr.openhoofd.nl,51.9229,4.40833
nostrcheck.me,43.6532,-79.3832
nostr.plantroon.com,50.1013,8.62643
satsage.xyz,37.3986,-121.964
nostr.faultables.net,43.6532,-79.3832
nostr.calitabby.net,39.9268,-75.0246
relay.freeplace.nl,52.3676,4.90414
relay.nostrhub.tech,49.4543,11.0746
roles-az-achieving-somebody.trycloudflare.com,43.6532,-79.3832
relay.arx-ccn.com,50.4754,12.3683
cyberspace.nostr1.com,40.7128,-74.006
nostr.smut.cloud,43.6532,-79.3832
nostr-02.czas.top,53.471,9.88208
relay.tapestry.ninja,40.8054,-74.0241
nostr-relay.amethyst.name,39.0438,-77.4874
bcast.seutoba.com.br,43.6532,-79.3832
premium.primal.net,40.7357,-74.1724
strfry.openhoofd.nl,51.9229,4.40833
relay.mostro.network,40.8302,-74.1299
wot.brightbolt.net,47.6735,-116.781
nostr.spaceshell.xyz,43.6532,-79.3832
nostr.rikmeijer.nl,50.4754,12.3683
relay.artx.market,43.652,-79.3633
strfry.felixzieger.de,50.1013,8.62643
relay.seq1.net,43.6532,-79.3832
relay.cosmicbolt.net,37.3986,-121.964
relay.electriclifestyle.com,26.2897,-80.1293
r.bitcoinhold.net,43.6532,-79.3832
nostr-relay.amethyst.name,39.0067,-77.4291
relay.stream.labs.h3.se,59.4016,17.9455
relay.unknown.cloud,43.6532,-79.3832
nostr-02.yakihonne.com,1.32123,103.695
relay.coinos.io,43.6532,-79.3832
relay5.bitransfer.org,43.6532,-79.3832
relay-dev.satlantis.io,40.8302,-74.1299
nostream.breadslice.com,43.6532,-79.3832
relay.fundstr.me,42.3601,-71.0589
nostr.oxtr.dev,50.4754,12.3683
nos.xmark.cc,50.6924,3.20113
ribo.us.nostria.app,41.5868,-93.625
relayone.geektank.ai,18.2148,-63.0574
nostr.mikoshi.de,50.1109,8.68213
relay.magiccity.live,25.8128,-80.2377
nostr-verified.wellorder.net,45.5201,-122.99
nostr.makibisskey.work,43.6532,-79.3832
wot.nostr.party,36.1627,-86.7816
relay.copylaradio.com,51.223,6.78245
nostr.sathoarder.com,48.5734,7.75211
relay.jeffg.fyi,43.6532,-79.3832
relay.wellorder.net,45.5201,-122.99
nostr.ovia.to,43.6532,-79.3832
black.nostrcity.club,41.8781,-87.6298
relay.nostrcheck.me,43.6532,-79.3832
nostr-relay.cbrx.io,43.6532,-79.3832
nostr-03.dorafactory.org,1.35208,103.82
nostr-relay.zimage.com,34.282,-118.439
relay.sigit.io,50.4754,12.3683
relay.laantungir.net,-19.4692,-42.5315
relay-admin.thaliyal.com,40.8218,-74.45
relay.mwaters.net,50.9871,2.12554
relay.lumina.rocks,49.0291,8.35695
nostr.satstralia.com,64.1476,-21.9392
nostr.sagaciousd.com,49.2827,-123.121
relay.bullishbounty.com,43.6532,-79.3832
wot.dergigi.com,64.1476,-21.9392
relay.vrtmrz.net,43.6532,-79.3832
nostr.0x7e.xyz,47.4988,8.72369
articles.layer3.news,37.3387,-121.885
relay.digitalezukunft.cyou,45.5019,-73.5674
nostr.notribe.net,40.8302,-74.1299
nostr.21crypto.ch,47.4988,8.72369
relay.lifpay.me,1.35208,103.82
relay.g1sms.fr,43.9432,2.07537
relay.snort.social,43.6532,-79.3832
shu02.shugur.net,21.4902,39.2246
nostr.hifish.org,47.4043,8.57398
orangepiller.org,60.1699,24.9384
nostr.myshosholoza.co.za,52.3676,4.90414
relay.nostrcheck.me,43.6532,-79.3832
relay.nostrhub.tech,49.0291,8.35696
nostr.mehdibekhtaoui.com,49.4939,-1.54813
nostrcheck.me,40.7357,-74.1724
relay.arx-ccn.com,50.4754,12.3683
relay2.ngengine.org,43.6532,-79.3832
nostr.21crypto.ch,47.4988,8.72369
nostr.girino.org,43.6532,-79.3832
relay.nostriches.club,43.6532,-79.3832
relay.angor.io,48.1046,11.6002
nostr.data.haus,50.4754,12.3683
nostr.zoracle.org,45.6018,-121.185
relay2.angor.io,48.1046,11.6002
librerelay.aaroniumii.com,43.6532,-79.3832
nostr.tadryanom.me,40.7357,-74.1724
nostr-relay.cbrx.io,43.6532,-79.3832
nostr-rs-relay.dev.fedibtc.com,39.0438,-77.4874
relay.aloftus.io,34.0881,-118.379
relay.barine.co,43.6532,-79.3832
nostr.red5d.dev,43.6532,-79.3832
nos.lol,50.4754,12.3683
ithurtswhenip.ee,51.223,6.78245
strfry.bonsai.com,37.8715,-122.273
relay01.lnfi.network,39.0997,-94.5786
nostrcheck.tnsor.network,43.6532,-79.3832
x.kojira.io,43.6532,-79.3832
nostr.snowbla.de,60.1699,24.9384
purplerelay.com,50.1109,8.68213
wot.sovbit.host,64.1466,-21.9426
shu04.shugur.net,25.2604,55.2989
nr.yay.so,46.2126,6.1154
nostr.smartflowsocial.com,43.6532,-79.3832
shu05.shugur.net,48.8566,2.35222
wot.dtonon.com,43.6532,-79.3832
pyramid.fiatjaf.com,51.5072,-0.127586
nostr.88mph.life,40.7357,-74.1724
dev-nostr.bityacht.io,25.0797,121.234
cyberspace.nostr1.com,40.7128,-74.006
relay.ngengine.org,40.7357,-74.1724
nostr.calitabby.net,39.9268,-75.0246
relay.toastr.net,40.8054,-74.0241
relay.cosmicbolt.net,37.3986,-121.964
nostr.davidebtc.me,50.1109,8.68213
espelho.girino.org,43.6532,-79.3832
srtrelay.c-stellar.net,40.7357,-74.1724
relay.nostriot.com,41.5695,-83.9786
relay.bitcoinveneto.org,64.1466,-21.9426
bitcoiner.social,39.1585,-94.5728
purpura.cloud,40.7357,-74.1724
nostr.blankfors.se,60.1699,24.9384
relay.nostromo.social,49.4543,11.0746
ribo.af.nostria.app,-26.2041,28.0473
relay.olas.app,50.4754,12.3683
nostr.carroarmato0.be,50.9928,3.26317
nostr.oxtr.dev,50.4754,12.3683
relay.upleb.uk,52.2297,21.0122
nostr.stakey.net,52.3676,4.90414
nostr2.girino.org,40.7357,-74.1724
nostr.rikmeijer.nl,50.4754,12.3683
relay5.bitransfer.org,40.7357,-74.1724
relay.mattybs.lol,40.7357,-74.1724
nostr.makibisskey.work,40.7357,-74.1724
wot.basspistol.org,49.4521,11.0767
relay.nostr.net,50.4754,12.3683
a.nos.lol,50.4754,12.3683
wot.dergigi.com,64.1476,-21.9392
fanfares.nostr1.com,40.7057,-74.0136
nostr.faultables.net,43.6532,-79.3832
relay.dwadziesciajeden.pl,52.2297,21.0122
adre.su,59.9311,30.3609
wot.nostr.party,36.1627,-86.7816
relay03.lnfi.network,39.0997,-94.5786
relay.orangepill.ovh,49.1689,-0.358841
gnostr.com,42.6978,23.3246
relay.wellorder.net,45.5201,-122.99
relay.21e6.cz,50.1682,14.0546
relay.tagayasu.xyz,43.6715,-79.38
relay.chatbett.de,28.0199,-82.5248
wot.soundhsa.com,33.1384,-95.6011
prl.plus,38.9072,-77.0369
nostr.einundzwanzig.space,50.1109,8.68213
nostream.breadslice.com,1.35208,103.82
relay.chorus.community,50.1109,8.68213
nostr.mom,50.4754,12.3683
relay.lightning.pub,41.8959,-88.2169
relay.hook.cafe,40.7357,-74.1724
relay-testnet.k8s.layer3.news,37.3387,-121.885
relay.fundstr.me,42.3601,-71.0589
relay.stream.labs.h3.se,59.4016,17.9455
relay.holzeis.me,43.6532,-79.3832
articles.layer3.news,37.3387,-121.885
nproxy.kristapsk.lv,60.1699,24.9384
nostr.thebiglake.org,32.71,-96.6745
relay.coinos.io,40.7357,-74.1724
nostr.camalolo.com,24.1469,120.684
theoutpost.life,64.1476,-21.9392
relay.nostraddress.com,40.7357,-74.1724
nostr.casa21.space,40.7357,-74.1724
relay.agorist.space,52.3734,4.89406
relay.nostr.wirednet.jp,34.706,135.493
nostr.jerrynya.fun,31.2304,121.474
relay.13room.space,43.6532,-79.3832
offchain.pub,47.6743,-117.112
relay.hasenpfeffr.com,39.0438,-77.4874
nostr-verified.wellorder.net,45.5201,-122.99
nostrelay.memory-art.xyz,43.6532,-79.3832
freeben666.fr,43.1204,6.12857
nostr.bilthon.dev,25.8128,-80.2377
nostr.spicyz.io,40.7357,-74.1724
bcast.girino.org,40.7357,-74.1724
nostr.noones.com,50.1109,8.68213
relay.electriclifestyle.com,26.2897,-80.1293
relay.guggero.org,47.3769,8.54169
relay.siamdev.cc,13.8434,100.363
relay.varke.eu,52.6921,6.19372
nostr.now,36.55,139.733
relay.origin.land,35.6673,139.751
yabu.me,35.6092,139.73
nostr-02.yakihonne.com,1.32123,103.695
nostr.tac.lol,47.4748,-122.273
r.bitcoinhold.net,40.7357,-74.1724
nostr.rtvslawenia.com,49.4543,11.0746
relay.sigit.io,50.4754,12.3683
nostr-rs-relay-ishosta.phamthanh.me,40.7357,-74.1724
relay.bitcoinartclock.com,50.4754,12.3683
relay.snort.social,40.7357,-74.1724
relay.mwaters.net,50.9871,2.12554
nostr-03.dorafactory.org,1.35208,103.82
relay.damus.io,40.7357,-74.1724
black.nostrcity.club,41.8781,-87.6298
noxir.kpherox.dev,34.8587,135.509
relay.javi.space,43.4633,11.8796
fenrir-s.notoshi.win,43.6532,-79.3832
relay02.lnfi.network,39.0997,-94.5786
mhp258zrpiiwn.clorecloud.net,40.7357,-74.1724
relay.libernet.app,43.6532,-79.3832
nostr.coincards.com,53.5501,-113.469
ynostr.yael.at,60.1699,24.9384
slick.mjex.me,39.048,-77.4817
nostr.agentcampfire.com,50.8933,6.05805
nostr-pub.wellorder.net,45.5201,-122.99
relay.artiostr.ch,43.6532,-79.3832
relay.davidebtc.me,50.1109,8.68213
shu01.shugur.net,21.4902,39.2246
relay.nostr.band,60.1699,24.9384
relay.evanverma.com,40.8302,-74.1299
nostr.simplex.icu,50.8198,-1.08798
wot.nostr.net,43.6532,-79.3832
relay.nostr.vet,52.6467,4.7395
r.lostr.net,52.3676,4.90414
relay.getsafebox.app,43.6532,-79.3832
relay.moinsen.com,50.4754,12.3683
nostr.blankfors.se,60.1699,24.9384
nostr-relay-1.trustlessenterprise.com,43.6532,-79.3832
orangesync.tech,50.1109,8.68213
relay.ru.ac.th,13.7584,100.622
orangepiller.org,60.1699,24.9384
relay.nostr.band,60.1699,24.9384
wot.soundhsa.com,34.0479,-118.256
khatru.nostrver.se,51.8933,4.42083
nostr.hifish.org,47.4043,8.57398
freelay.sovbit.host,64.1476,-21.9392
nostr.bilthon.dev,25.8128,-80.2377
nostr.night7.space,50.4754,12.3683
relay.illuminodes.com,47.6061,-122.333
relayone.soundhsa.com,34.0479,-118.256
nostr.azzamo.net,52.2633,21.0283
fenrir-s.notoshi.win,43.6532,-79.3832
nostr.spicyz.io,43.6532,-79.3832
nostrelay.memory-art.xyz,43.6532,-79.3832
nostr.coincards.com,53.5501,-113.469
alien.macneilmediagroup.com,43.6532,-79.3832
nostrings-relay-dev.fly.dev,41.8781,-87.6298
relay.satlantis.io,32.8769,-80.0114
srtrelay.c-stellar.net,43.6532,-79.3832
relay.agora.social,50.7383,15.0648
relay.bitcoindistrict.org,43.6532,-79.3832
relay.0xchat.com,1.35208,103.82
wot.utxo.one,43.6532,-79.3832
relay.bitcoinartclock.com,50.4754,12.3683
nostr.zenon.network,43.5009,-70.4428
wot.codingarena.top,50.4754,12.3683
nostr-02.dorafactory.org,1.35208,103.82
relay.nostromo.social,49.4543,11.0746
theoutpost.life,64.1476,-21.9392
strfry.shock.network,41.8959,-88.2169
strfry.openhoofd.nl,51.9229,4.40833
itanostr.space,52.2931,4.79099
relay.barine.co,43.6532,-79.3832
nostr.middling.mydns.jp,35.8099,140.12
relay.olas.app,50.4754,12.3683
nostr.girino.org,43.6532,-79.3832
nostr-relay.online,43.6532,-79.3832
relay.evanverma.com,40.8302,-74.1299
relay.angor.io,48.1046,11.6002
relay.nostrdice.com,-33.8688,151.209
ribo.us.nostria.app,41.5868,-93.625
relay01.lnfi.network,39.0997,-94.5786
nostr.namek.link,43.6532,-79.3832
relay.aloftus.io,34.0881,-118.379
ithurtswhenip.ee,51.223,6.78245
ribo.af.nostria.app,-26.2041,28.0473
shu05.shugur.net,48.8566,2.35222
noxir.kpherox.dev,34.8587,135.509
relay.degmods.com,50.4754,12.3683
relay.goodmorningbitcoin.com,43.6532,-79.3832
nostr.4rs.nl,49.0291,8.35696
nostr-relay.psfoundation.info,39.0438,-77.4874
relay.hasenpfeffr.com,39.0438,-77.4874
fanfares.nostr1.com,40.7128,-74.006
relay.nosto.re,51.8933,4.42083
nostr.liberty.fans,36.9104,-89.5875
nostr-2.21crypto.ch,47.4988,8.72369
relay-rpi.edufeed.org,49.4543,11.0746
offchain.pub,36.1809,-115.241
nostr.88mph.life,43.6532,-79.3832
nostr.luisschwab.net,43.6532,-79.3832
nostr.casa21.space,43.6532,-79.3832
strfry.elswa-dev.online,48.8566,2.35222
alienos.libretechsystems.xyz,55.4724,9.87335
nostr.overmind.lol,40.7357,-74.1724
nos.xmark.cc,50.6924,3.20113
relay.degmods.com,50.4754,12.3683
relay.seq1.net,40.7128,-74.006
relay.uid.ovh,43.6532,-79.3832
santo.iguanatech.net,40.8302,-74.1299
nostr.spaceshell.xyz,43.6532,-79.3832
nostr.hekster.org,37.3986,-121.964
wheat.happytavern.co,43.6532,-79.3832
nostr-02.czas.top,53.471,9.88208
satsage.xyz,37.3986,-121.964
no.str.cr,9.92857,-84.0528
relay.puresignal.news,40.7357,-74.1724
nostr-relay.nextblockvending.com,47.2343,-119.853
keys.nostr1.com,40.7057,-74.0136
relayone.soundhsa.com,33.1384,-95.6011
nostr-dev.wellorder.net,45.5201,-122.99
alien.macneilmediagroup.com,40.7357,-74.1724
nostr.kalf.org,52.3676,4.90414
nostrelites.org,41.8781,-87.6298
temp.iris.to,43.6532,-79.3832
relay.utxo.farm,35.6916,139.768
zap.watch,45.5029,-73.5723
nostr-pub.wellorder.net,45.5201,-122.99
wot.sovbit.host,64.1466,-21.9426
relay.endfiat.money,43.6532,-79.3832
nostr2.girino.org,43.6532,-79.3832
nostr.jerrynya.fun,31.2304,121.474
nostr.spacecitynode.com,29.7057,-95.2706
relay.siamdev.cc,13.9178,100.424
relay.notoshi.win,13.7829,100.546
relay.nostx.io,43.6532,-79.3832
relay.cypherflow.ai,48.8566,2.35222
freelay.sovbit.host,64.1476,-21.9392
relay.nosto.re,51.8933,4.42083
inbox.azzamo.net,52.2633,21.0283
nostr.ovia.to,43.6532,-79.3832
nostr.lostr.space,40.7357,-74.1724
nostr-relay-1.trustlessenterprise.com,43.6532,-79.3832
relay.nostar.org,40.7357,-74.1724
relay.mccormick.cx,52.3563,4.95714
nostr.0x7e.xyz,47.4988,8.72369
relay.0xchat.com,1.35208,103.82
relay.thebluepulse.com,40.7357,-74.1724
relay.letsfo.com,51.098,17.0321
librerelay.aaroniumii.com,43.6532,-79.3832
gnostr.com,40.9017,29.1616
nostr.pleb.one,38.6327,-90.1961
nostr.mehdibekhtaoui.com,49.4939,-1.54813
nostr.tadryanom.me,43.6532,-79.3832
relay.orangepill.ovh,49.1689,-0.358841
nostr.stakey.net,52.3676,4.90414
nostr.rtvslawenia.com,49.4543,11.0746
relay.damus.io,43.6532,-79.3832
dev-relay.lnfi.network,39.0997,-94.5786
slick.mjex.me,39.048,-77.4817
wot.sudocarlos.com,51.5072,-0.127586
relay04.lnfi.network,39.0997,-94.5786
relay.13room.space,43.6532,-79.3832
relay.conduit.market,43.6532,-79.3832
nostrelay.circum.space,52.3676,4.90414
nostr-relay.psfoundation.info,39.0438,-77.4874
strfry.shock.network,41.8959,-88.2169
nostr-2.21crypto.ch,47.4988,8.72369
relay1.nostrchat.io,60.1699,24.9384
nostr.plantroon.com,50.1013,8.62643
relay.artx.market,43.652,-79.3633
nostr.chaima.info,51.223,6.78245
wot.nostr.place,30.2672,-97.7431
nostr.rblb.it,43.4633,11.8796
relay.magiccity.live,25.8128,-80.2377
soloco.nl,40.7357,-74.1724
dizzyspells.nostr1.com,40.7128,-74.006
relay.zone667.com,60.1699,24.9384
nostr-01.uid.ovh,43.6532,-79.3832
zap.watch,45.5029,-73.5723
relay.wolfcoil.com,35.6092,139.73
relay.nostrdice.com,-33.8688,151.209
relay.goodmorningbitcoin.com,43.6532,-79.3832
relay.btcforplebs.com,40.7357,-74.1724
nostr.sathoarder.com,48.5734,7.75211
nostr.azzamo.net,52.2633,21.0283
wot.utxo.one,40.7128,-74.006
relay.bitcoindistrict.org,43.6532,-79.3832
relay.lumina.rocks,49.0291,8.35695
relay.primal.net,43.6532,-79.3832
nostr.notribe.net,40.8302,-74.1299
relay.usefusion.ai,38.7134,-78.1591
relay-dev.satlantis.io,40.8302,-74.1299
nostr.vulpem.com,49.4543,11.0746
orangesync.tech,50.1109,8.68213
relay.fountain.fm,39.0997,-94.5786
relay.cypherflow.ai,48.8566,2.35222
nostr-relay.online,40.7357,-74.1724
relay.internationalright-wing.org,-22.5022,-48.7114
relay.nostr.place,32.7767,-96.797
relay.npubhaus.com,40.7357,-74.1724
relay.jeffg.fyi,43.6532,-79.3832
nostr.night7.space,50.4754,12.3683
nostr.4rs.nl,49.0291,8.35696
nostr.liberty.fans,36.9104,-89.5875
ribo.eu.nostria.app,52.3676,4.90414
nostr.bitcoiner.social,39.1585,-94.5728
relay.basspistol.org,46.2044,6.14316
dev-relay.lnfi.network,39.0997,-94.5786
nostr.openhoofd.nl,51.9229,4.40833
nostr.huszonegy.world,47.4979,19.0402
relay.2nix.de,60.1699,24.9384
vitor.nostr1.com,40.7057,-74.0136
nostr.zenon.network,43.5009,-70.4428
relay.etch.social,41.2619,-95.8608
relay.fr13nd5.com,52.5233,13.3426
relay.agora.social,50.7383,15.0648
relay.credenso.cafe,43.3601,-80.3127
relay.illuminodes.com,47.6061,-122.333
relay.freeplace.nl,52.3676,4.90414
relay-rpi.edufeed.org,49.4543,11.0746
relay.bullishbounty.com,43.6532,-79.3832
relay04.lnfi.network,39.0997,-94.5786
nostr-01.yakihonne.com,1.32123,103.695
nostr-relay.xbytez.io,50.6924,3.20113
wot.sebastix.social,51.8933,4.42083
strfry.felixzieger.de,50.1013,8.62643
nostr.n7ekb.net,47.4941,-122.294
khatru.nostrver.se,51.8933,4.42083
relayrs.notoshi.win,40.7357,-74.1724
relay.wavlake.com,41.2619,-95.8608
wot.sudocarlos.com,51.5072,-0.127586
nostr.sagaciousd.com,49.2827,-123.121
relay.islandbitcoin.com,12.8498,77.6545
trizone.dev,1.35208,103.82
schnorr.me,40.7357,-74.1724
relay.vrtmrz.net,40.7357,-74.1724
relay.ditto.pub,43.6532,-79.3832
1 Relay URL Latitude Longitude
2 nostr.tac.lol nostr-relay.amethyst.name 47.4748 39.0438 -122.273 -77.4874
3 relay.javi.space bcast.seutoba.com.br 43.4633 43.6532 11.8796 -79.3832
4 nostr.einundzwanzig.space premium.primal.net 50.1109 40.7357 8.68213 -74.1724
5 nostr.kalf.org strfry.openhoofd.nl 52.3676 51.9229 4.90414 4.40833
wot.dtonon.com 43.6532 -79.3832
nostr-01.yakihonne.com 1.32123 103.695
wot.basspistol.org 49.4521 11.0767
relay.puresignal.news 43.6532 -79.3832
nostrelites.org 41.8781 -87.6298
nostr-relay.nextblockvending.com 47.674 -122.122
relay03.lnfi.network 39.0997 -94.5786
nproxy.kristapsk.lv 60.1699 24.9384
relay.toastr.net 40.8054 -74.0241
relay.davidebtc.me 51.5072 -0.127586
wot.nostr.net 43.6532 -79.3832
relay.mattybs.lol 43.6532 -79.3832
relay.zone667.com 60.1699 24.9384
nostr.kungfu-g.rip 33.7946 -84.4488
relay.mccormick.cx 52.3563 4.95714
relay.dwadziesciajeden.pl 52.2297 21.0122
nostr.data.haus 50.4754 12.3683
vitor.nostr1.com 40.7128 -74.006
purpura.cloud 43.6532 -79.3832
relay2.angor.io 48.1046 11.6002
nos.lol 50.4754 12.3683
nostr.rohoss.com 50.1109 8.68213
strfry.bonsai.com 37.8715 -122.273
relay.fountain.fm 39.0997 -94.5786
relay.npubhaus.com 43.6532 -79.3832
relay.nostr.wirednet.jp 34.706 135.493
soloco.nl 43.6532 -79.3832
shu01.shugur.net 21.4902 39.2246
nostr.davidebtc.me 51.5072 -0.127586
pyramid.fiatjaf.com 50.1109 8.68213
relay.ditto.pub 43.6532 -79.3832
relay.nostr.vet 52.6467 4.7395
relay.wavlake.com 41.2619 -95.8608
ribo.eu.nostria.app 52.3676 4.90414
relay.ngengine.org 43.6532 -79.3832
relay.bitcoinveneto.org 64.1466 -21.9426
no.str.cr 9.92857 -84.0528
relay.primal.net 43.6532 -79.3832
ynostr.yael.at 60.1699 24.9384
nostr.camalolo.com 24.1469 120.684
purplerelay.com 50.1109 8.68213
nostr-rs-relay-ishosta.phamthanh.me 43.6532 -79.3832
relay.internationalright-wing.org -22.5022 -48.7114
wheat.happytavern.co 43.6532 -79.3832
nostr.lostr.space 43.6532 -79.3832
relay.tagayasu.xyz 43.6715 -79.38
relay.varke.eu 52.6921 6.19372
free.relayted.de 50.1109 8.68213
nostr.thebiglake.org 32.71 -96.6745
nostr.lojong.info 43.6532 -79.3832
nostr.now 36.55 139.733
relay.jmoose.rocks 60.1699 24.9384
relay.holzeis.me 43.6532 -79.3832
nostr.roundrockbitcoiners.com 40.8054 -74.0241
nostr-rs-relay.dev.fedibtc.com 39.0438 -77.4874
relay2.ngengine.org 43.6532 -79.3832
nostr.snowbla.de 60.1699 24.9384
4u2ni0zjbjvni.clorecloud.net 43.6532 -79.3832
shu04.shugur.net 25.2604 55.2989
relay.fr13nd5.com 52.5233 13.3426
nostr.vulpem.com 49.4543 11.0746
temp.iris.to 43.6532 -79.3832
x.kojira.io 43.6532 -79.3832
adre.su 59.9311 30.3609
nostr-dev.wellorder.net 45.5201 -122.99
nostr.mom 50.4754 12.3683
relay.nostr.place 32.7767 -96.797
wot.nostr.place 30.2672 -97.7431
nostr.carroarmato0.be 50.9928 3.26317
nostrelay.circum.space 51.2217 6.77616
relay.chorus.community 50.1109 8.68213
relay.nostr.net 50.4754 12.3683
relay.nostr-check.me 43.6532 -79.3832
relay.nostrhub.fr 48.1046 11.6002
relay.nostraddress.com 43.6532 -79.3832
nostr.rblb.it 43.4633 11.8796
nostr.red5d.dev 43.6532 -79.3832
santo.iguanatech.net 40.8302 -74.1299
relay02.lnfi.network 39.0997 -94.5786
relay.21e6.cz 50.1682 14.0546
a.nos.lol 50.4754 12.3683
shu02.shugur.net 21.4902 39.2246
schnorr.me 43.6532 -79.3832
nostr.n7ekb.net 47.4941 -122.294
wot.shaving.kiwi 43.6532 -79.3832
dev-nostr.bityacht.io 25.0797 121.234
relay.credenso.cafe 43.1149 -80.7228
relay-testnet.k8s.layer3.news 37.3387 -121.885
relay.mess.ch 47.3591 8.55292
inbox.azzamo.net 52.2633 21.0283
prl.plus 55.7623 37.6381
yabu.me 35.6092 139.73
relayrs.notoshi.win 43.6532 -79.3832
premium.primal.net 43.6532 -79.3832
nostr.coincrowd.fund 39.0438 -77.4874
nostr.2b9t.xyz 34.0549 -118.243
nostr.thaliyal.com 40.8218 -74.45
relay.exit.pub 50.4754 12.3683
nostr.jfischer.org 49.0291 8.35696
relay.origin.land 35.6673 139.751
nostr.myshosholoza.co.za 52.3676 4.90414
relay.nostriot.com 41.5695 -83.9786
relay.btcforplebs.com 43.6532 -79.3832
relay.chakany.systems 43.6532 -79.3832
nostr.openhoofd.nl 51.9229 4.40833
nostrcheck.me 43.6532 -79.3832
nostr.plantroon.com 50.1013 8.62643
satsage.xyz 37.3986 -121.964
nostr.faultables.net 43.6532 -79.3832
nostr.calitabby.net 39.9268 -75.0246
relay.freeplace.nl 52.3676 4.90414
relay.nostrhub.tech 49.4543 11.0746
roles-az-achieving-somebody.trycloudflare.com 43.6532 -79.3832
relay.arx-ccn.com 50.4754 12.3683
cyberspace.nostr1.com 40.7128 -74.006
nostr.smut.cloud 43.6532 -79.3832
nostr-02.czas.top 53.471 9.88208
relay.tapestry.ninja 40.8054 -74.0241
6 relay.mostro.network 40.8302 -74.1299
7 wot.brightbolt.net ribo.us.nostria.app 47.6735 41.5868 -116.781 -93.625
8 nostr.spaceshell.xyz relayone.geektank.ai 43.6532 18.2148 -79.3832 -63.0574
nostr.rikmeijer.nl 50.4754 12.3683
relay.artx.market 43.652 -79.3633
strfry.felixzieger.de 50.1013 8.62643
relay.seq1.net 43.6532 -79.3832
relay.cosmicbolt.net 37.3986 -121.964
relay.electriclifestyle.com 26.2897 -80.1293
r.bitcoinhold.net 43.6532 -79.3832
nostr-relay.amethyst.name 39.0067 -77.4291
relay.stream.labs.h3.se 59.4016 17.9455
relay.unknown.cloud 43.6532 -79.3832
nostr-02.yakihonne.com 1.32123 103.695
relay.coinos.io 43.6532 -79.3832
relay5.bitransfer.org 43.6532 -79.3832
relay-dev.satlantis.io 40.8302 -74.1299
nostream.breadslice.com 43.6532 -79.3832
relay.fundstr.me 42.3601 -71.0589
nostr.oxtr.dev 50.4754 12.3683
nos.xmark.cc 50.6924 3.20113
9 nostr.mikoshi.de 50.1109 8.68213
relay.magiccity.live 25.8128 -80.2377
nostr-verified.wellorder.net 45.5201 -122.99
nostr.makibisskey.work 43.6532 -79.3832
wot.nostr.party 36.1627 -86.7816
relay.copylaradio.com 51.223 6.78245
nostr.sathoarder.com 48.5734 7.75211
relay.jeffg.fyi 43.6532 -79.3832
relay.wellorder.net 45.5201 -122.99
nostr.ovia.to 43.6532 -79.3832
black.nostrcity.club 41.8781 -87.6298
relay.nostrcheck.me 43.6532 -79.3832
nostr-relay.cbrx.io 43.6532 -79.3832
nostr-03.dorafactory.org 1.35208 103.82
nostr-relay.zimage.com 34.282 -118.439
relay.sigit.io 50.4754 12.3683
relay.laantungir.net -19.4692 -42.5315
relay-admin.thaliyal.com 40.8218 -74.45
relay.mwaters.net 50.9871 2.12554
relay.lumina.rocks 49.0291 8.35695
nostr.satstralia.com 64.1476 -21.9392
nostr.sagaciousd.com 49.2827 -123.121
relay.bullishbounty.com 43.6532 -79.3832
wot.dergigi.com 64.1476 -21.9392
relay.vrtmrz.net 43.6532 -79.3832
nostr.0x7e.xyz 47.4988 8.72369
articles.layer3.news 37.3387 -121.885
relay.digitalezukunft.cyou 45.5019 -73.5674
nostr.notribe.net 40.8302 -74.1299
nostr.21crypto.ch 47.4988 8.72369
10 relay.lifpay.me 1.35208 103.82
11 relay.g1sms.fr shu02.shugur.net 43.9432 21.4902 2.07537 39.2246
12 relay.snort.social nostr.hifish.org 43.6532 47.4043 -79.3832 8.57398
13 orangepiller.org 60.1699 24.9384
14 nostr.myshosholoza.co.za 52.3676 4.90414
15 relay.nostrcheck.me 43.6532 -79.3832
16 relay.nostrhub.tech 49.0291 8.35696
17 nostr.mehdibekhtaoui.com 49.4939 -1.54813
18 nostrcheck.me 40.7357 -74.1724
19 relay.arx-ccn.com 50.4754 12.3683
20 relay2.ngengine.org 43.6532 -79.3832
21 nostr.21crypto.ch 47.4988 8.72369
22 nostr.girino.org 43.6532 -79.3832
23 relay.nostriches.club 43.6532 -79.3832
24 relay.angor.io 48.1046 11.6002
25 nostr.data.haus 50.4754 12.3683
26 nostr.zoracle.org 45.6018 -121.185
27 relay2.angor.io 48.1046 11.6002
28 librerelay.aaroniumii.com 43.6532 -79.3832
29 nostr.tadryanom.me 40.7357 -74.1724
30 nostr-relay.cbrx.io 43.6532 -79.3832
31 nostr-rs-relay.dev.fedibtc.com 39.0438 -77.4874
32 relay.aloftus.io 34.0881 -118.379
33 relay.barine.co 43.6532 -79.3832
34 nostr.red5d.dev 43.6532 -79.3832
35 nos.lol 50.4754 12.3683
36 ithurtswhenip.ee 51.223 6.78245
37 strfry.bonsai.com 37.8715 -122.273
38 relay01.lnfi.network 39.0997 -94.5786
39 nostrcheck.tnsor.network 43.6532 -79.3832
40 x.kojira.io 43.6532 -79.3832
41 nostr.snowbla.de 60.1699 24.9384
42 purplerelay.com 50.1109 8.68213
43 wot.sovbit.host 64.1466 -21.9426
44 shu04.shugur.net 25.2604 55.2989
45 nr.yay.so 46.2126 6.1154
46 nostr.smartflowsocial.com 43.6532 -79.3832
47 shu05.shugur.net 48.8566 2.35222
48 wot.dtonon.com 43.6532 -79.3832
49 pyramid.fiatjaf.com 51.5072 -0.127586
50 nostr.88mph.life 40.7357 -74.1724
51 dev-nostr.bityacht.io 25.0797 121.234
52 cyberspace.nostr1.com 40.7128 -74.006
53 relay.ngengine.org 40.7357 -74.1724
54 nostr.calitabby.net 39.9268 -75.0246
55 relay.toastr.net 40.8054 -74.0241
56 relay.cosmicbolt.net 37.3986 -121.964
57 nostr.davidebtc.me 50.1109 8.68213
58 espelho.girino.org 43.6532 -79.3832
59 srtrelay.c-stellar.net 40.7357 -74.1724
60 relay.nostriot.com 41.5695 -83.9786
61 relay.bitcoinveneto.org 64.1466 -21.9426
62 bitcoiner.social 39.1585 -94.5728
63 purpura.cloud 40.7357 -74.1724
64 nostr.blankfors.se 60.1699 24.9384
65 relay.nostromo.social 49.4543 11.0746
66 ribo.af.nostria.app -26.2041 28.0473
67 relay.olas.app 50.4754 12.3683
68 nostr.carroarmato0.be 50.9928 3.26317
69 nostr.oxtr.dev 50.4754 12.3683
70 relay.upleb.uk 52.2297 21.0122
71 nostr.stakey.net 52.3676 4.90414
72 nostr2.girino.org 40.7357 -74.1724
73 nostr.rikmeijer.nl 50.4754 12.3683
74 relay5.bitransfer.org 40.7357 -74.1724
75 relay.mattybs.lol 40.7357 -74.1724
76 nostr.makibisskey.work 40.7357 -74.1724
77 wot.basspistol.org 49.4521 11.0767
78 relay.nostr.net 50.4754 12.3683
79 a.nos.lol 50.4754 12.3683
80 wot.dergigi.com 64.1476 -21.9392
81 fanfares.nostr1.com 40.7057 -74.0136
82 nostr.faultables.net 43.6532 -79.3832
83 relay.dwadziesciajeden.pl 52.2297 21.0122
84 adre.su 59.9311 30.3609
85 wot.nostr.party 36.1627 -86.7816
86 relay03.lnfi.network 39.0997 -94.5786
87 relay.orangepill.ovh 49.1689 -0.358841
88 gnostr.com 42.6978 23.3246
89 relay.wellorder.net 45.5201 -122.99
90 relay.21e6.cz 50.1682 14.0546
91 relay.tagayasu.xyz 43.6715 -79.38
92 relay.chatbett.de 28.0199 -82.5248
93 wot.soundhsa.com 33.1384 -95.6011
94 prl.plus 38.9072 -77.0369
95 nostr.einundzwanzig.space 50.1109 8.68213
96 nostream.breadslice.com 1.35208 103.82
97 relay.chorus.community 50.1109 8.68213
98 nostr.mom 50.4754 12.3683
99 relay.lightning.pub 41.8959 -88.2169
100 relay.hook.cafe 40.7357 -74.1724
101 relay-testnet.k8s.layer3.news 37.3387 -121.885
102 relay.fundstr.me 42.3601 -71.0589
103 relay.stream.labs.h3.se 59.4016 17.9455
104 relay.holzeis.me 43.6532 -79.3832
105 articles.layer3.news 37.3387 -121.885
106 nproxy.kristapsk.lv 60.1699 24.9384
107 nostr.thebiglake.org 32.71 -96.6745
108 relay.coinos.io 40.7357 -74.1724
109 nostr.camalolo.com 24.1469 120.684
110 theoutpost.life 64.1476 -21.9392
111 relay.nostraddress.com 40.7357 -74.1724
112 nostr.casa21.space 40.7357 -74.1724
113 relay.agorist.space 52.3734 4.89406
114 relay.nostr.wirednet.jp 34.706 135.493
115 nostr.jerrynya.fun 31.2304 121.474
116 relay.13room.space 43.6532 -79.3832
117 offchain.pub 47.6743 -117.112
118 relay.hasenpfeffr.com 39.0438 -77.4874
119 nostr-verified.wellorder.net 45.5201 -122.99
120 nostrelay.memory-art.xyz 43.6532 -79.3832
121 freeben666.fr 43.1204 6.12857
122 nostr.bilthon.dev 25.8128 -80.2377
123 nostr.spicyz.io 40.7357 -74.1724
124 bcast.girino.org 40.7357 -74.1724
125 nostr.noones.com 50.1109 8.68213
126 relay.electriclifestyle.com 26.2897 -80.1293
127 relay.guggero.org 47.3769 8.54169
128 relay.siamdev.cc 13.8434 100.363
129 relay.varke.eu 52.6921 6.19372
130 nostr.now 36.55 139.733
131 relay.origin.land 35.6673 139.751
132 yabu.me 35.6092 139.73
133 nostr-02.yakihonne.com 1.32123 103.695
134 nostr.tac.lol 47.4748 -122.273
135 r.bitcoinhold.net 40.7357 -74.1724
136 nostr.rtvslawenia.com 49.4543 11.0746
137 relay.sigit.io 50.4754 12.3683
138 nostr-rs-relay-ishosta.phamthanh.me 40.7357 -74.1724
139 relay.bitcoinartclock.com 50.4754 12.3683
140 relay.snort.social 40.7357 -74.1724
141 relay.mwaters.net 50.9871 2.12554
142 nostr-03.dorafactory.org 1.35208 103.82
143 relay.damus.io 40.7357 -74.1724
144 black.nostrcity.club 41.8781 -87.6298
145 noxir.kpherox.dev 34.8587 135.509
146 relay.javi.space 43.4633 11.8796
147 fenrir-s.notoshi.win 43.6532 -79.3832
148 relay02.lnfi.network 39.0997 -94.5786
149 mhp258zrpiiwn.clorecloud.net 40.7357 -74.1724
150 relay.libernet.app 43.6532 -79.3832
151 nostr.coincards.com 53.5501 -113.469
152 ynostr.yael.at 60.1699 24.9384
153 slick.mjex.me 39.048 -77.4817
154 nostr.agentcampfire.com 50.8933 6.05805
155 nostr-pub.wellorder.net 45.5201 -122.99
156 relay.artiostr.ch 43.6532 -79.3832
157 relay.davidebtc.me 50.1109 8.68213
158 shu01.shugur.net 21.4902 39.2246
159 relay.nostr.band 60.1699 24.9384
160 relay.evanverma.com 40.8302 -74.1299
161 nostr.simplex.icu 50.8198 -1.08798
162 wot.nostr.net 43.6532 -79.3832
163 relay.nostr.vet 52.6467 4.7395
164 r.lostr.net 52.3676 4.90414
165 relay.getsafebox.app 43.6532 -79.3832
166 relay.moinsen.com 50.4754 12.3683
nostr.blankfors.se 60.1699 24.9384
nostr-relay-1.trustlessenterprise.com 43.6532 -79.3832
orangesync.tech 50.1109 8.68213
relay.ru.ac.th 13.7584 100.622
orangepiller.org 60.1699 24.9384
relay.nostr.band 60.1699 24.9384
wot.soundhsa.com 34.0479 -118.256
khatru.nostrver.se 51.8933 4.42083
nostr.hifish.org 47.4043 8.57398
freelay.sovbit.host 64.1476 -21.9392
nostr.bilthon.dev 25.8128 -80.2377
nostr.night7.space 50.4754 12.3683
relay.illuminodes.com 47.6061 -122.333
relayone.soundhsa.com 34.0479 -118.256
nostr.azzamo.net 52.2633 21.0283
fenrir-s.notoshi.win 43.6532 -79.3832
nostr.spicyz.io 43.6532 -79.3832
nostrelay.memory-art.xyz 43.6532 -79.3832
nostr.coincards.com 53.5501 -113.469
alien.macneilmediagroup.com 43.6532 -79.3832
nostrings-relay-dev.fly.dev 41.8781 -87.6298
relay.satlantis.io 32.8769 -80.0114
srtrelay.c-stellar.net 43.6532 -79.3832
relay.agora.social 50.7383 15.0648
relay.bitcoindistrict.org 43.6532 -79.3832
relay.0xchat.com 1.35208 103.82
wot.utxo.one 43.6532 -79.3832
relay.bitcoinartclock.com 50.4754 12.3683
nostr.zenon.network 43.5009 -70.4428
wot.codingarena.top 50.4754 12.3683
nostr-02.dorafactory.org 1.35208 103.82
relay.nostromo.social 49.4543 11.0746
theoutpost.life 64.1476 -21.9392
strfry.shock.network 41.8959 -88.2169
strfry.openhoofd.nl 51.9229 4.40833
itanostr.space 52.2931 4.79099
relay.barine.co 43.6532 -79.3832
nostr.middling.mydns.jp 35.8099 140.12
relay.olas.app 50.4754 12.3683
nostr.girino.org 43.6532 -79.3832
nostr-relay.online 43.6532 -79.3832
relay.evanverma.com 40.8302 -74.1299
relay.angor.io 48.1046 11.6002
relay.nostrdice.com -33.8688 151.209
ribo.us.nostria.app 41.5868 -93.625
relay01.lnfi.network 39.0997 -94.5786
nostr.namek.link 43.6532 -79.3832
relay.aloftus.io 34.0881 -118.379
ithurtswhenip.ee 51.223 6.78245
ribo.af.nostria.app -26.2041 28.0473
shu05.shugur.net 48.8566 2.35222
noxir.kpherox.dev 34.8587 135.509
relay.degmods.com 50.4754 12.3683
relay.goodmorningbitcoin.com 43.6532 -79.3832
nostr.4rs.nl 49.0291 8.35696
nostr-relay.psfoundation.info 39.0438 -77.4874
relay.hasenpfeffr.com 39.0438 -77.4874
fanfares.nostr1.com 40.7128 -74.006
relay.nosto.re 51.8933 4.42083
nostr.liberty.fans 36.9104 -89.5875
nostr-2.21crypto.ch 47.4988 8.72369
relay-rpi.edufeed.org 49.4543 11.0746
offchain.pub 36.1809 -115.241
nostr.88mph.life 43.6532 -79.3832
167 nostr.luisschwab.net 43.6532 -79.3832
168 nostr.casa21.space strfry.elswa-dev.online 43.6532 48.8566 -79.3832 2.35222
169 alienos.libretechsystems.xyz 55.4724 9.87335
170 nostr.overmind.lol 40.7357 -74.1724
171 nos.xmark.cc 50.6924 3.20113
172 relay.degmods.com 50.4754 12.3683
173 relay.seq1.net 40.7128 -74.006
174 relay.uid.ovh 43.6532 -79.3832
175 santo.iguanatech.net 40.8302 -74.1299
176 nostr.spaceshell.xyz 43.6532 -79.3832
177 nostr.hekster.org 37.3986 -121.964
178 wheat.happytavern.co 43.6532 -79.3832
179 nostr-02.czas.top 53.471 9.88208
180 satsage.xyz 37.3986 -121.964
181 no.str.cr 9.92857 -84.0528
182 relay.puresignal.news 40.7357 -74.1724
183 nostr-relay.nextblockvending.com 47.2343 -119.853
184 keys.nostr1.com 40.7057 -74.0136
185 relayone.soundhsa.com 33.1384 -95.6011
186 nostr-dev.wellorder.net 45.5201 -122.99
187 alien.macneilmediagroup.com 40.7357 -74.1724
188 nostr.kalf.org 52.3676 4.90414
189 nostrelites.org 41.8781 -87.6298
190 temp.iris.to 43.6532 -79.3832
191 relay.utxo.farm 35.6916 139.768
192 zap.watch freelay.sovbit.host 45.5029 64.1476 -73.5723 -21.9392
193 nostr-pub.wellorder.net relay.nosto.re 45.5201 51.8933 -122.99 4.42083
194 wot.sovbit.host inbox.azzamo.net 64.1466 52.2633 -21.9426 21.0283
195 relay.endfiat.money nostr.ovia.to 43.6532 -79.3832
196 nostr2.girino.org nostr.lostr.space 43.6532 40.7357 -79.3832 -74.1724
197 nostr.jerrynya.fun nostr-relay-1.trustlessenterprise.com 31.2304 43.6532 121.474 -79.3832
198 nostr.spacecitynode.com relay.nostar.org 29.7057 40.7357 -95.2706 -74.1724
199 relay.siamdev.cc relay.mccormick.cx 13.9178 52.3563 100.424 4.95714
200 relay.notoshi.win nostr.0x7e.xyz 13.7829 47.4988 100.546 8.72369
201 relay.nostx.io relay.0xchat.com 43.6532 1.35208 -79.3832 103.82
202 relay.cypherflow.ai relay.thebluepulse.com 48.8566 40.7357 2.35222 -74.1724
203 relay.letsfo.com 51.098 17.0321
204 librerelay.aaroniumii.com nostrelay.circum.space 43.6532 52.3676 -79.3832 4.90414
205 gnostr.com nostr-relay.psfoundation.info 40.9017 39.0438 29.1616 -77.4874
206 nostr.pleb.one strfry.shock.network 38.6327 41.8959 -90.1961 -88.2169
207 nostr.mehdibekhtaoui.com nostr-2.21crypto.ch 49.4939 47.4988 -1.54813 8.72369
208 nostr.tadryanom.me relay1.nostrchat.io 43.6532 60.1699 -79.3832 24.9384
209 relay.orangepill.ovh nostr.plantroon.com 49.1689 50.1013 -0.358841 8.62643
210 nostr.stakey.net relay.artx.market 52.3676 43.652 4.90414 -79.3633
nostr.rtvslawenia.com 49.4543 11.0746
relay.damus.io 43.6532 -79.3832
dev-relay.lnfi.network 39.0997 -94.5786
slick.mjex.me 39.048 -77.4817
wot.sudocarlos.com 51.5072 -0.127586
relay04.lnfi.network 39.0997 -94.5786
relay.13room.space 43.6532 -79.3832
relay.conduit.market 43.6532 -79.3832
211 nostr.chaima.info 51.223 6.78245
212 wot.nostr.place 30.2672 -97.7431
213 nostr.rblb.it 43.4633 11.8796
214 relay.magiccity.live 25.8128 -80.2377
215 soloco.nl 40.7357 -74.1724
216 dizzyspells.nostr1.com 40.7128 -74.006
217 relay.zone667.com 60.1699 24.9384
218 nostr-01.uid.ovh 43.6532 -79.3832
219 zap.watch 45.5029 -73.5723
220 relay.wolfcoil.com 35.6092 139.73
221 relay.nostrdice.com -33.8688 151.209
222 relay.goodmorningbitcoin.com 43.6532 -79.3832
223 relay.btcforplebs.com 40.7357 -74.1724
224 nostr.sathoarder.com 48.5734 7.75211
225 nostr.azzamo.net 52.2633 21.0283
226 wot.utxo.one 40.7128 -74.006
227 relay.bitcoindistrict.org 43.6532 -79.3832
228 relay.lumina.rocks 49.0291 8.35695
229 relay.primal.net 43.6532 -79.3832
230 nostr.notribe.net 40.8302 -74.1299
231 relay.usefusion.ai 38.7134 -78.1591
232 relay-dev.satlantis.io 40.8302 -74.1299
233 nostr.vulpem.com 49.4543 11.0746
234 orangesync.tech 50.1109 8.68213
235 relay.fountain.fm 39.0997 -94.5786
236 relay.cypherflow.ai 48.8566 2.35222
237 nostr-relay.online 40.7357 -74.1724
238 relay.internationalright-wing.org -22.5022 -48.7114
239 relay.nostr.place 32.7767 -96.797
240 relay.npubhaus.com 40.7357 -74.1724
241 relay.jeffg.fyi 43.6532 -79.3832
242 nostr.night7.space 50.4754 12.3683
243 nostr.4rs.nl 49.0291 8.35696
244 nostr.liberty.fans 36.9104 -89.5875
245 ribo.eu.nostria.app 52.3676 4.90414
246 nostr.bitcoiner.social 39.1585 -94.5728
247 relay.basspistol.org 46.2044 6.14316
248 dev-relay.lnfi.network 39.0997 -94.5786
249 nostr.openhoofd.nl 51.9229 4.40833
250 nostr.huszonegy.world 47.4979 19.0402
251 relay.2nix.de 60.1699 24.9384
252 vitor.nostr1.com 40.7057 -74.0136
253 nostr.zenon.network 43.5009 -70.4428
254 relay.etch.social 41.2619 -95.8608
255 relay.fr13nd5.com 52.5233 13.3426
256 relay.agora.social 50.7383 15.0648
257 relay.credenso.cafe 43.3601 -80.3127
258 relay.illuminodes.com 47.6061 -122.333
259 relay.freeplace.nl 52.3676 4.90414
260 relay-rpi.edufeed.org 49.4543 11.0746
261 relay.bullishbounty.com 43.6532 -79.3832
262 relay04.lnfi.network 39.0997 -94.5786
263 nostr-01.yakihonne.com 1.32123 103.695
264 nostr-relay.xbytez.io 50.6924 3.20113
265 wot.sebastix.social 51.8933 4.42083
266 strfry.felixzieger.de 50.1013 8.62643
267 nostr.n7ekb.net 47.4941 -122.294
268 khatru.nostrver.se 51.8933 4.42083
269 relayrs.notoshi.win 40.7357 -74.1724
270 relay.wavlake.com 41.2619 -95.8608
271 wot.sudocarlos.com 51.5072 -0.127586
272 nostr.sagaciousd.com 49.2827 -123.121
273 relay.islandbitcoin.com 12.8498 77.6545
274 trizone.dev 1.35208 103.82
275 schnorr.me 40.7357 -74.1724
276 relay.vrtmrz.net 40.7357 -74.1724
277 relay.ditto.pub 43.6532 -79.3832
@@ -19,6 +19,9 @@ class BitchatApplication : Application() {
// Initialize relay directory (loads assets/nostr_relays.csv)
RelayDirectory.initialize(this)
// Initialize LocationNotesManager dependencies early so sheet subscriptions can start immediately
try { com.bitchat.android.nostr.LocationNotesInitializer.initialize(this) } catch (_: Exception) { }
// Initialize favorites persistence early so MessageRouter/NostrTransport can use it on startup
try {
com.bitchat.android.favorites.FavoritesPersistenceService.initialize(this)
@@ -3,7 +3,6 @@ package com.bitchat.android
import android.content.Intent
import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.OnBackPressedCallback
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
@@ -15,7 +14,6 @@ import androidx.compose.material3.Scaffold
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.repeatOnLifecycle
@@ -39,13 +37,14 @@ import com.bitchat.android.onboarding.PermissionExplanationScreen
import com.bitchat.android.onboarding.PermissionManager
import com.bitchat.android.ui.ChatScreen
import com.bitchat.android.ui.ChatViewModel
import com.bitchat.android.ui.OrientationAwareActivity
import com.bitchat.android.ui.theme.BitchatTheme
import com.bitchat.android.nostr.PoWPreferenceManager
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
class MainActivity : ComponentActivity() {
class MainActivity : OrientationAwareActivity() {
private lateinit var permissionManager: PermissionManager
private lateinit var onboardingCoordinator: OnboardingCoordinator
private lateinit var bluetoothStatusManager: BluetoothStatusManager
@@ -598,6 +597,9 @@ class MainActivity : ComponentActivity() {
PoWPreferenceManager.init(this@MainActivity)
Log.d("MainActivity", "PoW preferences initialized")
// Initialize Location Notes Manager (extracted to separate file)
com.bitchat.android.nostr.LocationNotesInitializer.initialize(this@MainActivity)
// Ensure all permissions are still granted (user might have revoked in settings)
if (!permissionManager.areAllPermissionsGranted()) {
val missing = permissionManager.getMissingPermissions()
@@ -3,34 +3,109 @@ package com.bitchat.android.features.media
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.net.Uri
import androidx.exifinterface.media.ExifInterface
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
object ImageUtils {
fun downscaleAndSaveToAppFiles(context: Context, uri: android.net.Uri, maxDim: Int = 512, quality: Int = 85): String? {
fun downscaleAndSaveToAppFiles(context: Context, uri: Uri, maxDim: Int = 512, quality: Int = 85): String? {
return try {
val resolver = context.contentResolver
val exifRotation = resolver.openInputStream(uri)?.use { getRotationDegreesFromExif(it) } ?: 0
// Reopen for decode as the previous stream is consumed
val input = resolver.openInputStream(uri) ?: return null
val original = BitmapFactory.decodeStream(input)
input.close()
original ?: return null
val w = original.width
val h = original.height
val oriented = if (exifRotation != 0) rotateBitmap(original, exifRotation) else original
val w = oriented.width
val h = oriented.height
val scale = (maxOf(w, h).toFloat() / maxDim.toFloat()).coerceAtLeast(1f)
val newW = (w / scale).toInt().coerceAtLeast(1)
val newH = (h / scale).toInt().coerceAtLeast(1)
val scaled = if (scale > 1f) Bitmap.createScaledBitmap(original, newW, newH, true) else original
val scaled = if (scale > 1f) Bitmap.createScaledBitmap(oriented, newW, newH, true) else oriented
val dir = File(context.filesDir, "images/outgoing").apply { mkdirs() }
val outFile = File(dir, "img_${System.currentTimeMillis()}.jpg")
FileOutputStream(outFile).use { fos ->
scaled.compress(Bitmap.CompressFormat.JPEG, quality, fos)
}
if (scaled !== original) try { original.recycle() } catch (_: Exception) {}
try { if (scaled != original) scaled.recycle() } catch (_: Exception) {}
try { if (oriented !== original) original.recycle() } catch (_: Exception) {}
try { if (scaled !== oriented) oriented.recycle() } catch (_: Exception) {}
outFile.absolutePath
} catch (e: Exception) {
null
}
}
}
fun downscalePathAndSaveToAppFiles(context: Context, path: String, maxDim: Int = 512, quality: Int = 85): String? {
return try {
val original = BitmapFactory.decodeFile(path) ?: return null
val exifRotation = getRotationDegreesFromExif(path)
val oriented = if (exifRotation != 0) rotateBitmap(original, exifRotation) else original
val w = oriented.width
val h = oriented.height
val scale = (maxOf(w, h).toFloat() / maxDim.toFloat()).coerceAtLeast(1f)
val newW = (w / scale).toInt().coerceAtLeast(1)
val newH = (h / scale).toInt().coerceAtLeast(1)
val scaled = if (scale > 1f) Bitmap.createScaledBitmap(oriented, newW, newH, true) else oriented
val dir = File(context.filesDir, "images/outgoing").apply { mkdirs() }
val outFile = File(dir, "img_${System.currentTimeMillis()}.jpg")
FileOutputStream(outFile).use { fos ->
scaled.compress(Bitmap.CompressFormat.JPEG, quality, fos)
}
try { if (oriented !== original) original.recycle() } catch (_: Exception) {}
try { if (scaled !== oriented) oriented.recycle() } catch (_: Exception) {}
outFile.absolutePath
} catch (e: Exception) {
null
}
}
fun loadBitmapWithExifOrientation(path: String): Bitmap? {
return try {
val base = BitmapFactory.decodeFile(path) ?: return null
val rotation = getRotationDegreesFromExif(path)
if (rotation != 0) rotateBitmap(base, rotation) else base
} catch (_: Exception) {
null
}
}
private fun rotateBitmap(src: Bitmap, degrees: Int): Bitmap {
return try {
val m = Matrix()
m.postRotate(degrees.toFloat())
Bitmap.createBitmap(src, 0, 0, src.width, src.height, m, true).also {
try { src.recycle() } catch (_: Exception) {}
}
} catch (_: Exception) {
src
}
}
private fun getRotationDegreesFromExif(path: String): Int = try {
val exif = ExifInterface(path)
orientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL))
} catch (_: Exception) { 0 }
private fun getRotationDegreesFromExif(stream: InputStream): Int = try {
val exif = ExifInterface(stream)
orientationToDegrees(exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, ExifInterface.ORIENTATION_NORMAL))
} catch (_: Exception) { 0 }
private fun orientationToDegrees(orientation: Int): Int = when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> 90
ExifInterface.ORIENTATION_ROTATE_180 -> 180
ExifInterface.ORIENTATION_ROTATE_270 -> 270
ExifInterface.ORIENTATION_TRANSPOSE -> 90
ExifInterface.ORIENTATION_TRANSVERSE -> 270
else -> 0
}
}
@@ -1,3 +1,4 @@
package com.bitchat.android.features.voice
import android.content.Context
@@ -37,12 +38,13 @@ class VoiceRecorder(private val context: Context) {
rec.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
rec.setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
rec.setAudioChannels(1)
rec.setAudioSamplingRate(44100)
// Lower bitrate to keep BLE payloads <= 32KiB for fragmentation
rec.setAudioEncodingBitRate(32_000)
// Target: 16 kHz AAC @ 20 kbps ≈ 2.5 KB/sec
// Lower sample rate and bitrate for compact, speech-optimized recordings
rec.setAudioSamplingRate(16000)
rec.setAudioEncodingBitRate(20_000)
rec.setOutputFile(file.absolutePath)
rec.prepare()
rec.start()
rec.start()
recorder = rec
outFile = file
file
@@ -115,4 +115,36 @@ object Geohash {
lonMax = maxOf(lonInterval.first, lonInterval.second)
)
}
/**
* Returns the 8 neighboring geohash cells at the same precision as the input.
* Neighbors include N, NE, E, SE, S, SW, W, NW, even when crossing parent cell boundaries.
*/
fun neighborsSamePrecision(geohash: String): Set<String> {
if (geohash.isEmpty()) return emptySet()
val p = geohash.length
val b = decodeToBounds(geohash)
val dLat = b.latMax - b.latMin
val dLon = b.lonMax - b.lonMin
fun wrapLon(lon: Double): Double {
var x = lon
while (x > 180.0) x -= 360.0
while (x < -180.0) x += 360.0
return x
}
val neighbors = mutableSetOf<String>()
for (dy in -1..1) {
for (dx in -1..1) {
if (dx == 0 && dy == 0) continue // skip center
val centerLat = (b.latMin + b.latMax) / 2 + dy * dLat
val rawLonCenter = (b.lonMin + b.lonMax) / 2 + dx * dLon
val centerLon = wrapLon(rawLonCenter)
val enc = encode(centerLat.coerceIn(-90.0, 90.0), centerLon, p)
if (enc.isNotEmpty() && enc != geohash) neighbors.add(enc)
}
}
return neighbors
}
}
@@ -5,6 +5,7 @@ package com.bitchat.android.geohash
* Direct port from iOS implementation for 100% compatibility
*/
enum class GeohashChannelLevel(val precision: Int, val displayName: String) {
BUILDING(8, "Building"), // iOS: precision 8 for building-level (used for Location Notes)
BLOCK(7, "Block"),
NEIGHBORHOOD(6, "Neighborhood"),
CITY(5, "City"),
@@ -88,10 +88,17 @@ class LocationChannelManager private constructor(private val context: Context) {
/**
* Enable location channels (request permission if needed)
* UNIFIED: Only requests location if location services are enabled by user
*/
fun enableLocationChannels() {
Log.d(TAG, "enableLocationChannels() called")
// UNIFIED FIX: Check if location services are enabled by user
if (!isLocationServicesEnabled()) {
Log.w(TAG, "Location services disabled by user - not requesting location")
return
}
when (getCurrentPermissionStatus()) {
PermissionState.NOT_DETERMINED -> {
Log.d(TAG, "Permission not determined - user needs to grant in app settings")
@@ -20,10 +20,10 @@ class BluetoothConnectionTracker(
companion object {
private const val TAG = "BluetoothConnectionTracker"
private const val CONNECTION_RETRY_DELAY = 5000L
private const val MAX_CONNECTION_ATTEMPTS = 3
private const val CLEANUP_DELAY = 500L
private const val CLEANUP_INTERVAL = 30000L // 30 seconds
private const val CONNECTION_RETRY_DELAY = com.bitchat.android.util.AppConstants.Mesh.CONNECTION_RETRY_DELAY_MS
private const val MAX_CONNECTION_ATTEMPTS = com.bitchat.android.util.AppConstants.Mesh.MAX_CONNECTION_ATTEMPTS
private const val CLEANUP_DELAY = com.bitchat.android.util.AppConstants.Mesh.CONNECTION_CLEANUP_DELAY_MS
private const val CLEANUP_INTERVAL = com.bitchat.android.util.AppConstants.Mesh.CONNECTION_CLEANUP_INTERVAL_MS // 30 seconds
}
// Connection tracking - reduced memory footprint
@@ -9,6 +9,7 @@ import android.content.Context
import android.os.ParcelUuid
import android.util.Log
import com.bitchat.android.protocol.BitchatPacket
import com.bitchat.android.util.AppConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -31,13 +32,6 @@ class BluetoothGattClientManager(
companion object {
private const val TAG = "BluetoothGattClientManager"
// Use exact same UUIDs as iOS version
private val SERVICE_UUID = UUID.fromString("F47B5E2D-4A9E-4C5A-9B3F-8E1D2C3A4B5C")
private val CHARACTERISTIC_UUID = UUID.fromString("A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D")
private val DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
// RSSI monitoring constants
private const val RSSI_UPDATE_INTERVAL = 5000L // 5 seconds
}
// Core Bluetooth components
@@ -182,10 +176,10 @@ class BluetoothGattClientManager(
Log.w(TAG, "Failed to request RSSI from ${deviceConn.device.address}: ${e.message}")
}
}
delay(RSSI_UPDATE_INTERVAL)
delay(AppConstants.Mesh.RSSI_UPDATE_INTERVAL_MS)
} catch (e: Exception) {
Log.w(TAG, "Error in RSSI monitoring: ${e.message}")
delay(RSSI_UPDATE_INTERVAL)
delay(AppConstants.Mesh.RSSI_UPDATE_INTERVAL_MS)
}
}
}
@@ -231,12 +225,12 @@ class BluetoothGattClientManager(
}
val scanFilter = ScanFilter.Builder()
.setServiceUuid(ParcelUuid(SERVICE_UUID))
.setServiceUuid(ParcelUuid(AppConstants.Mesh.Gatt.SERVICE_UUID))
.build()
val scanFilters = listOf(scanFilter)
Log.d(TAG, "Starting BLE scan with target service UUID: $SERVICE_UUID")
Log.d(TAG, "Starting BLE scan with target service UUID: ${AppConstants.Mesh.Gatt.SERVICE_UUID}")
scanCallback = object : ScanCallback() {
override fun onScanResult(callbackType: Int, result: ScanResult) {
@@ -321,7 +315,7 @@ class BluetoothGattClientManager(
val scanRecord = result.scanRecord
// CRITICAL: Only process devices that have our service UUID
val hasOurService = scanRecord?.serviceUuids?.any { it.uuid == SERVICE_UUID } == true
val hasOurService = scanRecord?.serviceUuids?.any { it.uuid == AppConstants.Mesh.Gatt.SERVICE_UUID } == true
if (!hasOurService) {
return
}
@@ -456,9 +450,9 @@ class BluetoothGattClientManager(
override fun onServicesDiscovered(gatt: BluetoothGatt, status: Int) {
if (status == BluetoothGatt.GATT_SUCCESS) {
val service = gatt.getService(SERVICE_UUID)
val service = gatt.getService(AppConstants.Mesh.Gatt.SERVICE_UUID)
if (service != null) {
val characteristic = service.getCharacteristic(CHARACTERISTIC_UUID)
val characteristic = service.getCharacteristic(AppConstants.Mesh.Gatt.CHARACTERISTIC_UUID)
if (characteristic != null) {
connectionTracker.getDeviceConnection(deviceAddress)?.let { deviceConn ->
val updatedConn = deviceConn.copy(characteristic = characteristic)
@@ -467,7 +461,7 @@ class BluetoothGattClientManager(
}
gatt.setCharacteristicNotification(characteristic, true)
val descriptor = characteristic.getDescriptor(DESCRIPTOR_UUID)
val descriptor = characteristic.getDescriptor(AppConstants.Mesh.Gatt.DESCRIPTOR_UUID)
if (descriptor != null) {
descriptor.value = BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE
gatt.writeDescriptor(descriptor)
@@ -9,6 +9,7 @@ import android.content.Context
import android.os.ParcelUuid
import android.util.Log
import com.bitchat.android.protocol.BitchatPacket
import com.bitchat.android.util.AppConstants
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
@@ -28,10 +29,6 @@ class BluetoothGattServerManager(
companion object {
private const val TAG = "BluetoothGattServerManager"
// Use exact same UUIDs as iOS version
private val SERVICE_UUID = UUID.fromString("F47B5E2D-4A9E-4C5A-9B3F-8E1D2C3A4B5C")
private val CHARACTERISTIC_UUID = UUID.fromString("A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D")
private val DESCRIPTOR_UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
}
// Core Bluetooth components
@@ -223,7 +220,7 @@ class BluetoothGattServerManager(
return
}
if (characteristic.uuid == CHARACTERISTIC_UUID) {
if (characteristic.uuid == AppConstants.Mesh.Gatt.CHARACTERISTIC_UUID) {
Log.i(TAG, "Server: Received packet from ${device.address}, size: ${value.size} bytes")
val packet = BitchatPacket.fromBinaryData(value)
if (packet != null) {
@@ -297,7 +294,7 @@ class BluetoothGattServerManager(
// Create characteristic with notification support
characteristic = BluetoothGattCharacteristic(
CHARACTERISTIC_UUID,
AppConstants.Mesh.Gatt.CHARACTERISTIC_UUID,
BluetoothGattCharacteristic.PROPERTY_READ or
BluetoothGattCharacteristic.PROPERTY_WRITE or
BluetoothGattCharacteristic.PROPERTY_WRITE_NO_RESPONSE or
@@ -307,12 +304,12 @@ class BluetoothGattServerManager(
)
val descriptor = BluetoothGattDescriptor(
DESCRIPTOR_UUID,
AppConstants.Mesh.Gatt.DESCRIPTOR_UUID,
BluetoothGattDescriptor.PERMISSION_READ or BluetoothGattDescriptor.PERMISSION_WRITE
)
characteristic?.addDescriptor(descriptor)
val service = BluetoothGattService(SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
val service = BluetoothGattService(AppConstants.Mesh.Gatt.SERVICE_UUID, BluetoothGattService.SERVICE_TYPE_PRIMARY)
service.addCharacteristic(characteristic)
gattServer?.addService(service)
@@ -357,7 +354,7 @@ class BluetoothGattServerManager(
val settings = powerManager.getAdvertiseSettings()
val data = AdvertiseData.Builder()
.addServiceUuid(ParcelUuid(SERVICE_UUID))
.addServiceUuid(ParcelUuid(AppConstants.Mesh.Gatt.SERVICE_UUID))
.setIncludeTxPowerLevel(false)
.setIncludeDeviceName(false)
.build()
@@ -36,7 +36,7 @@ class BluetoothMeshService(private val context: Context) {
companion object {
private const val TAG = "BluetoothMeshService"
private const val MAX_TTL: UByte = 7u
private val MAX_TTL: UByte = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
}
// Core components - each handling specific responsibilities
@@ -698,7 +698,7 @@ class BluetoothMeshService(private val context: Context) {
timestamp = System.currentTimeMillis().toULong(),
payload = encrypted,
signature = null,
ttl = 7u
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
)
// Sign and send the encrypted packet
@@ -844,7 +844,7 @@ class BluetoothMeshService(private val context: Context) {
timestamp = System.currentTimeMillis().toULong(),
payload = encrypted,
signature = null,
ttl = 7u // Same TTL as iOS messageTTL
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS // Same TTL as iOS messageTTL
)
// Sign the packet before broadcasting
@@ -47,7 +47,7 @@ class BluetoothPacketBroadcaster(
companion object {
private const val TAG = "BluetoothPacketBroadcaster"
private const val CLEANUP_DELAY = 500L
private const val CLEANUP_DELAY = com.bitchat.android.util.AppConstants.Mesh.BROADCAST_CLEANUP_DELAY_MS
}
// Optional nickname resolver injected by higher layer (peerID -> nickname?)
@@ -22,10 +22,10 @@ class FragmentManager {
companion object {
private const val TAG = "FragmentManager"
// iOS values: 512 MTU threshold, 469 max fragment size (512 MTU - headers)
private const val FRAGMENT_SIZE_THRESHOLD = 512 // Matches iOS: if data.count > 512
private const val MAX_FRAGMENT_SIZE = 469 // Matches iOS: maxFragmentSize = 469
private const val FRAGMENT_TIMEOUT = 30000L // Matches iOS: 30 seconds cleanup
private const val CLEANUP_INTERVAL = 10000L // 10 seconds cleanup check
private const val FRAGMENT_SIZE_THRESHOLD = com.bitchat.android.util.AppConstants.Fragmentation.FRAGMENT_SIZE_THRESHOLD // Matches iOS: if data.count > 512
private const val MAX_FRAGMENT_SIZE = com.bitchat.android.util.AppConstants.Fragmentation.MAX_FRAGMENT_SIZE // Matches iOS: maxFragmentSize = 469
private const val FRAGMENT_TIMEOUT = com.bitchat.android.util.AppConstants.Fragmentation.FRAGMENT_TIMEOUT_MS // Matches iOS: 30 seconds cleanup
private const val CLEANUP_INTERVAL = com.bitchat.android.util.AppConstants.Fragmentation.CLEANUP_INTERVAL_MS // 10 seconds cleanup check
}
// Fragment storage - iOS equivalent: incomingFragments: [String: [Int: Data]]
@@ -180,8 +180,12 @@ class FragmentManager {
incomingFragments.remove(fragmentIDString)
fragmentMetadata.remove(fragmentIDString)
Log.d(TAG, "Successfully reassembled and decoded original packet of ${reassembledData.size} bytes")
return originalPacket
// Suppress re-broadcast of the reassembled packet by zeroing TTL.
// We already relayed the incoming fragments; setting TTL=0 ensures
// PacketRelayManager will skip relaying this reconstructed packet.
val suppressedTtlPacket = originalPacket.copy(ttl = 0u.toUByte())
Log.d(TAG, "Successfully reassembled original (${reassembledData.size} bytes); set TTL=0 to suppress relay")
return suppressedTtlPacket
} else {
val metadata = fragmentMetadata[fragmentIDString]
Log.e(TAG, "Failed to decode reassembled packet (type=${metadata?.first}, total=${metadata?.second})")
@@ -183,16 +183,16 @@ class MessageHandler(private val myPeerID: String, private val appContext: andro
}
// Create NOISE_ENCRYPTED packet exactly like iOS
val packet = BitchatPacket(
version = 1u,
type = MessageType.NOISE_ENCRYPTED.value,
senderID = hexStringToByteArray(myPeerID),
recipientID = hexStringToByteArray(senderPeerID),
timestamp = System.currentTimeMillis().toULong(),
payload = encryptedPayload,
signature = null,
ttl = 7u // Same TTL as iOS messageTTL
)
val packet = BitchatPacket(
version = 1u,
type = MessageType.NOISE_ENCRYPTED.value,
senderID = hexStringToByteArray(myPeerID),
recipientID = hexStringToByteArray(senderPeerID),
timestamp = System.currentTimeMillis().toULong(),
payload = encryptedPayload,
signature = null,
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS // Same TTL as iOS messageTTL
)
delegate?.sendPacket(packet)
Log.d(TAG, "📤 Sent delivery ACK to $senderPeerID for message $messageID")
@@ -210,6 +210,14 @@ class MessageHandler(private val myPeerID: String, private val appContext: andro
val peerID = routed.peerID ?: "unknown"
if (peerID == myPeerID) return false
// Ignore stale announcements older than STALE_PEER_TIMEOUT
val now = System.currentTimeMillis()
val age = now - packet.timestamp.toLong()
if (age > com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS) {
Log.w(TAG, "Ignoring stale ANNOUNCE from ${peerID.take(8)} (age=${age}ms > ${com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS}ms)")
return false
}
// Try to decode as iOS-compatible IdentityAnnouncement with TLV format
val announcement = IdentityAnnouncement.decode(packet.payload)
@@ -317,7 +325,7 @@ class MessageHandler(private val myPeerID: String, private val appContext: andro
timestamp = System.currentTimeMillis().toULong(),
payload = response,
signature = null,
ttl = 7u // Same TTL as iOS
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS // Same TTL as iOS
)
delegate?.sendPacket(responsePacket)
@@ -67,9 +67,10 @@ class PeerManager {
companion object {
private const val TAG = "PeerManager"
private const val STALE_PEER_TIMEOUT = 180000L // 3 minutes (same as iOS)
private const val CLEANUP_INTERVAL = 60000L // 1 minute
}
// Centralized timeout from AppConstants
private val stalePeerTimeoutMs: Long = com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS
// Peer tracking data - enhanced with verification status
private val peers = ConcurrentHashMap<String, PeerInfo>() // peerID -> PeerInfo
@@ -299,7 +300,7 @@ class PeerManager {
fun isPeerActive(peerID: String): Boolean {
val info = peers[peerID] ?: return false
val now = System.currentTimeMillis()
return (now - info.lastSeen) <= STALE_PEER_TIMEOUT && info.isConnected
return (now - info.lastSeen) <= stalePeerTimeoutMs && info.isConnected
}
/**
@@ -328,7 +329,7 @@ class PeerManager {
*/
fun getActivePeerIDs(): List<String> {
val now = System.currentTimeMillis()
return peers.filterValues { (now - it.lastSeen) <= STALE_PEER_TIMEOUT && it.isConnected }
return peers.filterValues { (now - it.lastSeen) <= stalePeerTimeoutMs && it.isConnected }
.keys
.toList()
.sorted()
@@ -414,7 +415,7 @@ class PeerManager {
private fun startPeriodicCleanup() {
managerScope.launch {
while (isActive) {
delay(CLEANUP_INTERVAL)
delay(com.bitchat.android.util.AppConstants.Mesh.PEER_CLEANUP_INTERVAL_MS)
cleanupStalePeers()
}
}
@@ -426,7 +427,7 @@ class PeerManager {
private fun cleanupStalePeers() {
val now = System.currentTimeMillis()
val peersToRemove = peers.filterValues { (now - it.lastSeen) > STALE_PEER_TIMEOUT }
val peersToRemove = peers.filterValues { (now - it.lastSeen) > stalePeerTimeoutMs }
.keys
.toList()
@@ -21,22 +21,22 @@ class PowerManager(private val context: Context) {
private const val TAG = "PowerManager"
// Battery thresholds
private const val CRITICAL_BATTERY = 10
private const val LOW_BATTERY = 20
private const val MEDIUM_BATTERY = 50
private const val CRITICAL_BATTERY = com.bitchat.android.util.AppConstants.Power.CRITICAL_BATTERY_PERCENT
private const val LOW_BATTERY = com.bitchat.android.util.AppConstants.Power.LOW_BATTERY_PERCENT
private const val MEDIUM_BATTERY = com.bitchat.android.util.AppConstants.Power.MEDIUM_BATTERY_PERCENT
// Scan duty cycle periods (ms)
private const val SCAN_ON_DURATION_NORMAL = 8000L // 8 seconds on
private const val SCAN_OFF_DURATION_NORMAL = 2000L // 2 seconds off
private const val SCAN_ON_DURATION_POWER_SAVE = 2000L // 2 seconds on
private const val SCAN_OFF_DURATION_POWER_SAVE = 8000L // 8 seconds off
private const val SCAN_ON_DURATION_ULTRA_LOW = 1000L // 1 second on
private const val SCAN_OFF_DURATION_ULTRA_LOW = 10000L // 10 seconds off
private const val SCAN_ON_DURATION_NORMAL = com.bitchat.android.util.AppConstants.Power.SCAN_ON_DURATION_NORMAL_MS // 8 seconds on
private const val SCAN_OFF_DURATION_NORMAL = com.bitchat.android.util.AppConstants.Power.SCAN_OFF_DURATION_NORMAL_MS // 2 seconds off
private const val SCAN_ON_DURATION_POWER_SAVE = com.bitchat.android.util.AppConstants.Power.SCAN_ON_DURATION_POWER_SAVE_MS // 2 seconds on
private const val SCAN_OFF_DURATION_POWER_SAVE = com.bitchat.android.util.AppConstants.Power.SCAN_OFF_DURATION_POWER_SAVE_MS // 8 seconds off
private const val SCAN_ON_DURATION_ULTRA_LOW = com.bitchat.android.util.AppConstants.Power.SCAN_ON_DURATION_ULTRA_LOW_MS // 1 second on
private const val SCAN_OFF_DURATION_ULTRA_LOW = com.bitchat.android.util.AppConstants.Power.SCAN_OFF_DURATION_ULTRA_LOW_MS // 10 seconds off
// Connection limits
private const val MAX_CONNECTIONS_NORMAL = 8
private const val MAX_CONNECTIONS_POWER_SAVE = 4
private const val MAX_CONNECTIONS_ULTRA_LOW = 2
private const val MAX_CONNECTIONS_NORMAL = com.bitchat.android.util.AppConstants.Power.MAX_CONNECTIONS_NORMAL
private const val MAX_CONNECTIONS_POWER_SAVE = com.bitchat.android.util.AppConstants.Power.MAX_CONNECTIONS_POWER_SAVE
private const val MAX_CONNECTIONS_ULTRA_LOW = com.bitchat.android.util.AppConstants.Power.MAX_CONNECTIONS_ULTRA_LOW
}
enum class PowerMode {
@@ -19,10 +19,10 @@ class SecurityManager(private val encryptionService: EncryptionService, private
companion object {
private const val TAG = "SecurityManager"
private const val MESSAGE_TIMEOUT = 300000L // 5 minutes (same as iOS)
private const val CLEANUP_INTERVAL = 300000L // 5 minutes
private const val MAX_PROCESSED_MESSAGES = 10000
private const val MAX_PROCESSED_KEY_EXCHANGES = 1000
private const val MESSAGE_TIMEOUT = com.bitchat.android.util.AppConstants.Security.MESSAGE_TIMEOUT_MS // 5 minutes (same as iOS)
private const val CLEANUP_INTERVAL = com.bitchat.android.util.AppConstants.Security.CLEANUP_INTERVAL_MS // 5 minutes
private const val MAX_PROCESSED_MESSAGES = com.bitchat.android.util.AppConstants.Security.MAX_PROCESSED_MESSAGES
private const val MAX_PROCESSED_KEY_EXCHANGES = com.bitchat.android.util.AppConstants.Security.MAX_PROCESSED_KEY_EXCHANGES
}
// Security tracking
@@ -16,10 +16,10 @@ class StoreForwardManager {
companion object {
private const val TAG = "StoreForwardManager"
private const val MESSAGE_CACHE_TIMEOUT = 43200000L // 12 hours for regular peers
private const val MAX_CACHED_MESSAGES = 100 // For regular peers
private const val MAX_CACHED_MESSAGES_FAVORITES = 1000 // For favorites
private const val CLEANUP_INTERVAL = 600000L // 10 minutes
private const val MESSAGE_CACHE_TIMEOUT = com.bitchat.android.util.AppConstants.StoreForward.MESSAGE_CACHE_TIMEOUT_MS // 12 hours for regular peers
private const val MAX_CACHED_MESSAGES = com.bitchat.android.util.AppConstants.StoreForward.MAX_CACHED_MESSAGES // For regular peers
private const val MAX_CACHED_MESSAGES_FAVORITES = com.bitchat.android.util.AppConstants.StoreForward.MAX_CACHED_MESSAGES_FAVORITES // For favorites
private const val CLEANUP_INTERVAL = com.bitchat.android.util.AppConstants.StoreForward.CLEANUP_INTERVAL_MS // 10 minutes
}
/**
@@ -29,11 +29,11 @@ import java.util.concurrent.atomic.AtomicLong
*/
object TorManager {
private const val TAG = "TorManager"
private const val DEFAULT_SOCKS_PORT = 9060
private const val RESTART_DELAY_MS = 2000L // 2 seconds between stop/start
private const val INACTIVITY_TIMEOUT_MS = 5000L // 5 seconds of no activity before restart
private const val MAX_RETRY_ATTEMPTS = 5
private const val STOP_TIMEOUT_MS = 7000L
private const val DEFAULT_SOCKS_PORT = com.bitchat.android.util.AppConstants.Tor.DEFAULT_SOCKS_PORT
private const val RESTART_DELAY_MS = com.bitchat.android.util.AppConstants.Tor.RESTART_DELAY_MS // 2 seconds between stop/start
private const val INACTIVITY_TIMEOUT_MS = com.bitchat.android.util.AppConstants.Tor.INACTIVITY_TIMEOUT_MS // 5 seconds of no activity before restart
private const val MAX_RETRY_ATTEMPTS = com.bitchat.android.util.AppConstants.Tor.MAX_RETRY_ATTEMPTS
private const val STOP_TIMEOUT_MS = com.bitchat.android.util.AppConstants.Tor.STOP_TIMEOUT_MS
private val appScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
@@ -24,8 +24,8 @@ class NoiseEncryptionService(private val context: Context) {
private const val TAG = "NoiseEncryptionService"
// Session limits for performance and security
private const val REKEY_TIME_LIMIT = 3600000L // 1 hour (same as iOS)
private const val REKEY_MESSAGE_LIMIT = 1000L // 1k messages (matches iOS) (same as iOS)
private const val REKEY_TIME_LIMIT = com.bitchat.android.util.AppConstants.Noise.REKEY_TIME_LIMIT_MS // 1 hour (same as iOS)
private const val REKEY_MESSAGE_LIMIT = com.bitchat.android.util.AppConstants.Noise.REKEY_MESSAGE_LIMIT_ENCRYPTION // 1k messages (matches iOS) (same as iOS)
}
// Static identity key (persistent across app restarts) - loaded from secure storage
@@ -25,8 +25,8 @@ class NoiseSession(
private const val PROTOCOL_NAME = "Noise_XX_25519_ChaChaPoly_SHA256"
// Rekey thresholds (same as iOS)
private const val REKEY_TIME_LIMIT = 3600000L // 1 hour
private const val REKEY_MESSAGE_LIMIT = 10000L // 10k messages
private const val REKEY_TIME_LIMIT = com.bitchat.android.util.AppConstants.Noise.REKEY_TIME_LIMIT_MS // 1 hour
private const val REKEY_MESSAGE_LIMIT = com.bitchat.android.util.AppConstants.Noise.REKEY_MESSAGE_LIMIT_SESSION // 10k messages
// XX Pattern Message Sizes (exactly matching iOS implementation)
private const val XX_MESSAGE_1_SIZE = 32 // -> e (ephemeral key only)
@@ -34,13 +34,13 @@ class NoiseSession(
private const val XX_MESSAGE_3_SIZE = 48 // -> s, se (encrypted static key)
// Maximum payload size for safety
private const val MAX_PAYLOAD_SIZE = 256
private const val MAX_PAYLOAD_SIZE = com.bitchat.android.util.AppConstants.Noise.MAX_PAYLOAD_SIZE_BYTES
// Constants for replay protection (matching iOS implementation)
private const val NONCE_SIZE_BYTES = 4
private const val REPLAY_WINDOW_SIZE = 1024
private const val REPLAY_WINDOW_BYTES = REPLAY_WINDOW_SIZE / 8 // 128 bytes
private const val HIGH_NONCE_WARNING_THRESHOLD = 1_000_000_000L
private const val HIGH_NONCE_WARNING_THRESHOLD = com.bitchat.android.util.AppConstants.Noise.HIGH_NONCE_WARNING_THRESHOLD
// MARK: - Sliding Window Replay Protection
@@ -0,0 +1,63 @@
package com.bitchat.android.nostr
import android.content.Context
import android.util.Log
/**
* Initializer for LocationNotesManager with all dependencies
* Extracts initialization logic from MainActivity for better separation of concerns
*/
object LocationNotesInitializer {
private const val TAG = "LocationNotesInitializer"
/**
* Initialize LocationNotesManager with all required dependencies
*
* @param context Application context
* @return true if initialization succeeded, false otherwise
*/
fun initialize(context: Context): Boolean {
return try {
LocationNotesManager.getInstance().initialize(
relayManager = { NostrRelayManager.getInstance(context) },
subscribe = { filter, id, handler ->
// CRITICAL FIX: Extract geohash properly from filter using getGeohash() method
val geohashFromFilter = filter.getGeohash() ?: run {
Log.e(TAG, "❌ Cannot extract geohash from filter for location notes")
return@initialize id // Return subscription ID even on error
}
Log.d(TAG, "📍 Location Notes subscribing to geohash: $geohashFromFilter")
NostrRelayManager.getInstance(context).subscribeForGeohash(
geohash = geohashFromFilter,
filter = filter,
id = id,
handler = handler,
includeDefaults = true,
nRelays = 5
)
},
unsubscribe = { id ->
NostrRelayManager.getInstance(context).unsubscribe(id)
},
sendEvent = { event, relayUrls ->
if (relayUrls != null) {
NostrRelayManager.getInstance(context).sendEvent(event, relayUrls)
} else {
NostrRelayManager.getInstance(context).sendEvent(event)
}
},
deriveIdentity = { geohash ->
NostrIdentityBridge.deriveIdentity(geohash, context)
}
)
Log.d(TAG, "✅ Location Notes Manager initialized")
true
} catch (e: Exception) {
Log.e(TAG, "❌ Failed to initialize Location Notes Manager: ${e.message}", e)
false
}
}
}
@@ -0,0 +1,468 @@
package com.bitchat.android.nostr
import android.util.Log
import androidx.annotation.MainThread
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import kotlinx.coroutines.*
/**
* Manages location notes (kind=1 text notes with geohash tags)
* iOS-compatible implementation with LiveData for Android UI binding
*/
@MainThread
class LocationNotesManager private constructor() {
companion object {
private const val TAG = "LocationNotesManager"
private const val MAX_NOTES_IN_MEMORY = 500
@Volatile
private var INSTANCE: LocationNotesManager? = null
fun getInstance(): LocationNotesManager {
return INSTANCE ?: synchronized(this) {
INSTANCE ?: LocationNotesManager().also { INSTANCE = it }
}
}
}
/**
* Note data class matching iOS implementation
*/
data class Note(
val id: String,
val pubkey: String,
val content: String,
val createdAt: Int,
val nickname: String?
) {
/**
* Display name for the note - matches iOS exactly
* Format: "nickname#abcd" or "anon#abcd" where abcd is last 4 chars of pubkey
*/
val displayName: String
get() {
val suffix = pubkey.takeLast(4)
val nick = nickname?.trim()
return if (!nick.isNullOrEmpty()) {
"$nick#$suffix"
} else {
"anon#$suffix"
}
}
}
/**
* Manager state enum
*/
enum class State {
IDLE,
LOADING,
READY,
NO_RELAYS
}
// Published state (LiveData for Android)
private val _notes = MutableLiveData<List<Note>>(emptyList())
val notes: LiveData<List<Note>> = _notes
private val _geohash = MutableLiveData<String?>(null)
val geohash: LiveData<String?> = _geohash
private val _initialLoadComplete = MutableLiveData(false)
val initialLoadComplete: LiveData<Boolean> = _initialLoadComplete
private val _state = MutableLiveData(State.IDLE)
val state: LiveData<State> = _state
private val _errorMessage = MutableLiveData<String?>(null)
val errorMessage: LiveData<String?> = _errorMessage
// Private state
private var subscriptionIDs: MutableMap<String, String> = mutableMapOf()
private val noteIDs = mutableSetOf<String>() // For deduplication
private var subscribedGeohashes: Set<String> = emptySet()
// Dependencies (injected via setters for flexibility)
private var relayLookup: (() -> NostrRelayManager)? = null
private var subscribeFunc: ((NostrFilter, String, (NostrEvent) -> Unit) -> String)? = null
private var unsubscribeFunc: ((String) -> Unit)? = null
private var sendEventFunc: ((NostrEvent, List<String>?) -> Unit)? = null
private var deriveIdentityFunc: ((String) -> NostrIdentity)? = null
// Coroutine scope for background operations
private val scope = CoroutineScope(Dispatchers.Main + SupervisorJob())
/**
* Initialize dependencies
*/
fun initialize(
relayManager: () -> NostrRelayManager,
subscribe: (NostrFilter, String, (NostrEvent) -> Unit) -> String,
unsubscribe: (String) -> Unit,
sendEvent: (NostrEvent, List<String>?) -> Unit,
deriveIdentity: (String) -> NostrIdentity
) {
this.relayLookup = relayManager
this.subscribeFunc = subscribe
this.unsubscribeFunc = unsubscribe
this.sendEventFunc = sendEvent
this.deriveIdentityFunc = deriveIdentity
}
/**
* Set geohash and start subscription
* iOS: Validates building-level precision (8 characters)
*/
fun setGeohash(newGeohash: String) {
val normalized = newGeohash.lowercase()
if (_geohash.value == normalized) {
Log.d(TAG, "Geohash unchanged, skipping: $normalized")
return
}
// Validate geohash (building-level precision: 8 chars) - matches iOS
if (!isValidBuildingGeohash(normalized)) {
Log.w(TAG, "LocationNotesManager: rejecting invalid geohash '$normalized' (expected 8 valid base32 chars)")
return
}
Log.d(TAG, "Setting geohash: $normalized")
// Cancel existing subscription
cancel()
// Set loading state before clearing to prevent empty state flicker (iOS pattern)
_state.value = State.LOADING
_initialLoadComplete.value = false
_errorMessage.value = null
// Clear notes
_notes.value = emptyList()
noteIDs.clear()
_geohash.value = normalized
// Compute target geohashes: center + neighbors (±1)
val neighbors = try {
com.bitchat.android.geohash.Geohash.neighborsSamePrecision(normalized)
} catch (_: Exception) { emptySet() }
subscribedGeohashes = (neighbors + normalized).toSet()
// Start new subscriptions for all cells
subscribeAll()
}
/**
* Validate building-level geohash (precision 8) - matches iOS Geohash.isValidBuildingGeohash
*/
private fun isValidBuildingGeohash(geohash: String): Boolean {
if (geohash.length != 8) return false
val base32Chars = "0123456789bcdefghjkmnpqrstuvwxyz"
return geohash.all { it in base32Chars }
}
/**
* Refresh notes for current geohash
*/
fun refresh() {
val currentGeohash = _geohash.value
if (currentGeohash == null) {
Log.w(TAG, "Cannot refresh - no geohash set")
return
}
Log.d(TAG, "Refreshing notes for geohash: $currentGeohash")
// Cancel and restart subscriptions for current ±1 set
cancel()
_notes.value = emptyList()
noteIDs.clear()
_initialLoadComplete.value = false
// Rebuild subscribedGeohashes and resubscribe
val neighbors = try {
com.bitchat.android.geohash.Geohash.neighborsSamePrecision(currentGeohash)
} catch (_: Exception) { emptySet() }
subscribedGeohashes = (neighbors + currentGeohash).toSet()
subscribeAll()
}
/**
* Send a new location note
*/
fun send(content: String, nickname: String?) {
val currentGeohash = _geohash.value
if (currentGeohash == null) {
Log.w(TAG, "Cannot send note - no geohash set")
_errorMessage.value = "No location set"
return
}
val trimmed = content.trim()
if (trimmed.isEmpty()) {
return
}
// CRITICAL FIX: Get geo-specific relays for sending (matching iOS pattern)
// iOS: let relays = dependencies.relayLookup(geohash, TransportConfig.nostrGeoRelayCount)
val relays = try {
com.bitchat.android.nostr.RelayDirectory.closestRelaysForGeohash(currentGeohash, 5)
} catch (e: Exception) {
Log.e(TAG, "Failed to lookup relays for geohash $currentGeohash: ${e.message}")
emptyList()
}
// Check if we have relays (iOS pattern: guard !relays.isEmpty())
if (relays.isEmpty()) {
Log.w(TAG, "Send blocked - no geo relays for geohash: $currentGeohash")
_state.value = State.NO_RELAYS
_errorMessage.value = "No relays available"
return
}
val deriveIdentity = deriveIdentityFunc
if (deriveIdentity == null) {
Log.e(TAG, "Cannot send note - deriveIdentity not initialized")
_errorMessage.value = "Not initialized"
return
}
Log.d(TAG, "Sending note to geohash: $currentGeohash via ${relays.size} geo relays")
scope.launch {
try {
val identity = withContext(Dispatchers.IO) {
deriveIdentity(currentGeohash)
}
val event = withContext(Dispatchers.IO) {
NostrProtocol.createGeohashTextNote(
content = trimmed,
geohash = currentGeohash,
senderIdentity = identity,
nickname = nickname
)
}
// Optimistic local echo - add note immediately to UI
val localNote = Note(
id = event.id,
pubkey = event.pubkey,
content = trimmed,
createdAt = event.createdAt,
nickname = nickname
)
if (!noteIDs.contains(event.id)) {
noteIDs.add(event.id)
val currentNotes = _notes.value ?: emptyList()
_notes.value = (currentNotes + localNote).sortedByDescending { it.createdAt }
// Trim if exceeds max
if (noteIDs.size > MAX_NOTES_IN_MEMORY) {
trimOldestNotes()
}
}
// CRITICAL FIX: Send to geo-specific relays (matching iOS pattern)
// iOS: dependencies.sendEvent(event, relays)
withContext(Dispatchers.IO) {
sendEventFunc?.invoke(event, relays)
}
Log.d(TAG, "✅ Note sent successfully to ${relays.size} geo relays: ${event.id.take(16)}...")
// Clear any error messages on successful send
_errorMessage.value = null
_state.value = State.READY
} catch (e: Exception) {
Log.e(TAG, "Failed to send note: ${e.message}")
_errorMessage.value = "Failed to send: ${e.message}"
}
}
}
/**
* Subscribe to location notes for current geohash
*/
private fun subscribeAll() {
val currentGeohash = _geohash.value
if (currentGeohash == null) {
Log.w(TAG, "Cannot subscribe - no geohash set")
_state.value = State.IDLE
return
}
val subscribe = subscribeFunc
if (subscribe == null) {
Log.e(TAG, "Cannot subscribe - subscribe function not initialized; will retry shortly")
_state.value = State.LOADING
// Retry a few times in case initialization is racing the sheet open
scope.launch {
var attempts = 0
while (attempts < 10 && subscribeFunc == null) {
delay(300)
attempts++
}
val subNow = subscribeFunc
if (subNow != null) {
// Try again now that dependencies are ready
subscribeAll()
} else {
// Give UI a chance to show empty state rather than spinner forever
if (!_initialLoadComplete.value!!) {
_initialLoadComplete.value = true
_state.value = State.READY
}
}
}
return
}
_state.value = State.LOADING
// Subscribe for each geohash in the ±1 set
subscribedGeohashes.forEach { gh ->
val filter = NostrFilter.geohashNotes(
geohash = gh,
since = null,
limit = 200
)
val subId = "location-notes-$gh"
Log.d(TAG, "📡 Subscribing to location notes: $subId")
try {
val id = subscribe(filter, subId) { event -> handleEvent(event) }
subscriptionIDs[gh] = id
} catch (e: Exception) {
Log.e(TAG, "Failed to subscribe for $gh: ${e.message}")
}
}
// Mark initial load complete after brief delay to allow relay responses
scope.launch {
delay(2000) // Wait 2 seconds for initial batch
if (!_initialLoadComplete.value!!) {
_initialLoadComplete.value = true
_state.value = State.READY
Log.d(TAG, "Initial load complete for geohash: $currentGeohash (${noteIDs.size} notes)")
}
}
}
/**
* Handle incoming event from subscription
*/
private fun handleEvent(event: NostrEvent) {
// Validate event
if (event.kind != NostrKind.TEXT_NOTE) {
Log.v(TAG, "Ignoring non-text-note event: kind=${event.kind}")
return
}
// Check for geohash tag
val geohashTag = event.tags.firstOrNull { it.size >= 2 && it[0] == "g" }
if (geohashTag == null) {
Log.v(TAG, "Ignoring event without geohash tag: ${event.id.take(16)}...")
return
}
// Check if matches current geohash
val eventGeohash = geohashTag[1]
if (!subscribedGeohashes.contains(eventGeohash)) {
Log.v(TAG, "Ignoring event for non-subscribed geohash: $eventGeohash")
return
}
// Deduplicate
if (noteIDs.contains(event.id)) {
return
}
// Extract nickname from tags
val nicknameTag = event.tags.firstOrNull { it.size >= 2 && it[0] == "n" }
val nickname = nicknameTag?.get(1)
// Create note
val note = Note(
id = event.id,
pubkey = event.pubkey,
content = event.content,
createdAt = event.createdAt,
nickname = nickname
)
// Add to collection
noteIDs.add(event.id)
val currentNotes = _notes.value ?: emptyList()
_notes.value = (currentNotes + note).sortedByDescending { it.createdAt }
Log.d(TAG, "📥 Added note: ${note.displayName} - ${note.content.take(50)}")
// Trim if exceeds max
if (noteIDs.size > MAX_NOTES_IN_MEMORY) {
trimOldestNotes()
}
// Update state
if (!_initialLoadComplete.value!!) {
_initialLoadComplete.value = true
}
_state.value = State.READY
}
/**
* Trim oldest notes to stay within memory limit
*/
private fun trimOldestNotes() {
val currentNotes = _notes.value ?: return
if (currentNotes.size <= MAX_NOTES_IN_MEMORY) return
val trimmed = currentNotes.sortedByDescending { it.createdAt }.take(MAX_NOTES_IN_MEMORY)
_notes.value = trimmed
// Update note IDs set
noteIDs.clear()
noteIDs.addAll(trimmed.map { it.id })
Log.d(TAG, "Trimmed notes to $MAX_NOTES_IN_MEMORY (removed ${currentNotes.size - trimmed.size})")
}
/**
* Clear error message - matches iOS clearError()
*/
fun clearError() {
_errorMessage.value = null
}
/**
* Cancel subscription and clear state
*/
fun cancel() {
if (subscriptionIDs.isNotEmpty()) {
subscriptionIDs.values.forEach { subId ->
try {
Log.d(TAG, "🚫 Canceling subscription: $subId")
unsubscribeFunc?.invoke(subId)
} catch (_: Exception) { }
}
subscriptionIDs.clear()
}
subscribedGeohashes = emptySet()
_state.value = State.IDLE
}
/**
* Cleanup resources
*/
fun cleanup() {
cancel()
scope.cancel()
_notes.value = emptyList()
noteIDs.clear()
_geohash.value = null
_initialLoadComplete.value = false
_errorMessage.value = null
}
}
@@ -46,7 +46,7 @@ object NostrEmbeddedBitChat {
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
signature = null,
ttl = 7u
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
)
val data = packet.toBinaryData() ?: return null
@@ -86,7 +86,7 @@ object NostrEmbeddedBitChat {
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
signature = null,
ttl = 7u
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
)
val data = packet.toBinaryData() ?: return null
@@ -123,7 +123,7 @@ object NostrEmbeddedBitChat {
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
signature = null,
ttl = 7u
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
)
val data = packet.toBinaryData() ?: return null
@@ -158,7 +158,7 @@ object NostrEmbeddedBitChat {
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
signature = null,
ttl = 7u
ttl = com.bitchat.android.util.AppConstants.MESSAGE_TTL_HOPS
)
val data = packet.toBinaryData() ?: return null
@@ -22,7 +22,7 @@ class NostrEventDeduplicator(
) {
companion object {
private const val TAG = "NostrDeduplicator"
private const val DEFAULT_CAPACITY = 10000
private const val DEFAULT_CAPACITY = com.bitchat.android.util.AppConstants.Nostr.DEFAULT_DEDUP_CAPACITY
@Volatile
private var INSTANCE: NostrEventDeduplicator? = null
@@ -55,6 +55,18 @@ data class NostrFilter(
)
}
/**
* Create filter for geohash-scoped text notes (kind=1 with g tag)
*/
fun geohashNotes(geohash: String, since: Long? = null, limit: Int = 200): NostrFilter {
return NostrFilter(
kinds = listOf(NostrKind.TEXT_NOTE),
since = since?.let { (it / 1000).toInt() },
tagFilters = mapOf("g" to listOf(geohash)),
limit = limit
)
}
/**
* Create filter for specific event IDs
*/
@@ -193,4 +205,12 @@ data class NostrFilter(
return "NostrFilter(${parts.joinToString(", ")})"
}
/**
* Get geohash value from g tag filter (if present)
* Returns the first geohash in the filter or null if none
*/
fun getGeohash(): String? {
return tagFilters?.get("g")?.firstOrNull()
}
}
@@ -90,6 +90,34 @@ object NostrProtocol {
}
}
/**
* Create a geohash-scoped text note (kind 1) with optional nickname
* This creates a persistent text note that can be retrieved later
*/
suspend fun createGeohashTextNote(
content: String,
geohash: String,
senderIdentity: NostrIdentity,
nickname: String? = null
): NostrEvent = withContext(Dispatchers.Default) {
val tags = mutableListOf<List<String>>()
tags.add(listOf("g", geohash))
if (!nickname.isNullOrEmpty()) {
tags.add(listOf("n", nickname))
}
val event = NostrEvent(
pubkey = senderIdentity.publicKeyHex,
createdAt = (System.currentTimeMillis() / 1000).toInt(),
kind = NostrKind.TEXT_NOTE,
tags = tags,
content = content
)
return@withContext senderIdentity.signEvent(event)
}
/**
* Create a geohash-scoped ephemeral public message (kind 20000)
* Includes Proof of Work mining if enabled in settings
@@ -41,10 +41,10 @@ class NostrRelayManager private constructor() {
)
// Exponential backoff configuration (same as iOS)
private const val INITIAL_BACKOFF_INTERVAL = 1000L // 1 second
private const val MAX_BACKOFF_INTERVAL = 300000L // 5 minutes
private const val BACKOFF_MULTIPLIER = 2.0
private const val MAX_RECONNECT_ATTEMPTS = 10
private const val INITIAL_BACKOFF_INTERVAL = com.bitchat.android.util.AppConstants.Nostr.INITIAL_BACKOFF_INTERVAL_MS // 1 second
private const val MAX_BACKOFF_INTERVAL = com.bitchat.android.util.AppConstants.Nostr.MAX_BACKOFF_INTERVAL_MS // 5 minutes
private const val BACKOFF_MULTIPLIER = com.bitchat.android.util.AppConstants.Nostr.BACKOFF_MULTIPLIER
private const val MAX_RECONNECT_ATTEMPTS = com.bitchat.android.util.AppConstants.Nostr.MAX_RECONNECT_ATTEMPTS
// Track gift-wraps we initiated for logging
private val pendingGiftWrapIDs = ConcurrentHashMap.newKeySet<String>()
@@ -111,7 +111,7 @@ class NostrRelayManager private constructor() {
// Subscription validation timer
private var subscriptionValidationJob: Job? = null
private val SUBSCRIPTION_VALIDATION_INTERVAL = 30000L // 30 seconds
private val SUBSCRIPTION_VALIDATION_INTERVAL = com.bitchat.android.util.AppConstants.Nostr.SUBSCRIPTION_VALIDATION_INTERVAL_MS // 30 seconds
// OkHttp client for WebSocket connections (via provider to honor Tor)
private val httpClient: OkHttpClient
@@ -19,7 +19,7 @@ class NostrTransport(
companion object {
private const val TAG = "NostrTransport"
private const val READ_ACK_INTERVAL = 350L // ~3 per second (0.35s interval like iOS)
private const val READ_ACK_INTERVAL = com.bitchat.android.util.AppConstants.Nostr.READ_ACK_INTERVAL_MS // ~3 per second (0.35s interval like iOS)
@Volatile
private var INSTANCE: NostrTransport? = null
@@ -102,8 +102,8 @@ private fun BatteryOptimizationEnabledContent(
.padding(bottom = 16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "bitchat",
Text(
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -112,8 +112,8 @@ private fun BatteryOptimizationEnabledContent(
color = colorScheme.onBackground
)
Text(
text = "battery optimization detected",
Text(
text = stringResource(R.string.battery_optimization_detected_title),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.7f)
@@ -136,22 +136,22 @@ private fun BatteryOptimizationEnabledContent(
) {
Icon(
imageVector = Icons.Filled.Power,
contentDescription = "Battery Optimization",
contentDescription = stringResource(R.string.cd_battery_optimization),
tint = colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
.size(20.dp)
)
Column {
Text(
text = "Battery Optimization Enabled",
Text(
text = stringResource(R.string.battery_optimization_enabled_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "bitchat needs to run in the background to maintain mesh connections. battery optimization can interrupt these connections.",
Text(
text = stringResource(R.string.battery_optimization_explanation_short),
style = MaterialTheme.typography.bodySmall,
color = colorScheme.onBackground.copy(alpha = 0.8f)
)
@@ -176,22 +176,22 @@ private fun BatteryOptimizationEnabledContent(
) {
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "Benefits",
contentDescription = stringResource(R.string.cd_benefits),
tint = colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
.size(20.dp)
)
Column {
Text(
text = "Benefits of Disabling",
Text(
text = stringResource(R.string.benefits_of_disabling),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "• reliable message delivery\n• maintains mesh connectivity\n• prevents connection drops",
Text(
text = stringResource(R.string.battery_benefits_short),
style = MaterialTheme.typography.bodySmall,
color = colorScheme.onBackground.copy(alpha = 0.8f)
)
@@ -222,8 +222,8 @@ private fun BatteryOptimizationEnabledContent(
)
Spacer(modifier = Modifier.width(8.dp))
}
Text(
text = "Disable Battery Optimization",
Text(
text = stringResource(R.string.disable_battery_optimization),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -240,8 +240,8 @@ private fun BatteryOptimizationEnabledContent(
modifier = Modifier.weight(1f),
enabled = !isLoading
) {
Text(
text = "Check Again",
Text(
text = stringResource(R.string.check_again),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
)
@@ -256,8 +256,8 @@ private fun BatteryOptimizationEnabledContent(
modifier = Modifier.weight(1f),
enabled = !isLoading
) {
Text(
text = "Skip for Now",
Text(
text = stringResource(R.string.battery_optimization_skip),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
)
@@ -282,7 +282,7 @@ private fun BatteryOptimizationCheckingContent(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -291,8 +291,8 @@ private fun BatteryOptimizationCheckingContent(
color = colorScheme.onBackground
)
Text(
text = "battery optimization disabled",
Text(
text = stringResource(R.string.battery_optimization_disabled_title),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.7f)
@@ -312,15 +312,15 @@ private fun BatteryOptimizationCheckingContent(
Icon(
imageVector = Icons.Filled.BatteryStd,
contentDescription = "Checking Battery Optimization",
contentDescription = stringResource(R.string.cd_checking_battery_optimization),
modifier = Modifier
.size(64.dp)
.rotate(rotation),
tint = colorScheme.primary
)
Text(
text = "bitchat can run reliably in the background",
Text(
text = stringResource(R.string.battery_optimization_success_message),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.8f)
@@ -345,7 +345,7 @@ private fun BatteryOptimizationNotSupportedContent(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -355,7 +355,7 @@ private fun BatteryOptimizationNotSupportedContent(
)
Text(
text = "battery optimization not required",
text = stringResource(R.string.battery_optimization_not_required),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.7f)
@@ -364,13 +364,13 @@ private fun BatteryOptimizationNotSupportedContent(
Icon(
imageVector = Icons.Filled.CheckCircle,
contentDescription = "Battery Optimization Not Supported",
contentDescription = stringResource(R.string.cd_not_supported_battery_optimization),
modifier = Modifier.size(64.dp),
tint = colorScheme.primary
)
Text(
text = "your device doesn't require battery optimization settings. bitchat will run normally.",
text = stringResource(R.string.battery_optimization_not_supported_message),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.8f)
@@ -385,8 +385,8 @@ private fun BatteryOptimizationNotSupportedContent(
containerColor = colorScheme.primary
)
) {
Text(
text = "Continue",
Text(
text = stringResource(R.string.continue_btn),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -394,4 +394,4 @@ private fun BatteryOptimizationNotSupportedContent(
)
}
}
}
}
@@ -14,6 +14,8 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Screen shown when checking Bluetooth status or requesting Bluetooth enable
@@ -69,13 +71,13 @@ private fun BluetoothDisabledContent(
// Bluetooth icon - using Bluetooth outlined icon in app's green color
Icon(
imageVector = Icons.Outlined.Bluetooth,
contentDescription = "Bluetooth",
contentDescription = stringResource(R.string.cd_bluetooth),
modifier = Modifier.size(64.dp),
tint = Color(0xFF00C851) // App's main green color
)
Text(
text = "Bluetooth Required",
text = stringResource(R.string.bluetooth_required),
style = MaterialTheme.typography.headlineSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -95,8 +97,8 @@ private fun BluetoothDisabledContent(
modifier = Modifier.padding(16.dp),
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "bitchat needs Bluetooth to:",
Text(
text = stringResource(R.string.bluetooth_needs_for),
style = MaterialTheme.typography.bodyMedium.copy(
fontWeight = FontWeight.Medium,
color = colorScheme.onSurface
@@ -105,11 +107,8 @@ private fun BluetoothDisabledContent(
modifier = Modifier.fillMaxWidth()
)
Text(
text = "• Discover nearby users\n" +
"• Create mesh network connections\n" +
"• Send and receive messages\n" +
"• Work without internet or servers",
Text(
text = stringResource(R.string.bluetooth_needs_bullets),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.8f)
@@ -132,8 +131,8 @@ private fun BluetoothDisabledContent(
containerColor = Color(0xFF00C851) // App's main green color
)
) {
Text(
text = "Enable Bluetooth",
Text(
text = stringResource(R.string.enable_bluetooth),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -177,14 +176,14 @@ private fun BluetoothNotSupportedContent(
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Text(
text = "",
text = stringResource(R.string.warning_emoji),
style = MaterialTheme.typography.headlineLarge,
modifier = Modifier.padding(16.dp)
)
}
Text(
text = "Bluetooth Not Supported",
text = stringResource(R.string.bluetooth_not_supported),
style = MaterialTheme.typography.headlineSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -201,7 +200,7 @@ private fun BluetoothNotSupportedContent(
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Text(
text = "This device doesn't support Bluetooth Low Energy (BLE), which is required for bitchat to function.\n\nbitchat needs BLE to create mesh networks and communicate with nearby devices without internet.",
text = stringResource(R.string.bluetooth_unsupported_explanation),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface
@@ -222,7 +221,7 @@ private fun BluetoothCheckingContent(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -234,7 +233,7 @@ private fun BluetoothCheckingContent(
BluetoothLoadingIndicator()
Text(
text = "Checking Bluetooth status...",
text = stringResource(R.string.checking_bluetooth_status),
style = MaterialTheme.typography.bodyLarge.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -12,6 +12,8 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Loading screen shown during app initialization after permissions are granted
@@ -59,7 +61,7 @@ fun InitializingScreen(modifier: Modifier) {
) {
// App title
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -88,7 +90,7 @@ fun InitializingScreen(modifier: Modifier) {
horizontalArrangement = Arrangement.Center
) {
Text(
text = "Initializing mesh network",
text = stringResource(R.string.initializing_mesh_network),
style = MaterialTheme.typography.bodyLarge.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -98,7 +100,7 @@ fun InitializingScreen(modifier: Modifier) {
// Animated dots
dots.forEach { alpha ->
Text(
text = ".",
text = stringResource(R.string.dot),
style = MaterialTheme.typography.bodyLarge.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = alpha)
@@ -123,7 +125,7 @@ fun InitializingScreen(modifier: Modifier) {
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Setting up Bluetooth mesh networking...",
text = stringResource(R.string.setting_up_bluetooth),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.8f)
@@ -132,7 +134,7 @@ fun InitializingScreen(modifier: Modifier) {
)
Text(
text = "This should only take a few seconds",
text = stringResource(R.string.should_take_seconds),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.6f)
@@ -173,14 +175,14 @@ fun InitializationErrorScreen(
elevation = CardDefaults.cardElevation(defaultElevation = 4.dp)
) {
Text(
text = "⚠️",
text = stringResource(R.string.warning_emoji),
style = MaterialTheme.typography.headlineLarge,
modifier = Modifier.padding(16.dp)
)
}
Text(
text = "Setup Not Complete",
text = stringResource(R.string.setup_not_complete),
style = MaterialTheme.typography.headlineSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -216,7 +218,7 @@ fun InitializationErrorScreen(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Try Again",
text = stringResource(R.string.try_again),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -230,7 +232,7 @@ fun InitializationErrorScreen(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Open Settings",
text = stringResource(R.string.open_settings),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
),
@@ -15,6 +15,8 @@ import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Screen shown when checking location services status or requesting location services enable
@@ -70,13 +72,13 @@ private fun LocationDisabledContent(
// Location icon - using LocationOn outlined icon in app's green color
Icon(
imageVector = Icons.Outlined.LocationOn,
contentDescription = "Location Services",
contentDescription = stringResource(R.string.cd_location_services),
modifier = Modifier.size(64.dp),
tint = Color(0xFF00C851) // App's main green color
)
Text(
text = "Location Services Required",
text = stringResource(R.string.location_services_required),
style = MaterialTheme.typography.headlineSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -103,13 +105,13 @@ private fun LocationDisabledContent(
) {
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "Privacy",
contentDescription = stringResource(R.string.cd_privacy),
tint = Color(0xFF4CAF50),
modifier = Modifier.size(20.dp)
)
Spacer(modifier = Modifier.width(8.dp))
Text(
text = "Privacy First",
Text(
text = stringResource(R.string.privacy_first),
style = MaterialTheme.typography.bodyMedium.copy(
fontWeight = FontWeight.Bold,
color = colorScheme.onSurface
@@ -117,8 +119,8 @@ private fun LocationDisabledContent(
)
}
Text(
text = "bitchat does NOT track your location.\n\nLocation services are required for Bluetooth scanning and for the Geohash chat feature.",
Text(
text = stringResource(R.string.location_explanation),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.8f)
@@ -127,8 +129,8 @@ private fun LocationDisabledContent(
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "bitchat needs location services for:",
Text(
text = stringResource(R.string.location_needs_for),
style = MaterialTheme.typography.bodyMedium.copy(
fontWeight = FontWeight.Medium,
color = colorScheme.onSurface
@@ -137,11 +139,8 @@ private fun LocationDisabledContent(
modifier = Modifier.fillMaxWidth()
)
Text(
text = "• Bluetooth device scanning\n" +
"• Discovering nearby users on mesh network\n" +
"• Geohash chat feature\n" +
"• No tracking or location collection",
Text(
text = stringResource(R.string.location_needs_bullets),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.8f)
@@ -164,8 +163,8 @@ private fun LocationDisabledContent(
containerColor = Color(0xFF00C851) // App's main green color
)
) {
Text(
text = "Open Location Settings",
Text(
text = stringResource(R.string.open_location_settings),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -178,8 +177,8 @@ private fun LocationDisabledContent(
onClick = onRetry,
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "Check Again",
Text(
text = stringResource(R.string.check_again),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
),
@@ -202,13 +201,13 @@ private fun LocationNotAvailableContent(
// Error icon
Icon(
imageVector = Icons.Filled.ErrorOutline,
contentDescription = "Error",
contentDescription = stringResource(R.string.cd_error),
modifier = Modifier.size(64.dp),
tint = colorScheme.error
)
Text(
text = "Location Services Unavailable",
text = stringResource(R.string.location_services_unavailable),
style = MaterialTheme.typography.headlineSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -225,7 +224,7 @@ private fun LocationNotAvailableContent(
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
) {
Text(
text = "Location services are not available on this device. This is unusual as location services are standard on Android devices.\n\nbitchat needs location services for Bluetooth scanning to work properly (Android requirement). Without this, the app cannot discover nearby users.",
text = stringResource(R.string.location_unavailable_explanation),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface
@@ -246,7 +245,7 @@ private fun LocationCheckingContent(
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -258,7 +257,7 @@ private fun LocationCheckingContent(
LocationLoadingIndicator()
Text(
text = "Checking location services...",
text = stringResource(R.string.checking_location_services),
style = MaterialTheme.typography.bodyLarge.copy(
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -24,6 +24,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Permission explanation screen shown before requesting permissions
@@ -65,7 +67,7 @@ fun PermissionExplanationScreen(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = MaterialTheme.typography.headlineLarge.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -76,7 +78,7 @@ fun PermissionExplanationScreen(
}
Text(
text = "decentralized mesh messaging with end-to-end encryption",
text = stringResource(R.string.about_tagline),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.7f)
@@ -99,7 +101,7 @@ fun PermissionExplanationScreen(
) {
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "Privacy Protected",
contentDescription = stringResource(R.string.cd_privacy_protected),
tint = colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
@@ -107,16 +109,14 @@ fun PermissionExplanationScreen(
)
Column {
Text(
text = "Your Privacy is Protected",
text = stringResource(R.string.privacy_protected),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "• no tracking or data collection\n" +
"• Bluetooth mesh chats are fully offline\n" +
"• Geohash chats use the internet",
text = stringResource(R.string.privacy_bullets),
style = MaterialTheme.typography.bodySmall,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.8f)
@@ -128,7 +128,7 @@ fun PermissionExplanationScreen(
// Section header
Text(
text = "permissions",
text = stringResource(R.string.permissions_header),
style = MaterialTheme.typography.labelLarge,
color = colorScheme.onBackground.copy(alpha = 0.7f),
modifier = Modifier.padding(top = 8.dp, bottom = 8.dp)
@@ -163,7 +163,7 @@ fun PermissionExplanationScreen(
)
) {
Text(
text = "Grant Permissions",
text = stringResource(R.string.grant_permissions),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -218,12 +218,12 @@ private fun PermissionCategoryCard(
) {
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "Warning",
contentDescription = stringResource(R.string.cd_warning),
tint = Color(0xFFFF9800),
modifier = Modifier.size(16.dp)
)
Text(
text = "bitchat does NOT track your location",
text = stringResource(R.string.location_tracking_warning),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Medium,
@@ -98,8 +98,8 @@ data class BitchatPacket(
timestamp = timestamp,
payload = payload,
signature = null, // Remove signature for signing
ttl = 0u, // Use fixed TTL=0 for signing to ensure relay compatibility
route = route
ttl = com.bitchat.android.util.AppConstants.SYNC_TTL_HOPS // Use fixed TTL=0 for signing to ensure relay compatibility
)
return BinaryProtocol.encode(unsignedPacket)
}
@@ -10,7 +10,7 @@ import java.util.zip.Inflater
* Uses the same zlib algorithm as iOS CompressionUtil.swift
*/
object CompressionUtil {
private const val COMPRESSION_THRESHOLD = 100 // bytes - same as iOS
private const val COMPRESSION_THRESHOLD = com.bitchat.android.util.AppConstants.Protocol.COMPRESSION_THRESHOLD_BYTES // bytes - same as iOS
/**
* Helper to check if compression is worth it - exact same logic as iOS
@@ -13,7 +13,7 @@ class SeenMessageStore private constructor(private val context: Context) {
companion object {
private const val TAG = "SeenMessageStore"
private const val STORAGE_KEY = "seen_message_store_v1"
private const val MAX_IDS = 10_000
private const val MAX_IDS = com.bitchat.android.util.AppConstants.Services.SEEN_MESSAGE_MAX_IDS
@Volatile private var INSTANCE: SeenMessageStore? = null
fun getInstance(appContext: Context): SeenMessageStore {
@@ -86,4 +86,3 @@ class SeenMessageStore private constructor(private val context: Context) {
val read: List<String> = emptyList()
)
}
@@ -31,7 +31,9 @@ class GossipSyncManager(
fun gcsTargetFpr(): Double // percent -> 0.0..1.0
}
companion object { private const val TAG = "GossipSyncManager" }
companion object {
private const val TAG = "GossipSyncManager"
}
var delegate: Delegate? = null
@@ -46,6 +48,7 @@ class GossipSyncManager(
private val latestAnnouncementByPeer = ConcurrentHashMap<String, Pair<String, BitchatPacket>>()
private var periodicJob: Job? = null
private var cleanupJob: Job? = null
fun start() {
periodicJob?.cancel()
periodicJob = scope.launch(Dispatchers.IO) {
@@ -57,10 +60,23 @@ class GossipSyncManager(
catch (e: Exception) { Log.e(TAG, "Periodic sync error: ${e.message}") }
}
}
// Start periodic cleanup of stale announcements and messages
cleanupJob?.cancel()
cleanupJob = scope.launch(Dispatchers.IO) {
while (isActive) {
try {
delay(com.bitchat.android.util.AppConstants.Sync.CLEANUP_INTERVAL_MS)
pruneStaleAnnouncements()
} catch (e: CancellationException) { throw e }
catch (e: Exception) { Log.e(TAG, "Periodic cleanup error: ${e.message}") }
}
}
}
fun stop() {
periodicJob?.cancel(); periodicJob = null
cleanupJob?.cancel(); cleanupJob = null
}
fun scheduleInitialSync(delayMs: Long = 5_000L) {
@@ -98,6 +114,13 @@ class GossipSyncManager(
}
}
} else if (isAnnouncement) {
// Ignore stale announcements older than STALE_PEER_TIMEOUT
val now = System.currentTimeMillis()
val age = now - packet.timestamp.toLong()
if (age > com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS) {
Log.d(TAG, "Ignoring stale ANNOUNCE (age=${age}ms > ${com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS}ms)")
return
}
// senderID is fixed-size 8 bytes; map to hex string for key
val sender = packet.senderID.joinToString("") { b -> "%02x".format(b) }
latestAnnouncementByPeer[sender] = id to packet
@@ -118,7 +141,7 @@ class GossipSyncManager(
senderID = hexStringToByteArray(myPeerID),
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
ttl = 0u // neighbors only
ttl = com.bitchat.android.util.AppConstants.SYNC_TTL_HOPS // neighbors only
)
// Sign and broadcast
val signed = delegate?.signPacketForBroadcast(packet) ?: packet
@@ -134,7 +157,7 @@ class GossipSyncManager(
recipientID = hexStringToByteArray(peerID),
timestamp = System.currentTimeMillis().toULong(),
payload = payload,
ttl = 0u // neighbor only
ttl = com.bitchat.android.util.AppConstants.SYNC_TTL_HOPS // neighbor only
)
Log.d(TAG, "Sending sync request to $peerID (${payload.size} bytes)")
// Sign and send directly to peer
@@ -162,7 +185,7 @@ class GossipSyncManager(
val idBytes = hexToBytes(id)
if (!mightContain(idBytes)) {
// Send original packet unchanged to requester only (keep local TTL)
val toSend = pkt.copy(ttl = 0u)
val toSend = pkt.copy(ttl = com.bitchat.android.util.AppConstants.SYNC_TTL_HOPS)
delegate?.sendPacketToPeer(fromPeerID, toSend)
Log.d(TAG, "Sent sync announce: Type ${toSend.type} from ${toSend.senderID.toHexString()} to $fromPeerID packet id ${idBytes.toHexString()}")
}
@@ -173,7 +196,7 @@ class GossipSyncManager(
for (pkt in toSendMsgs) {
val idBytes = PacketIdUtil.computeIdBytes(pkt)
if (!mightContain(idBytes)) {
val toSend = pkt.copy(ttl = 0u)
val toSend = pkt.copy(ttl = com.bitchat.android.util.AppConstants.SYNC_TTL_HOPS)
delegate?.sendPacketToPeer(fromPeerID, toSend)
Log.d(TAG, "Sent sync message: Type ${toSend.type} to $fromPeerID packet id ${idBytes.toHexString()}")
}
@@ -235,6 +258,42 @@ class GossipSyncManager(
return RequestSyncPacket(p = params.p, m = mVal, data = params.data).encode()
}
// Periodically remove stale announcements and all their messages
private fun pruneStaleAnnouncements() {
val now = System.currentTimeMillis()
val stalePeers = mutableListOf<String>()
// Identify stale announcements by age
for ((peerID, pair) in latestAnnouncementByPeer.entries) {
val pkt = pair.second
val age = now - pkt.timestamp.toLong()
if (age > com.bitchat.android.util.AppConstants.Mesh.STALE_PEER_TIMEOUT_MS) {
stalePeers.add(peerID)
}
}
if (stalePeers.isEmpty()) return
// Remove announcements and their messages
var totalPrunedMsgs = 0
for (peerID in stalePeers) {
// Count messages to be pruned for logging
val toRemove = mutableListOf<String>()
synchronized(messages) {
for ((id, message) in messages) {
val sender = message.senderID.joinToString("") { b -> "%02x".format(b) }
if (sender == peerID) toRemove.add(id)
}
}
totalPrunedMsgs += toRemove.size
// Reuse existing removal which also clears announcement entry
removeAnnouncementForPeer(peerID)
}
Log.d(TAG, "Pruned ${stalePeers.size} stale announcements and $totalPrunedMsgs messages")
}
// Explicitly remove stored announcement for a given peer (hex ID)
fun removeAnnouncementForPeer(peerID: String) {
val key = peerID.lowercase()
@@ -244,16 +303,20 @@ class GossipSyncManager(
// Collect IDs to remove first to avoid modifying collection while iterating
val idsToRemove = mutableListOf<String>()
for ((id, message) in messages) {
val sender = message.senderID.joinToString("") { b -> "%02x".format(b) }
if (sender == key) {
idsToRemove.add(id)
synchronized(messages) {
for ((id, message) in messages) {
val sender = message.senderID.joinToString("") { b -> "%02x".format(b) }
if (sender == key) {
idsToRemove.add(id)
}
}
}
// Now remove the collected IDs
for (id in idsToRemove) {
messages.remove(id)
synchronized(messages) {
for (id in idsToRemove) {
messages.remove(id)
}
}
if (idsToRemove.isNotEmpty()) {
@@ -29,7 +29,8 @@ import androidx.compose.ui.unit.sp
import com.bitchat.android.nostr.NostrProofOfWork
import com.bitchat.android.nostr.PoWPreferenceManager
import com.bitchat.android.ui.debug.DebugSettingsSheet
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* About Sheet for bitchat app information
* Matches the design language of LocationChannelsSheet
@@ -102,7 +103,7 @@ fun AboutSheet(
verticalAlignment = Alignment.Bottom
) {
Text(
text = "bitchat",
text = stringResource(R.string.app_name),
style = TextStyle(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -112,7 +113,7 @@ fun AboutSheet(
)
Text(
text = "v$versionName",
text = stringResource(R.string.version_prefix, versionName?:""),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onBackground.copy(alpha = 0.5f),
@@ -123,7 +124,7 @@ fun AboutSheet(
}
Text(
text = "decentralized mesh messaging with end-to-end encryption",
text = stringResource(R.string.about_tagline),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f)
@@ -141,7 +142,7 @@ fun AboutSheet(
) {
Icon(
imageVector = Icons.Filled.Bluetooth,
contentDescription = "Offline Mesh Chat",
contentDescription = stringResource(R.string.cd_offline_mesh_chat),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
@@ -150,14 +151,14 @@ fun AboutSheet(
Spacer(modifier = Modifier.width(16.dp))
Column {
Text(
text = "Offline Mesh Chat",
text = stringResource(R.string.about_offline_mesh_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "Communicate directly via Bluetooth LE without internet or servers. Messages relay through nearby devices to extend range.",
text = stringResource(R.string.about_offline_mesh_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f)
)
@@ -173,7 +174,7 @@ fun AboutSheet(
) {
Icon(
imageVector = Icons.Default.Public,
contentDescription = "Online Geohash Channels",
contentDescription = stringResource(R.string.cd_online_geohash_channels),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
@@ -182,14 +183,14 @@ fun AboutSheet(
Spacer(modifier = Modifier.width(16.dp))
Column {
Text(
text = "Online Geohash Channels",
text = stringResource(R.string.about_online_geohash_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "Connect with people in your area using geohash-based channels. Extend the mesh using public internet relays.",
text = stringResource(R.string.about_online_geohash_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f)
)
@@ -205,7 +206,7 @@ fun AboutSheet(
) {
Icon(
imageVector = Icons.Default.Lock,
contentDescription = "End-to-End Encryption",
contentDescription = stringResource(R.string.cd_end_to_end_encryption),
tint = MaterialTheme.colorScheme.primary,
modifier = Modifier
.padding(top = 2.dp)
@@ -214,14 +215,14 @@ fun AboutSheet(
Spacer(modifier = Modifier.width(16.dp))
Column {
Text(
text = "End-to-End Encryption",
text = stringResource(R.string.about_e2e_title),
style = MaterialTheme.typography.titleMedium,
fontWeight = FontWeight.Medium,
color = MaterialTheme.colorScheme.onBackground
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = "Private messages are encrypted. Channel messages are public.",
text = stringResource(R.string.about_e2e_desc),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.8f)
)
@@ -232,7 +233,7 @@ fun AboutSheet(
// Appearance Section
item(key = "appearance_section") {
Text(
text = "appearance",
text = stringResource(R.string.about_appearance),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f),
modifier = Modifier
@@ -247,24 +248,24 @@ fun AboutSheet(
FilterChip(
selected = themePref.isSystem,
onClick = { com.bitchat.android.ui.theme.ThemePreferenceManager.set(context, com.bitchat.android.ui.theme.ThemePreference.System) },
label = { Text("system", fontFamily = FontFamily.Monospace) }
label = { Text(stringResource(R.string.about_system), fontFamily = FontFamily.Monospace) }
)
FilterChip(
selected = themePref.isLight,
onClick = { com.bitchat.android.ui.theme.ThemePreferenceManager.set(context, com.bitchat.android.ui.theme.ThemePreference.Light) },
label = { Text("light", fontFamily = FontFamily.Monospace) }
label = { Text(stringResource(R.string.about_light), fontFamily = FontFamily.Monospace) }
)
FilterChip(
selected = themePref.isDark,
onClick = { com.bitchat.android.ui.theme.ThemePreferenceManager.set(context, com.bitchat.android.ui.theme.ThemePreference.Dark) },
label = { Text("dark", fontFamily = FontFamily.Monospace) }
label = { Text(stringResource(R.string.about_dark), fontFamily = FontFamily.Monospace) }
)
}
}
// Proof of Work Section
item(key = "pow_section") {
Text(
text = "proof of work",
text = stringResource(R.string.about_pow),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f),
modifier = Modifier
@@ -289,7 +290,7 @@ fun AboutSheet(
FilterChip(
selected = !powEnabled,
onClick = { PoWPreferenceManager.setPowEnabled(false) },
label = { Text("pow off", fontFamily = FontFamily.Monospace) }
label = { Text(stringResource(R.string.about_pow_off), fontFamily = FontFamily.Monospace) }
)
FilterChip(
selected = powEnabled,
@@ -299,7 +300,7 @@ fun AboutSheet(
horizontalArrangement = Arrangement.spacedBy(6.dp),
verticalAlignment = Alignment.CenterVertically
) {
Text("pow on", fontFamily = FontFamily.Monospace)
Text(stringResource(R.string.about_pow_on), fontFamily = FontFamily.Monospace)
// Show current difficulty
if (powEnabled) {
Surface(
@@ -313,7 +314,7 @@ fun AboutSheet(
}
Text(
text = "add proof of work to geohash messages for spam deterrence.",
text = stringResource(R.string.about_pow_tip),
fontSize = 10.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.6f)
@@ -326,7 +327,7 @@ fun AboutSheet(
verticalArrangement = Arrangement.spacedBy(8.dp)
) {
Text(
text = "difficulty: $powDifficulty bits (~${NostrProofOfWork.estimateMiningTime(powDifficulty)})",
text = stringResource(R.string.about_pow_difficulty, powDifficulty, NostrProofOfWork.estimateMiningTime(powDifficulty)),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
)
@@ -353,20 +354,20 @@ fun AboutSheet(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = "difficulty $powDifficulty requires ~${NostrProofOfWork.estimateWork(powDifficulty)} hash attempts",
text = stringResource(R.string.about_pow_difficulty_attempts, powDifficulty, NostrProofOfWork.estimateWork(powDifficulty)),
fontSize = 10.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.7f)
)
Text(
text = when {
powDifficulty == 0 -> "no proof of work required"
powDifficulty <= 8 -> "very low - minimal spam protection"
powDifficulty <= 12 -> "low - basic spam protection"
powDifficulty <= 16 -> "medium - good spam protection"
powDifficulty <= 20 -> "high - strong spam protection"
powDifficulty <= 24 -> "very high - may cause delays"
else -> "extreme - significant computation required"
powDifficulty == 0 -> stringResource(R.string.about_pow_desc_none)
powDifficulty <= 8 -> stringResource(R.string.about_pow_desc_very_low)
powDifficulty <= 12 -> stringResource(R.string.about_pow_desc_low)
powDifficulty <= 16 -> stringResource(R.string.about_pow_desc_medium)
powDifficulty <= 20 -> stringResource(R.string.about_pow_desc_high)
powDifficulty <= 24 -> stringResource(R.string.about_pow_desc_very_high)
else -> stringResource(R.string.about_pow_desc_extreme)
},
fontSize = 10.sp,
fontFamily = FontFamily.Monospace,
@@ -384,7 +385,7 @@ fun AboutSheet(
val torMode = remember { mutableStateOf(com.bitchat.android.net.TorPreferenceManager.get(context)) }
val torStatus by com.bitchat.android.net.TorManager.statusFlow.collectAsState()
Text(
text = "network",
text = stringResource(R.string.about_network),
style = MaterialTheme.typography.labelLarge,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f),
modifier = Modifier
@@ -429,7 +430,7 @@ fun AboutSheet(
)
}
Text(
text = "route internet over tor for enhanced privacy.",
text = stringResource(R.string.about_tor_route),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
@@ -446,14 +447,14 @@ fun AboutSheet(
verticalArrangement = Arrangement.spacedBy(6.dp)
) {
Text(
text = "tor Status: $statusText, bootstrap ${torStatus.bootstrapPercent}%",
text = stringResource(R.string.about_tor_status, statusText, torStatus.bootstrapPercent),
style = MaterialTheme.typography.bodySmall,
color = colorScheme.onSurface.copy(alpha = 0.75f)
)
val lastLog = torStatus.lastLogLine
if (lastLog.isNotEmpty()) {
Text(
text = "Last: ${lastLog.take(160)}",
text = stringResource(R.string.about_last, lastLog.take(160)),
style = MaterialTheme.typography.labelSmall,
color = colorScheme.onSurface.copy(alpha = 0.6f)
)
@@ -483,20 +484,20 @@ fun AboutSheet(
) {
Icon(
imageVector = Icons.Filled.Warning,
contentDescription = "Warning",
contentDescription = stringResource(R.string.cd_warning),
tint = errorColor,
modifier = Modifier.size(16.dp)
)
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "Emergency Data Deletion",
text = stringResource(R.string.about_emergency_title),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
color = errorColor
)
Text(
text = "Tip: Triple-click the app title to emergency delete all stored data including messages, keys, and settings.",
text = stringResource(R.string.about_emergency_tip),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.8f)
@@ -523,14 +524,14 @@ fun AboutSheet(
)
) {
Text(
text = "Debug Settings",
text = stringResource(R.string.about_debug_settings),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace
)
}
}
Text(
text = "Open Source • Privacy First • Decentralized",
text = stringResource(R.string.about_footer),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f),
@@ -557,7 +558,7 @@ fun AboutSheet(
.padding(horizontal = 16.dp)
) {
Text(
text = "Close",
text = stringResource(R.string.close_plain),
style = MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.Bold),
color = MaterialTheme.colorScheme.onBackground
)
@@ -588,7 +589,7 @@ fun PasswordPromptDialog(
onDismissRequest = onDismiss,
title = {
Text(
text = "Enter Channel Password",
text = stringResource(R.string.pwd_prompt_title),
style = MaterialTheme.typography.titleMedium,
color = colorScheme.onSurface
)
@@ -596,7 +597,7 @@ fun PasswordPromptDialog(
text = {
Column {
Text(
text = "Channel $channelName is password protected. Enter the password to join.",
text = stringResource(R.string.pwd_prompt_message, channelName ?: ""),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.onSurface
)
@@ -605,7 +606,7 @@ fun PasswordPromptDialog(
OutlinedTextField(
value = passwordInput,
onValueChange = onPasswordChange,
label = { Text("Password", style = MaterialTheme.typography.bodyMedium) },
label = { Text(stringResource(R.string.pwd_label), style = MaterialTheme.typography.bodyMedium) },
textStyle = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
),
@@ -619,7 +620,7 @@ fun PasswordPromptDialog(
confirmButton = {
TextButton(onClick = onConfirm) {
Text(
text = "Join",
text = stringResource(R.string.join),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.primary
)
@@ -628,7 +629,7 @@ fun PasswordPromptDialog(
dismissButton = {
TextButton(onClick = onDismiss) {
Text(
text = "Cancel",
text = stringResource(R.string.cancel),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.onSurface
)
@@ -21,11 +21,16 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bitchat.android.core.ui.utils.singleOrTripleClickable
import com.bitchat.android.geohash.LocationChannelManager.PermissionState
import androidx.compose.foundation.Canvas
import androidx.compose.ui.geometry.Offset
/**
* Header components for ChatScreen
@@ -51,23 +56,27 @@ fun isFavoriteReactive(
}
@Composable
fun TorStatusIcon(
fun TorStatusDot(
modifier: Modifier = Modifier
) {
val torStatus by com.bitchat.android.net.TorManager.statusFlow.collectAsState()
if (torStatus.mode != com.bitchat.android.net.TorMode.OFF) {
val cableColor = when {
torStatus.running && torStatus.bootstrapPercent < 100 -> Color(0xFFFF9500)
torStatus.running && torStatus.bootstrapPercent >= 100 -> Color(0xFF00C851)
else -> Color.Red
val dotColor = when {
torStatus.running && torStatus.bootstrapPercent < 100 -> Color(0xFFFF9500) // Orange - bootstrapping
torStatus.running && torStatus.bootstrapPercent >= 100 -> Color(0xFF00C851) // Green - connected
else -> Color.Red // Red - error/disconnected
}
Canvas(
modifier = modifier
) {
val radius = size.minDimension / 2
drawCircle(
color = dotColor,
radius = radius,
center = Offset(size.width / 2, size.height / 2)
)
}
Icon(
imageVector = Icons.Outlined.Cable,
contentDescription = "Tor status",
modifier = modifier,
tint = cableColor
)
}
}
@@ -80,23 +89,23 @@ fun NoiseSessionIcon(
"uninitialized" -> Triple(
Icons.Outlined.NoEncryption,
Color(0x87878700), // Grey - ready to establish
"Ready for handshake"
stringResource(R.string.cd_ready_for_handshake)
)
"handshaking" -> Triple(
Icons.Outlined.Sync,
Color(0x87878700), // Grey - in progress
"Handshake in progress"
stringResource(R.string.cd_handshake_in_progress)
)
"established" -> Triple(
Icons.Filled.Lock,
Color(0xFFFF9500), // Orange - secure
"End-to-end encrypted"
stringResource(R.string.cd_encrypted)
)
else -> { // "failed" or any other state
Triple(
Icons.Outlined.Warning,
Color(0xFFFF4444), // Red - error
"Handshake failed"
stringResource(R.string.cd_handshake_failed)
)
}
}
@@ -129,7 +138,7 @@ fun NicknameEditor(
modifier = modifier
) {
Text(
text = "@",
text = stringResource(R.string.at_symbol),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.primary.copy(alpha = 0.8f)
)
@@ -193,8 +202,8 @@ fun PeerCounter(
Icon(
imageVector = Icons.Default.Group,
contentDescription = when (selectedLocationChannel) {
is com.bitchat.android.geohash.ChannelID.Location -> "Geohash participants"
else -> "Connected peers"
is com.bitchat.android.geohash.ChannelID.Location -> stringResource(R.string.cd_geohash_participants)
else -> stringResource(R.string.cd_connected_peers)
},
modifier = Modifier.size(16.dp),
tint = countColor
@@ -211,7 +220,7 @@ fun PeerCounter(
if (joinedChannels.isNotEmpty()) {
Text(
text = " · ⧉ ${joinedChannels.size}",
text = stringResource(R.string.channel_count_prefix) + "${joinedChannels.size}",
style = MaterialTheme.typography.bodyMedium,
color = if (isConnected) Color(0xFF00C851) else Color.Red,
fontSize = 16.sp,
@@ -231,7 +240,8 @@ fun ChatHeaderContent(
onSidebarClick: () -> Unit,
onTripleClick: () -> Unit,
onShowAppInfo: () -> Unit,
onLocationChannelsClick: () -> Unit
onLocationChannelsClick: () -> Unit,
onLocationNotesClick: () -> Unit
) {
val colorScheme = MaterialTheme.colorScheme
@@ -287,6 +297,7 @@ fun ChatHeaderContent(
onTripleTitleClick = onTripleClick,
onSidebarClick = onSidebarClick,
onLocationChannelsClick = onLocationChannelsClick,
onLocationNotesClick = onLocationNotesClick,
viewModel = viewModel
)
}
@@ -373,13 +384,13 @@ private fun PrivateChatHeader(
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back",
contentDescription = stringResource(R.string.back),
modifier = Modifier.size(16.dp),
tint = colorScheme.primary
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "back",
text = stringResource(R.string.chat_back),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.primary
)
@@ -405,7 +416,7 @@ private fun PrivateChatHeader(
if (showGlobe) {
Icon(
imageVector = Icons.Outlined.Public,
contentDescription = "Nostr reachable",
contentDescription = stringResource(R.string.cd_nostr_reachable),
modifier = Modifier.size(14.dp),
tint = Color(0xFF9B59B6) // Purple like iOS
)
@@ -428,7 +439,7 @@ private fun PrivateChatHeader(
) {
Icon(
imageVector = if (isFavorite) Icons.Filled.Star else Icons.Outlined.Star,
contentDescription = if (isFavorite) "Remove from favorites" else "Add to favorites",
contentDescription = if (isFavorite) stringResource(R.string.cd_remove_favorite) else stringResource(R.string.cd_add_favorite),
modifier = Modifier.size(18.dp), // Slightly larger than sidebar icon
tint = if (isFavorite) Color(0xFFFFD700) else Color(0x87878700) // Yellow or grey
)
@@ -463,13 +474,13 @@ private fun ChannelHeader(
) {
Icon(
imageVector = Icons.Filled.ArrowBack,
contentDescription = "Back",
contentDescription = stringResource(R.string.back),
modifier = Modifier.size(16.dp),
tint = colorScheme.primary
)
Spacer(modifier = Modifier.width(4.dp))
Text(
text = "back",
text = stringResource(R.string.chat_back),
style = MaterialTheme.typography.bodyMedium,
color = colorScheme.primary
)
@@ -478,7 +489,7 @@ private fun ChannelHeader(
// Title - perfectly centered regardless of other elements
Text(
text = "channel: $channel",
text = stringResource(R.string.chat_channel_prefix, channel),
style = MaterialTheme.typography.titleMedium,
color = Color(0xFFFF9500), // Orange to match input field
modifier = Modifier
@@ -492,7 +503,7 @@ private fun ChannelHeader(
modifier = Modifier.align(Alignment.CenterEnd)
) {
Text(
text = "leave",
text = stringResource(R.string.chat_leave),
style = MaterialTheme.typography.bodySmall,
color = Color.Red
)
@@ -508,6 +519,7 @@ private fun MainHeader(
onTripleTitleClick: () -> Unit,
onSidebarClick: () -> Unit,
onLocationChannelsClick: () -> Unit,
onLocationNotesClick: () -> Unit,
viewModel: ChatViewModel
) {
val colorScheme = MaterialTheme.colorScheme
@@ -534,7 +546,7 @@ private fun MainHeader(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "bitchat/",
text = stringResource(R.string.app_brand),
style = MaterialTheme.typography.headlineSmall,
color = colorScheme.primary,
modifier = Modifier.singleOrTripleClickable(
@@ -562,7 +574,7 @@ private fun MainHeader(
// Render icon directly to avoid symbol resolution issues
Icon(
imageVector = Icons.Filled.Email,
contentDescription = "Unread private messages",
contentDescription = stringResource(R.string.cd_unread_private_messages),
modifier = Modifier
.size(16.dp)
.clickable { viewModel.openLatestUnreadPrivateChat() },
@@ -571,7 +583,7 @@ private fun MainHeader(
}
// Location channels button (matching iOS implementation) and bookmark grouped tightly
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(end = 14.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.padding(end = 4.dp)) {
LocationChannelsButton(
viewModel = viewModel,
onClick = onLocationChannelsClick
@@ -586,14 +598,14 @@ private fun MainHeader(
val isBookmarked = bookmarks.contains(currentGeohash)
Box(
modifier = Modifier
.padding(start = 1.dp) // minimal gap between geohash and bookmark
.padding(start = 2.dp) // minimal gap between geohash and bookmark
.size(20.dp)
.clickable { bookmarksStore.toggle(currentGeohash) },
contentAlignment = Alignment.Center
) {
Icon(
imageVector = if (isBookmarked) Icons.Filled.Bookmark else Icons.Outlined.BookmarkBorder,
contentDescription = "Toggle bookmark",
contentDescription = stringResource(R.string.cd_toggle_bookmark),
tint = if (isBookmarked) Color(0xFF00C851) else MaterialTheme.colorScheme.onSurface.copy(alpha = 0.75f),
modifier = Modifier.size(16.dp)
)
@@ -601,15 +613,25 @@ private fun MainHeader(
}
}
// Tor status cable icon when Tor is enabled
TorStatusIcon(modifier = Modifier.size(14.dp))
// Location Notes button (extracted to separate component)
LocationNotesButton(
viewModel = viewModel,
onClick = onLocationNotesClick
)
// Tor status dot when Tor is enabled
TorStatusDot(
modifier = Modifier
.size(8.dp)
.padding(start = 0.dp, end = 2.dp)
)
// PoW status indicator
PoWStatusIndicator(
modifier = Modifier,
style = PoWIndicatorStyle.COMPACT
)
Spacer(modifier = Modifier.width(2.dp))
PeerCounter(
connectedPeers = connectedPeers.filter { it != viewModel.meshService.myPeerID },
joinedChannels = joinedChannels,
@@ -668,7 +690,7 @@ private fun LocationChannelsButton(
Spacer(modifier = Modifier.width(2.dp))
Icon(
imageVector = Icons.Default.PinDrop,
contentDescription = "Teleported",
contentDescription = stringResource(R.string.cd_teleported),
modifier = Modifier.size(12.dp),
tint = badgeColor
)
@@ -19,6 +19,7 @@ import androidx.compose.material.icons.filled.ArrowDownward
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material3.IconButton
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
@@ -62,6 +63,7 @@ fun ChatScreen(viewModel: ChatViewModel) {
var showPasswordDialog by remember { mutableStateOf(false) }
var passwordInput by remember { mutableStateOf("") }
var showLocationChannelsSheet by remember { mutableStateOf(false) }
var showLocationNotesSheet by remember { mutableStateOf(false) }
var showUserSheet by remember { mutableStateOf(false) }
var selectedUserForSheet by remember { mutableStateOf("") }
var selectedMessageForSheet by remember { mutableStateOf<BitchatMessage?>(null) }
@@ -97,6 +99,13 @@ fun ChatScreen(viewModel: ChatViewModel) {
}
}
// Determine whether to show media buttons (only hide in geohash location chats)
val showMediaButtons = when {
selectedPrivatePeer != null -> true
currentChannel != null -> true
else -> selectedLocationChannel !is com.bitchat.android.geohash.ChannelID.Location
}
// Use WindowInsets to handle keyboard properly
Box(
modifier = Modifier
@@ -225,7 +234,8 @@ fun ChatScreen(viewModel: ChatViewModel) {
selectedPrivatePeer = selectedPrivatePeer,
currentChannel = currentChannel,
nickname = nickname,
colorScheme = colorScheme
colorScheme = colorScheme,
showMediaButtons = showMediaButtons
)
}
@@ -240,7 +250,8 @@ fun ChatScreen(viewModel: ChatViewModel) {
onSidebarToggle = { viewModel.showSidebar() },
onShowAppInfo = { viewModel.showAppInfo() },
onPanicClear = { viewModel.panicClearAllData() },
onLocationChannelsClick = { showLocationChannelsSheet = true }
onLocationChannelsClick = { showLocationChannelsSheet = true },
onLocationNotesClick = { showLocationNotesSheet = true }
)
// Divider under header - positioned after status bar + header height
@@ -294,7 +305,7 @@ fun ChatScreen(viewModel: ChatViewModel) {
IconButton(onClick = { forceScrollToBottom = !forceScrollToBottom }) {
Icon(
imageVector = Icons.Filled.ArrowDownward,
contentDescription = "Scroll to bottom",
contentDescription = stringResource(com.bitchat.android.R.string.cd_scroll_to_bottom),
tint = Color(0xFF00C851)
)
}
@@ -353,6 +364,8 @@ fun ChatScreen(viewModel: ChatViewModel) {
onAppInfoDismiss = { viewModel.hideAppInfo() },
showLocationChannelsSheet = showLocationChannelsSheet,
onLocationChannelsSheetDismiss = { showLocationChannelsSheet = false },
showLocationNotesSheet = showLocationNotesSheet,
onLocationNotesSheetDismiss = { showLocationNotesSheet = false },
showUserSheet = showUserSheet,
onUserSheetDismiss = {
showUserSheet = false
@@ -381,7 +394,8 @@ private fun ChatInputSection(
selectedPrivatePeer: String?,
currentChannel: String?,
nickname: String,
colorScheme: ColorScheme
colorScheme: ColorScheme,
showMediaButtons: Boolean
) {
Surface(
modifier = Modifier.fillMaxWidth(),
@@ -417,6 +431,7 @@ private fun ChatInputSection(
selectedPrivatePeer = selectedPrivatePeer,
currentChannel = currentChannel,
nickname = nickname,
showMediaButtons = showMediaButtons,
modifier = Modifier.fillMaxWidth()
)
}
@@ -434,8 +449,12 @@ private fun ChatFloatingHeader(
onSidebarToggle: () -> Unit,
onShowAppInfo: () -> Unit,
onPanicClear: () -> Unit,
onLocationChannelsClick: () -> Unit
onLocationChannelsClick: () -> Unit,
onLocationNotesClick: () -> Unit
) {
val context = androidx.compose.ui.platform.LocalContext.current
val locationManager = remember { com.bitchat.android.geohash.LocationChannelManager.getInstance(context) }
Surface(
modifier = Modifier
.fillMaxWidth()
@@ -459,7 +478,12 @@ private fun ChatFloatingHeader(
onSidebarClick = onSidebarToggle,
onTripleClick = onPanicClear,
onShowAppInfo = onShowAppInfo,
onLocationChannelsClick = onLocationChannelsClick
onLocationChannelsClick = onLocationChannelsClick,
onLocationNotesClick = {
// Ensure location is loaded before showing sheet
locationManager.refreshChannels()
onLocationNotesClick()
}
)
},
colors = TopAppBarDefaults.topAppBarColors(
@@ -470,6 +494,7 @@ private fun ChatFloatingHeader(
}
}
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun ChatDialogs(
showPasswordDialog: Boolean,
@@ -482,6 +507,8 @@ private fun ChatDialogs(
onAppInfoDismiss: () -> Unit,
showLocationChannelsSheet: Boolean,
onLocationChannelsSheetDismiss: () -> Unit,
showLocationNotesSheet: Boolean,
onLocationNotesSheetDismiss: () -> Unit,
showUserSheet: Boolean,
onUserSheetDismiss: () -> Unit,
selectedUserForSheet: String,
@@ -522,6 +549,14 @@ private fun ChatDialogs(
)
}
// Location notes sheet (extracted to separate presenter)
if (showLocationNotesSheet) {
LocationNotesSheetPresenter(
viewModel = viewModel,
onDismiss = onLocationNotesSheetDismiss
)
}
// User action sheet
if (showUserSheet) {
ChatUserSheet(
@@ -3,10 +3,7 @@ package com.bitchat.android.ui
/**
* UI constants/utilities for nickname rendering.
*/
const val MAX_NICKNAME_LENGTH: Int = 15
fun truncateNickname(name: String, maxLen: Int = MAX_NICKNAME_LENGTH): String {
fun truncateNickname(name: String, maxLen: Int = com.bitchat.android.util.AppConstants.UI.MAX_NICKNAME_LENGTH): String {
return if (name.length <= maxLen) name else name.take(maxLen)
}
@@ -12,6 +12,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.text.AnnotatedString
import kotlinx.coroutines.launch
@@ -61,7 +63,7 @@ fun ChatUserSheet(
) {
// Header
Text(
text = "@$targetNickname",
text = stringResource(R.string.at_nickname, targetNickname),
fontSize = 18.sp,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -69,7 +71,7 @@ fun ChatUserSheet(
)
Text(
text = if (selectedMessage != null) "choose an action for this message or user" else "choose an action for this user",
text = if (selectedMessage != null) stringResource(R.string.choose_action_message_or_user) else stringResource(R.string.choose_action_user),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
@@ -83,8 +85,8 @@ fun ChatUserSheet(
selectedMessage?.let { message ->
item {
UserActionRow(
title = "copy message",
subtitle = "copy this message to clipboard",
title = stringResource(R.string.action_copy_message_title),
subtitle = stringResource(R.string.action_copy_message_subtitle),
titleColor = standardGrey,
onClick = {
// Copy the message content to clipboard
@@ -100,8 +102,8 @@ fun ChatUserSheet(
// Slap action
item {
UserActionRow(
title = "slap $targetNickname",
subtitle = "send a playful slap message",
title = stringResource(R.string.action_slap_title, targetNickname),
subtitle = stringResource(R.string.action_slap_subtitle),
titleColor = standardBlue,
onClick = {
// Send slap command
@@ -114,8 +116,8 @@ fun ChatUserSheet(
// Hug action
item {
UserActionRow(
title = "hug $targetNickname",
subtitle = "send a friendly hug message",
title = stringResource(R.string.action_hug_title, targetNickname),
subtitle = stringResource(R.string.action_hug_subtitle),
titleColor = standardGreen,
onClick = {
// Send hug command
@@ -128,8 +130,8 @@ fun ChatUserSheet(
// Block action
item {
UserActionRow(
title = "block $targetNickname",
subtitle = "block all messages from this user",
title = stringResource(R.string.action_block_title, targetNickname),
subtitle = stringResource(R.string.action_block_subtitle),
titleColor = standardRed,
onClick = {
// Check if we're in a geohash channel
@@ -158,7 +160,7 @@ fun ChatUserSheet(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "cancel",
text = stringResource(R.string.cancel_lower),
fontSize = BASE_FONT_SIZE.sp,
fontFamily = FontFamily.Monospace
)
@@ -147,21 +147,13 @@ class ChatViewModel(
mediaSendingManager.handleTransferProgressEvent(evt)
}
}
// Removed background location notes subscription. Notes now load only when sheet opens.
}
fun cancelMediaSend(messageId: String) {
val transferId = synchronized(transferMessageMap) { messageTransferMap[messageId] }
if (transferId != null) {
val cancelled = meshService.cancelFileTransfer(transferId)
if (cancelled) {
// Remove the message from chat upon explicit cancel
messageManager.removeMessageById(messageId)
synchronized(transferMessageMap) {
transferMessageMap.remove(transferId)
messageTransferMap.remove(messageId)
}
}
}
// Delegate to MediaSendingManager which tracks transfer IDs and cleans up UI state
mediaSendingManager.cancelMediaSend(messageId)
}
private fun loadAndInitialize() {
@@ -226,20 +218,6 @@ class ChatViewModel(
} catch (_: Exception) { }
// Note: Mesh service is now started by MainActivity
// Show welcome message if no peers after delay
viewModelScope.launch {
delay(10000)
if (state.getConnectedPeersValue().isEmpty() && state.getMessagesValue().isEmpty()) {
val welcomeMessage = BitchatMessage(
sender = "system",
content = "get people around you to download bitchat and chat with them here!",
timestamp = Date(),
isRelay = false
)
messageManager.addMessage(welcomeMessage)
}
}
// BLE receives are inserted by MessageHandler path; no VoiceNoteBus for Tor in this branch.
}
@@ -605,6 +583,8 @@ class ChatViewModel(
}
}
// Location notes subscription management moved to LocationNotesViewModelExtensions.kt
/**
* Update reactive states for all connected peers (session states, fingerprints, nicknames, RSSI)
*/
@@ -20,6 +20,8 @@ import androidx.compose.ui.unit.sp
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
import java.util.*
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* GeohashPeopleList - iOS-compatible component for displaying geohash participants
@@ -66,7 +68,7 @@ fun GeohashPeopleList(
)
Spacer(modifier = Modifier.width(6.dp))
Text(
text = "PEOPLE",
text = stringResource(R.string.geohash_people_header),
style = MaterialTheme.typography.labelSmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold
@@ -78,7 +80,7 @@ fun GeohashPeopleList(
if (geohashPeople.isEmpty()) {
// Empty state - matches iOS "nobody around..."
Text(
text = "nobody around...",
text = stringResource(R.string.nobody_around),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontSize = BASE_FONT_SIZE.sp
@@ -182,7 +184,7 @@ private fun GeohashPersonItem(
// Unread DM indicator (orange envelope)
Icon(
imageVector = Icons.Filled.Email,
contentDescription = "Unread message",
contentDescription = stringResource(R.string.cd_unread_message),
modifier = Modifier.size(12.dp),
tint = Color(0xFFFF9500) // iOS orange
)
@@ -253,7 +255,7 @@ private fun GeohashPersonItem(
// "You" indicator for current user
if (isMe) {
Text(
text = " (you)",
text = stringResource(R.string.you_suffix),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace,
fontSize = BASE_FONT_SIZE.sp
@@ -11,7 +11,6 @@ import android.webkit.WebChromeClient
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
@@ -37,13 +36,15 @@ import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import androidx.core.view.updateLayoutParams
import com.bitchat.android.geohash.Geohash
import com.bitchat.android.geohash.LocationChannelManager
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
@OptIn(ExperimentalMaterial3Api::class)
class GeohashPickerActivity : ComponentActivity() {
class GeohashPickerActivity : OrientationAwareActivity() {
companion object {
const val EXTRA_INITIAL_GEOHASH = "initial_geohash"
@@ -175,7 +176,7 @@ class GeohashPickerActivity : ComponentActivity() {
shadowElevation = 6.dp
) {
Text(
text = "pan and zoom to select a geohash",
text = stringResource(R.string.pan_zoom_instruction),
fontSize = 12.sp,
textAlign = TextAlign.Center,
fontFamily = FontFamily.Monospace,
@@ -228,7 +229,7 @@ class GeohashPickerActivity : ComponentActivity() {
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Filled.Remove, contentDescription = "Decrease precision")
Icon(Icons.Filled.Remove, contentDescription = stringResource(R.string.cd_decrease_precision))
}
}
@@ -244,7 +245,7 @@ class GeohashPickerActivity : ComponentActivity() {
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Filled.Add, contentDescription = "Increase precision")
Icon(Icons.Filled.Add, contentDescription = stringResource(R.string.cd_increase_precision))
}
}
@@ -264,10 +265,10 @@ class GeohashPickerActivity : ComponentActivity() {
)
) {
Row(verticalAlignment = Alignment.CenterVertically) {
Icon(Icons.Filled.Check, contentDescription = "Select geohash")
Icon(Icons.Filled.Check, contentDescription = stringResource(R.string.cd_select_geohash))
Spacer(Modifier.width(6.dp))
Text(
text = "select",
text = stringResource(R.string.select),
fontSize = (BASE_FONT_SIZE - 2).sp,
fontFamily = FontFamily.Monospace
)
@@ -170,6 +170,7 @@ fun MessageInput(
selectedPrivatePeer: String?,
currentChannel: String?,
nickname: String,
showMediaButtons: Boolean,
modifier: Modifier = Modifier
) {
val colorScheme = MaterialTheme.colorScheme
@@ -217,7 +218,7 @@ fun MessageInput(
// Show placeholder when there's no text and not recording
if (value.text.isEmpty() && !isRecording) {
Text(
text = "type a message...",
text = stringResource(R.string.type_a_message_placeholder),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
),
@@ -252,8 +253,8 @@ fun MessageInput(
Spacer(modifier = Modifier.width(8.dp)) // Reduced spacing
// Voice and image buttons when no text (always visible for mesh + channels + private)
if (value.text.isEmpty()) {
// Voice and image buttons when no text (only visible in Mesh chat)
if (value.text.isEmpty() && showMediaButtons) {
// Hold-to-record microphone
val bg = if (colorScheme.background == Color.Black) Color(0xFF00FF00).copy(alpha = 0.75f) else Color(0xFF008000).copy(alpha = 0.75f)
@@ -486,7 +487,7 @@ fun MentionSuggestionItem(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "@$suggestion",
text = stringResource(R.string.mention_suggestion_at, suggestion),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.SemiBold
@@ -498,7 +499,7 @@ fun MentionSuggestionItem(
Spacer(modifier = Modifier.weight(1f))
Text(
text = "mention",
text = stringResource(R.string.mention),
style = MaterialTheme.typography.bodySmall.copy(
fontFamily = FontFamily.Monospace
),
@@ -16,6 +16,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
@@ -94,7 +95,7 @@ fun LinkPreviewPill(
) {
Icon(
imageVector = Icons.Outlined.Link,
contentDescription = "Link",
contentDescription = stringResource(com.bitchat.android.R.string.cd_link),
modifier = Modifier.size(24.dp),
tint = Color.Blue
)
@@ -37,6 +37,8 @@ import com.bitchat.android.geohash.GeohashChannelLevel
import com.bitchat.android.geohash.LocationChannelManager
import com.bitchat.android.geohash.GeohashBookmarksStore
import com.bitchat.android.ui.theme.BASE_FONT_SIZE
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Location Channels Sheet for selecting geohash-based location channels
@@ -133,7 +135,7 @@ fun LocationChannelsSheet(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
Text(
text = "#location channels",
text = stringResource(R.string.location_channels_title),
style = MaterialTheme.typography.headlineSmall,
fontFamily = FontFamily.Monospace,
fontWeight = FontWeight.Bold,
@@ -141,7 +143,7 @@ fun LocationChannelsSheet(
)
Text(
text = "chat with people near you using geohash channels. only a coarse geohash is shared, never exact gps. do not screenshot or share this screen to protect your privacy.",
text = stringResource(R.string.location_channels_desc),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f)
@@ -170,7 +172,7 @@ fun LocationChannelsSheet(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = "grant location permission",
text = stringResource(R.string.grant_location_permission),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace
)
@@ -180,7 +182,7 @@ fun LocationChannelsSheet(
LocationChannelManager.PermissionState.RESTRICTED -> {
Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
Text(
text = "location permission denied. enable in settings to use location channels.",
text = stringResource(R.string.location_permission_denied),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = Color.Red.copy(alpha = 0.8f)
@@ -194,7 +196,7 @@ fun LocationChannelsSheet(
}
) {
Text(
text = "open settings",
text = stringResource(R.string.open_settings),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace
)
@@ -203,7 +205,7 @@ fun LocationChannelsSheet(
}
LocationChannelManager.PermissionState.AUTHORIZED -> {
Text(
text = "✓ location permission granted",
text = stringResource(R.string.location_permission_granted),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = standardGreen
@@ -216,7 +218,7 @@ fun LocationChannelsSheet(
) {
CircularProgressIndicator(modifier = Modifier.size(12.dp))
Text(
text = "checking permissions...",
text = stringResource(R.string.checking_permissions),
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f)
@@ -232,7 +234,7 @@ fun LocationChannelsSheet(
item(key = "mesh") {
ChannelRow(
title = meshTitleWithCount(viewModel),
subtitle = "#bluetooth • ${bluetoothRangeString()}",
subtitle = stringResource(R.string.location_bluetooth_subtitle, bluetoothRangeString()),
isSelected = selectedChannel is ChannelID.Mesh,
titleColor = standardBlue,
titleBold = meshCount(viewModel) > 0,
@@ -245,8 +247,11 @@ fun LocationChannelsSheet(
}
// Nearby options (only show if location services are enabled)
// CRITICAL: Filter out .building level (precision 8) - iOS pattern
// iOS: let nearby = manager.availableChannels.filter { $0.level != .building }
if (availableChannels.isNotEmpty() && locationServicesEnabled) {
items(availableChannels) { channel ->
val nearbyChannels = availableChannels.filter { it.level != GeohashChannelLevel.BUILDING }
items(nearbyChannels) { channel ->
val coverage = coverageString(channel.geohash.length)
val nameBase = locationNames[channel.level]
val namePart = nameBase?.let { formattedNamePrefix(channel.level) + it }
@@ -262,13 +267,13 @@ fun LocationChannelsSheet(
titleColor = standardGreen,
titleBold = highlight,
trailingContent = {
IconButton(onClick = { bookmarksStore.toggle(channel.geohash) }) {
Icon(
imageVector = if (isBookmarked) Icons.Filled.Bookmark else Icons.Outlined.BookmarkBorder,
contentDescription = if (isBookmarked) "Unbookmark" else "Bookmark",
tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f),
)
}
IconButton(onClick = { bookmarksStore.toggle(channel.geohash) }) {
Icon(
imageVector = if (isBookmarked) Icons.Filled.Bookmark else Icons.Outlined.BookmarkBorder,
contentDescription = if (isBookmarked) stringResource(R.string.cd_remove_bookmark) else stringResource(R.string.cd_add_bookmark),
tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f),
)
}
},
onClick = {
// Selecting a suggested nearby channel is not a teleport
@@ -286,7 +291,7 @@ fun LocationChannelsSheet(
) {
CircularProgressIndicator(modifier = Modifier.size(16.dp))
Text(
text = "finding nearby channels…",
text = stringResource(R.string.finding_nearby_channels),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace
)
@@ -298,7 +303,7 @@ fun LocationChannelsSheet(
if (bookmarks.isNotEmpty()) {
item(key = "bookmarked_header") {
Text(
text = "bookmarked",
text = stringResource(R.string.bookmarked),
style = MaterialTheme.typography.labelLarge,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.7f),
@@ -328,7 +333,7 @@ fun LocationChannelsSheet(
IconButton(onClick = { bookmarksStore.toggle(gh) }) {
Icon(
imageVector = Icons.Filled.Bookmark,
contentDescription = "Remove bookmark",
contentDescription = stringResource(R.string.cd_remove_bookmark),
tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f),
)
}
@@ -366,7 +371,7 @@ fun LocationChannelsSheet(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "#",
text = stringResource(R.string.hash_symbol),
fontSize = BASE_FONT_SIZE.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
@@ -409,7 +414,7 @@ fun LocationChannelsSheet(
decorationBox = { innerTextField ->
if (customGeohash.isEmpty()) {
Text(
text = "geohash",
text = stringResource(R.string.geohash_placeholder),
fontSize = BASE_FONT_SIZE.sp,
fontFamily = FontFamily.Monospace,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.4f)
@@ -435,7 +440,7 @@ fun LocationChannelsSheet(
}) {
Icon(
imageVector = Icons.Filled.Map,
contentDescription = "Open map",
contentDescription = stringResource(R.string.cd_open_map),
tint = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.8f)
)
}
@@ -453,7 +458,7 @@ fun LocationChannelsSheet(
locationManager.select(ChannelID.Location(channel))
onDismiss()
} else {
customError = "invalid geohash"
customError = context.getString(R.string.invalid_geohash)
}
},
enabled = isValid,
@@ -467,14 +472,13 @@ fun LocationChannelsSheet(
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "teleport",
text = stringResource(R.string.teleport),
fontSize = BASE_FONT_SIZE.sp,
fontFamily = FontFamily.Monospace
)
// iOS has a face.dashed icon, use closest Material equivalent
Icon(
imageVector = Icons.Filled.PinDrop,
contentDescription = "Teleport",
contentDescription = stringResource(R.string.cd_teleport),
modifier = Modifier.size(14.dp),
tint = MaterialTheme.colorScheme.onSurface
)
@@ -530,11 +534,7 @@ fun LocationChannelsSheet(
modifier = Modifier.fillMaxWidth()
) {
Text(
text = if (locationServicesEnabled) {
"disable location services"
} else {
"enable location services"
},
text = if (locationServicesEnabled) stringResource(R.string.disable_location_services) else stringResource(R.string.enable_location_services),
fontSize = 12.sp,
fontFamily = FontFamily.Monospace
)
@@ -558,7 +558,7 @@ fun LocationChannelsSheet(
.padding(horizontal = 16.dp)
) {
Text(
text = "Close",
text = stringResource(R.string.close_plain),
style = MaterialTheme.typography.labelMedium.copy(fontWeight = FontWeight.Bold),
color = MaterialTheme.colorScheme.onBackground
)
@@ -573,8 +573,6 @@ fun LocationChannelsSheet(
if (isPresented) {
if (permissionState == LocationChannelManager.PermissionState.AUTHORIZED && locationServicesEnabled) {
locationManager.refreshChannels()
}
if (locationServicesEnabled) {
locationManager.beginLiveRefresh()
}
val geohashes = (availableChannels.map { it.geohash } + bookmarks).toSet().toList()
@@ -668,7 +666,7 @@ private fun ChannelRow(
if (isSelected) {
Icon(
imageVector = Icons.Filled.Check,
contentDescription = "Selected",
contentDescription = stringResource(R.string.cd_selected),
tint = Color(0xFF32D74B), // iOS green for checkmark
modifier = Modifier.size(20.dp)
)
@@ -695,10 +693,13 @@ private fun splitTitleAndCount(title: String): Pair<String, String?> {
}
}
@Composable
private fun meshTitleWithCount(viewModel: ChatViewModel): String {
val meshCount = meshCount(viewModel)
val noun = if (meshCount == 1) "person" else "people"
return "mesh [$meshCount $noun]"
val ctx = androidx.compose.ui.platform.LocalContext.current
val peopleText = ctx.resources.getQuantityString(com.bitchat.android.R.plurals.people_count, meshCount, meshCount)
val meshLabel = stringResource(com.bitchat.android.R.string.mesh_label)
return "$meshLabel [$peopleText]"
}
private fun meshCount(viewModel: ChatViewModel): Int {
@@ -708,14 +709,26 @@ private fun meshCount(viewModel: ChatViewModel): Int {
} ?: 0
}
@Composable
private fun geohashTitleWithCount(channel: GeohashChannel, participantCount: Int): String {
val noun = if (participantCount == 1) "person" else "people"
return "${channel.level.displayName.lowercase()} [$participantCount $noun]"
val ctx = androidx.compose.ui.platform.LocalContext.current
val peopleText = ctx.resources.getQuantityString(com.bitchat.android.R.plurals.people_count, participantCount, participantCount)
val levelName = when (channel.level) {
com.bitchat.android.geohash.GeohashChannelLevel.BUILDING -> "Building" // iOS: precision 8 for location notes
com.bitchat.android.geohash.GeohashChannelLevel.BLOCK -> stringResource(com.bitchat.android.R.string.location_level_block)
com.bitchat.android.geohash.GeohashChannelLevel.NEIGHBORHOOD -> stringResource(com.bitchat.android.R.string.location_level_neighborhood)
com.bitchat.android.geohash.GeohashChannelLevel.CITY -> stringResource(com.bitchat.android.R.string.location_level_city)
com.bitchat.android.geohash.GeohashChannelLevel.PROVINCE -> stringResource(com.bitchat.android.R.string.location_level_province)
com.bitchat.android.geohash.GeohashChannelLevel.REGION -> stringResource(com.bitchat.android.R.string.location_level_region)
}
return "$levelName [$peopleText]"
}
@Composable
private fun geohashHashTitleWithCount(geohash: String, participantCount: Int): String {
val noun = if (participantCount == 1) "person" else "people"
return "#$geohash [$participantCount $noun]"
val ctx = androidx.compose.ui.platform.LocalContext.current
val peopleText = ctx.resources.getQuantityString(com.bitchat.android.R.plurals.people_count, participantCount, participantCount)
return "#$geohash [$peopleText]"
}
private fun isChannelSelected(channel: GeohashChannel, selectedChannel: ChannelID?): Boolean {
@@ -738,7 +751,8 @@ private fun levelForLength(length: Int): GeohashChannelLevel {
5 -> GeohashChannelLevel.CITY
6 -> GeohashChannelLevel.NEIGHBORHOOD
7 -> GeohashChannelLevel.BLOCK
else -> GeohashChannelLevel.BLOCK
8 -> GeohashChannelLevel.BUILDING // iOS: precision 8 for building-level
else -> if (length > 8) GeohashChannelLevel.BUILDING else GeohashChannelLevel.BLOCK
}
}
@@ -0,0 +1,67 @@
package com.bitchat.android.ui
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.Description
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import com.bitchat.android.R
import com.bitchat.android.geohash.ChannelID
import com.bitchat.android.geohash.LocationChannelManager
import com.bitchat.android.nostr.LocationNotesManager
/**
* Location Notes button component for MainHeader
* Shows in mesh mode when location permission granted AND services enabled
* Icon turns primary color when notes exist, gray otherwise
*/
@Composable
fun LocationNotesButton(
viewModel: ChatViewModel,
onClick: () -> Unit,
modifier: Modifier = Modifier
) {
val colorScheme = MaterialTheme.colorScheme
val context = LocalContext.current
// Get channel and permission state
val selectedLocationChannel by viewModel.selectedLocationChannel.observeAsState()
val locationManager = remember { LocationChannelManager.getInstance(context) }
val permissionState by locationManager.permissionState.observeAsState()
val locationServicesEnabled by locationManager.locationServicesEnabled.observeAsState(false)
// Check both permission AND location services enabled
val locationPermissionGranted = permissionState == LocationChannelManager.PermissionState.AUTHORIZED
val locationEnabled = locationPermissionGranted && locationServicesEnabled
// Get notes count from LocationNotesManager
val notesManager = remember { LocationNotesManager.getInstance() }
val notes by notesManager.notes.observeAsState(emptyList())
val notesCount = notes.size
// Only show in mesh mode when location is authorized (iOS pattern)
if (selectedLocationChannel is ChannelID.Mesh && locationEnabled) {
val hasNotes = notesCount > 0
IconButton(
onClick = onClick,
modifier = modifier.size(24.dp)
) {
Icon(
imageVector = Icons.Outlined.Description, // "long.text.page.and.pencil" equivalent
contentDescription = stringResource(R.string.cd_location_notes),
modifier = Modifier.size(16.dp),
tint = if (hasNotes) colorScheme.primary else Color.Gray
)
}
}
}
@@ -0,0 +1,612 @@
package com.bitchat.android.ui
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.isSystemInDarkTheme
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowUpward
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.res.pluralStringResource
import com.bitchat.android.R
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bitchat.android.geohash.GeohashChannelLevel
import com.bitchat.android.geohash.LocationChannelManager
import com.bitchat.android.nostr.LocationNotesManager
import java.text.SimpleDateFormat
import java.util.*
import java.util.Calendar
/**
* Location Notes Sheet - EXACT iOS UI match for bitchat
* Matches iOS LocationNotesView.swift exactly in style, colors, fonts, and text
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LocationNotesSheet(
geohash: String,
locationName: String?,
nickname: String?,
onDismiss: () -> Unit,
modifier: Modifier = Modifier
) {
val context = LocalContext.current
val isDark = isSystemInDarkTheme()
// iOS color scheme
val backgroundColor = if (isDark) Color.Black else Color.White
val accentGreen = if (isDark) Color.Green else Color(0xFF008000) // dark: green, light: dark green (0, 0.5, 0)
// Managers
val notesManager = remember { LocationNotesManager.getInstance() }
val locationManager = remember { LocationChannelManager.getInstance(context) }
// State
val notes by notesManager.notes.observeAsState(emptyList())
val state by notesManager.state.observeAsState(LocationNotesManager.State.IDLE)
val errorMessage by notesManager.errorMessage.observeAsState()
val initialLoadComplete by notesManager.initialLoadComplete.observeAsState(false)
// SIMPLIFIED: Get count directly from notes list (no separate counter needed)
val count = notes.size
// Get location name (building or block) - matches iOS locationNames lookup
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
val displayLocationName = locationNames[GeohashChannelLevel.BUILDING]?.takeIf { it.isNotEmpty() }
?: locationNames[GeohashChannelLevel.BLOCK]?.takeIf { it.isNotEmpty() }
// Input field state
var draft by remember { mutableStateOf("") }
val sendButtonEnabled = draft.trim().isNotEmpty() && state != LocationNotesManager.State.NO_RELAYS
// Scroll state
val listState = rememberLazyListState()
// Effect to set geohash when sheet opens
LaunchedEffect(geohash) {
notesManager.setGeohash(geohash)
}
// Cleanup when sheet closes
DisposableEffect(Unit) {
onDispose {
notesManager.cancel()
}
}
ModalBottomSheet(
onDismissRequest = onDismiss,
modifier = modifier,
sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true),
containerColor = backgroundColor,
contentColor = if (isDark) Color.White else Color.Black
) {
Column(
modifier = Modifier
.fillMaxWidth()
.fillMaxHeight(0.9f)
) {
// Header section (matches iOS headerSection)
LocationNotesHeader(
geohash = geohash,
count = count,
locationName = displayLocationName,
state = state,
accentGreen = accentGreen,
backgroundColor = backgroundColor,
onClose = onDismiss
)
// ScrollView with notes content
Box(
modifier = Modifier
.weight(1f)
.fillMaxWidth()
.background(backgroundColor)
) {
LazyColumn(
state = listState,
modifier = Modifier.fillMaxSize(),
contentPadding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)
) {
// Notes content (matches iOS notesContent)
when {
state == LocationNotesManager.State.NO_RELAYS -> {
item {
NoRelaysRow(
onRetry = { notesManager.refresh() }
)
}
}
state == LocationNotesManager.State.LOADING && !initialLoadComplete -> {
item {
LoadingRow()
}
}
notes.isEmpty() -> {
item {
EmptyRow()
}
}
else -> {
items(notes, key = { it.id }) { note ->
NoteRow(note = note)
Spacer(modifier = Modifier.height(12.dp))
}
}
}
// Error row (matches iOS errorRow)
errorMessage?.let { error ->
if (state != LocationNotesManager.State.NO_RELAYS) {
item {
ErrorRow(
message = error,
onDismiss = { notesManager.clearError() }
)
}
}
}
}
}
// Divider before input (matches iOS overlay)
HorizontalDivider(
modifier = Modifier.fillMaxWidth(),
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.2f),
thickness = 1.dp
)
// Input section (matches iOS inputSection)
LocationNotesInputSection(
draft = draft,
onDraftChange = { draft = it },
sendButtonEnabled = sendButtonEnabled,
accentGreen = accentGreen,
backgroundColor = backgroundColor,
onSend = {
val content = draft.trim()
if (content.isNotEmpty()) {
notesManager.send(content, nickname)
draft = ""
}
}
)
}
}
}
/**
* Header section - matches iOS headerSection exactly
* Shows: "#geohash • X notes", location name, description, and close button
*/
@Composable
private fun LocationNotesHeader(
geohash: String,
count: Int,
locationName: String?,
state: LocationNotesManager.State,
accentGreen: Color,
backgroundColor: Color,
onClose: () -> Unit
) {
Column(
modifier = Modifier
.fillMaxWidth()
.background(backgroundColor)
.padding(horizontal = 16.dp)
.padding(top = 16.dp, bottom = 12.dp)
) {
// Title row with close button
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
// Localized title with ±1 and note count
Text(
text = pluralStringResource(
id = R.plurals.location_notes_title,
count = count,
geohash,
count
),
fontFamily = FontFamily.Monospace,
fontSize = 18.sp,
color = MaterialTheme.colorScheme.onSurface
)
// Close button - iOS style with xmark icon
Box(
modifier = Modifier
.size(32.dp)
.clickable(onClick = onClose),
contentAlignment = Alignment.Center
) {
Text(
text = "",
fontFamily = FontFamily.Monospace,
fontSize = 13.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface
)
}
}
Spacer(modifier = Modifier.height(8.dp))
// Location name in green (building or block)
locationName?.let { name ->
if (name.isNotEmpty()) {
Text(
text = name,
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = accentGreen
)
Spacer(modifier = Modifier.height(8.dp))
}
}
// Description
Text(
text = stringResource(R.string.location_notes_description),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
// Relays paused message if no relays
if (state == LocationNotesManager.State.NO_RELAYS) {
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.location_notes_relays_unavailable),
fontFamily = FontFamily.Monospace,
fontSize = 11.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
}
}
}
/**
* Note row - matches iOS noteRow exactly
* Shows @basename then timestamp, then content below
*/
@Composable
private fun NoteRow(note: LocationNotesManager.Note) {
// Extract baseName (before #suffix like iOS)
val baseName = note.displayName.split("#", limit = 2).firstOrNull() ?: note.displayName
val ts = timestampText(note.createdAt)
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp)
) {
// First row: @nickname and timestamp
Row(
modifier = Modifier.fillMaxWidth(),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "@$baseName",
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface
)
if (ts.isNotEmpty()) {
Spacer(modifier = Modifier.width(6.dp))
Text(
text = ts,
fontFamily = FontFamily.Monospace,
fontSize = 11.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
}
}
Spacer(modifier = Modifier.height(2.dp))
// Second row: content
Text(
text = note.content,
fontFamily = FontFamily.Monospace,
fontSize = 14.sp,
color = MaterialTheme.colorScheme.onSurface
)
}
}
/**
* No relays row - matches iOS noRelaysRow
*/
@Composable
private fun NoRelaysRow(onRetry: () -> Unit) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp)
) {
Text(
text = stringResource(R.string.location_notes_no_relays_title),
fontFamily = FontFamily.Monospace,
fontSize = 13.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.location_notes_no_relays_desc),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.retry),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.clickable(onClick = onRetry)
)
}
}
/**
* Loading row - matches iOS loadingRow
*/
@Composable
private fun LoadingRow() {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 8.dp),
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
CircularProgressIndicator(
modifier = Modifier.size(16.dp),
strokeWidth = 2.dp
)
Spacer(modifier = Modifier.width(10.dp))
Text(
text = stringResource(R.string.loading_location_notes),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
}
}
/**
* Empty row - matches iOS emptyRow
*/
@Composable
private fun EmptyRow() {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp)
) {
Text(
text = stringResource(R.string.location_notes_empty_title),
fontFamily = FontFamily.Monospace,
fontSize = 13.sp,
fontWeight = FontWeight.SemiBold,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.location_notes_empty_desc),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.6f)
)
}
}
/**
* Error row - matches iOS errorRow
*/
@Composable
private fun ErrorRow(message: String, onDismiss: () -> Unit) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 6.dp)
) {
Row(
horizontalArrangement = Arrangement.Start,
verticalAlignment = Alignment.CenterVertically
) {
Text(
text = "",
fontSize = 12.sp
)
Spacer(modifier = Modifier.width(6.dp))
Text(
text = message,
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.onSurface
)
}
Spacer(modifier = Modifier.height(4.dp))
Text(
text = stringResource(R.string.dismiss),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = MaterialTheme.colorScheme.primary,
modifier = Modifier.clickable(onClick = onDismiss)
)
}
}
/**
* Input section - matches main chat input exactly
*/
@Composable
private fun LocationNotesInputSection(
draft: String,
onDraftChange: (String) -> Unit,
sendButtonEnabled: Boolean,
accentGreen: Color,
backgroundColor: Color,
onSend: () -> Unit
) {
val isDark = isSystemInDarkTheme()
val colorScheme = MaterialTheme.colorScheme
Row(
modifier = Modifier
.fillMaxWidth()
.background(backgroundColor)
.padding(horizontal = 12.dp, vertical = 8.dp), // Match main chat padding
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.spacedBy(8.dp) // Match main chat spacing
) {
// Text input with placeholder overlay (matches main chat exactly)
Box(
modifier = Modifier.weight(1f)
) {
androidx.compose.foundation.text.BasicTextField(
value = draft,
onValueChange = onDraftChange,
textStyle = MaterialTheme.typography.bodyMedium.copy(
color = colorScheme.primary,
fontFamily = FontFamily.Monospace
),
cursorBrush = androidx.compose.ui.graphics.SolidColor(colorScheme.primary),
keyboardOptions = androidx.compose.foundation.text.KeyboardOptions(
imeAction = androidx.compose.ui.text.input.ImeAction.Send
),
keyboardActions = androidx.compose.foundation.text.KeyboardActions(
onSend = { if (sendButtonEnabled) onSend() }
),
modifier = Modifier.fillMaxWidth()
)
// Placeholder when empty (matches main chat)
if (draft.isEmpty()) {
Text(
text = stringResource(R.string.location_notes_input_placeholder),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = FontFamily.Monospace
),
color = colorScheme.onSurface.copy(alpha = 0.5f),
modifier = Modifier.fillMaxWidth()
)
}
}
// Send button - circular with icon (matches main chat exactly)
IconButton(
onClick = { if (sendButtonEnabled) onSend() },
enabled = sendButtonEnabled,
modifier = Modifier.size(32.dp)
) {
Box(
modifier = Modifier
.size(30.dp)
.background(
color = if (!sendButtonEnabled) {
colorScheme.onSurface.copy(alpha = 0.3f)
} else {
accentGreen.copy(alpha = 0.75f)
},
shape = CircleShape
),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Filled.ArrowUpward,
contentDescription = stringResource(R.string.send_message),
modifier = Modifier.size(20.dp),
tint = if (!sendButtonEnabled) {
colorScheme.onSurface.copy(alpha = 0.5f)
} else if (isDark) {
Color.Black // Black arrow on green in dark theme
} else {
Color.White // White arrow on green in light theme
}
)
}
}
}
}
/**
* Timestamp text - matches iOS timestampText exactly
* Shows relative time for < 7 days, absolute date otherwise
*/
private fun timestampText(createdAt: Int): String {
val date = Date(createdAt * 1000L)
val now = Date()
// Calculate days difference
val calendar = Calendar.getInstance()
calendar.time = date
val dateDay = calendar.get(Calendar.DAY_OF_YEAR)
val dateYear = calendar.get(Calendar.YEAR)
calendar.time = now
val nowDay = calendar.get(Calendar.DAY_OF_YEAR)
val nowYear = calendar.get(Calendar.YEAR)
val daysDiff = if (dateYear == nowYear) {
nowDay - dateDay
} else {
// Simplified: just check if less than 7 days by timestamp
val diff = (now.time - date.time) / (1000 * 60 * 60 * 24)
diff.toInt()
}
return if (daysDiff < 7) {
// Relative formatting (abbreviated)
val diffMillis = now.time - date.time
val diffSeconds = diffMillis / 1000
when {
diffSeconds < 60 -> "" // Don't show "just now" in iOS
diffSeconds < 3600 -> {
val minutes = (diffSeconds / 60).toInt()
"${minutes}m ago"
}
diffSeconds < 86400 -> {
val hours = (diffSeconds / 3600).toInt()
"${hours}h ago"
}
else -> {
val days = (diffSeconds / 86400).toInt()
"${days}d ago"
}
}
} else {
// Absolute date formatting
val sameYear = dateYear == nowYear
val formatter = if (sameYear) {
SimpleDateFormat("MMM d", Locale.getDefault())
} else {
SimpleDateFormat("MMM d, y", Locale.getDefault())
}
formatter.format(date)
}
}
@@ -0,0 +1,100 @@
package com.bitchat.android.ui
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.livedata.observeAsState
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import com.bitchat.android.geohash.GeohashChannelLevel
import com.bitchat.android.geohash.LocationChannelManager
/**
* Presenter component for LocationNotesSheet
* Handles sheet presentation logic with proper error states
* Extracts this logic from ChatScreen for better separation of concerns
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun LocationNotesSheetPresenter(
viewModel: ChatViewModel,
onDismiss: () -> Unit
) {
val context = LocalContext.current
val locationManager = remember { LocationChannelManager.getInstance(context) }
val availableChannels by locationManager.availableChannels.observeAsState(emptyList())
val nickname by viewModel.nickname.observeAsState("")
// iOS pattern: notesGeohash ?? LocationChannelManager.shared.availableChannels.first(where: { $0.level == .building })?.geohash
val buildingGeohash = availableChannels.firstOrNull { it.level == GeohashChannelLevel.BUILDING }?.geohash
if (buildingGeohash != null) {
// Get location name from locationManager
val locationNames by locationManager.locationNames.observeAsState(emptyMap())
val locationName = locationNames[GeohashChannelLevel.BUILDING]
?: locationNames[GeohashChannelLevel.BLOCK]
LocationNotesSheet(
geohash = buildingGeohash,
locationName = locationName,
nickname = nickname,
onDismiss = onDismiss
)
} else {
// No building geohash available - show error state (matches iOS)
LocationNotesErrorSheet(
onDismiss = onDismiss,
locationManager = locationManager
)
}
}
/**
* Error sheet when location is unavailable
*/
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun LocationNotesErrorSheet(
onDismiss: () -> Unit,
locationManager: LocationChannelManager
) {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
ModalBottomSheet(
onDismissRequest = onDismiss,
sheetState = sheetState,
containerColor = MaterialTheme.colorScheme.surface
) {
Column(
modifier = Modifier
.fillMaxWidth()
.padding(24.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text(
text = "Location Unavailable",
style = MaterialTheme.typography.titleMedium,
color = MaterialTheme.colorScheme.onSurface
)
Spacer(modifier = Modifier.height(16.dp))
Text(
text = "Location permission is required for notes",
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Spacer(modifier = Modifier.height(24.dp))
Button(onClick = {
// UNIFIED FIX: Enable location services first (user toggle)
locationManager.enableLocationServices()
// Then request location channels (which will also request permission if needed)
locationManager.enableLocationChannels()
locationManager.refreshChannels()
}) {
Text("Enable Location")
}
}
}
}
@@ -20,7 +20,7 @@ class MediaSendingManager(
) {
companion object {
private const val TAG = "MediaSendingManager"
private const val MAX_FILE_SIZE = 50 * 1024 * 1024 // 50MB limit
private const val MAX_FILE_SIZE = com.bitchat.android.util.AppConstants.Media.MAX_FILE_SIZE_BYTES // 50MB limit
}
// Track in-flight transfer progress: transferId -> messageId and reverse
@@ -275,6 +275,9 @@ class MediaSendingManager(
if (transferId != null) {
val cancelled = meshService.cancelFileTransfer(transferId)
if (cancelled) {
// Try to remove cached local file for this message (if any)
runCatching { findMessagePathById(messageId)?.let { java.io.File(it).delete() } }
// Remove the message from chat upon explicit cancel
messageManager.removeMessageById(messageId)
synchronized(transferMessageMap) {
@@ -285,6 +288,20 @@ class MediaSendingManager(
}
}
private fun findMessagePathById(messageId: String): String? {
// Search main timeline
state.getMessagesValue().firstOrNull { it.id == messageId }?.content?.let { return it }
// Search private chats
state.getPrivateChatsValue().values.forEach { list ->
list.firstOrNull { it.id == messageId }?.content?.let { return it }
}
// Search channel messages
state.getChannelMessagesValue().values.forEach { list ->
list.firstOrNull { it.id == messageId }?.content?.let { return it }
}
return null
}
/**
* Update progress for a transfer
*/
@@ -43,6 +43,9 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.shape.CircleShape
import com.bitchat.android.ui.media.FileMessageItem
import com.bitchat.android.model.BitchatMessageType
import com.bitchat.android.R
import androidx.compose.ui.res.stringResource
// VoiceNotePlayer moved to com.bitchat.android.ui.media.VoiceNotePlayer
@@ -334,11 +337,11 @@ fun MessageItem(
.clickable { onCancelTransfer?.invoke(message) },
contentAlignment = Alignment.Center
) {
Icon(imageVector = Icons.Filled.Close, contentDescription = "Cancel", tint = Color.White, modifier = Modifier.size(14.dp))
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(R.string.cd_cancel), tint = Color.White, modifier = Modifier.size(14.dp))
}
}
} else {
Text(text = "[file unavailable]", fontFamily = FontFamily.Monospace, color = Color.Gray)
Text(text = stringResource(R.string.file_unavailable), fontFamily = FontFamily.Monospace, color = Color.Gray)
}
}
}
@@ -471,7 +474,7 @@ fun DeliveryStatusIcon(status: DeliveryStatus) {
when (status) {
is DeliveryStatus.Sending -> {
Text(
text = "",
text = stringResource(R.string.status_sending),
fontSize = 10.sp,
color = colorScheme.primary.copy(alpha = 0.6f)
)
@@ -479,7 +482,7 @@ fun DeliveryStatusIcon(status: DeliveryStatus) {
is DeliveryStatus.Sent -> {
// Use a subtle hollow marker for Sent; single check is reserved for Delivered (iOS parity)
Text(
text = "",
text = stringResource(R.string.status_pending),
fontSize = 10.sp,
color = colorScheme.primary.copy(alpha = 0.6f)
)
@@ -487,14 +490,14 @@ fun DeliveryStatusIcon(status: DeliveryStatus) {
is DeliveryStatus.Delivered -> {
// Single check for Delivered (matches iOS expectations)
Text(
text = "",
text = stringResource(R.string.status_sent),
fontSize = 10.sp,
color = colorScheme.primary.copy(alpha = 0.8f)
)
}
is DeliveryStatus.Read -> {
Text(
text = "✓✓",
text = stringResource(R.string.status_delivered),
fontSize = 10.sp,
color = Color(0xFF007AFF), // Blue
fontWeight = FontWeight.Bold
@@ -502,7 +505,7 @@ fun DeliveryStatusIcon(status: DeliveryStatus) {
}
is DeliveryStatus.Failed -> {
Text(
text = "",
text = stringResource(R.string.status_failed),
fontSize = 10.sp,
color = Color.Red.copy(alpha = 0.8f)
)
@@ -510,7 +513,7 @@ fun DeliveryStatusIcon(status: DeliveryStatus) {
is DeliveryStatus.PartiallyDelivered -> {
// Show a single subdued check without numeric label
Text(
text = "",
text = stringResource(R.string.status_sent),
fontSize = 10.sp,
color = colorScheme.primary.copy(alpha = 0.6f)
)
@@ -13,8 +13,8 @@ class MessageManager(private val state: ChatState) {
// Message deduplication - FIXED: Prevent duplicate messages from dual connection paths
private val processedUIMessages = Collections.synchronizedSet(mutableSetOf<String>())
private val recentSystemEvents = Collections.synchronizedMap(mutableMapOf<String, Long>())
private val MESSAGE_DEDUP_TIMEOUT = 30000L // 30 seconds
private val SYSTEM_EVENT_DEDUP_TIMEOUT = 5000L // 5 seconds
private val MESSAGE_DEDUP_TIMEOUT = com.bitchat.android.util.AppConstants.UI.MESSAGE_DEDUP_TIMEOUT_MS // 30 seconds
private val SYSTEM_EVENT_DEDUP_TIMEOUT = com.bitchat.android.util.AppConstants.UI.SYSTEM_EVENT_DEDUP_TIMEOUT_MS // 5 seconds
// MARK: - Public Message Management
@@ -37,6 +37,7 @@ class MessageManager(private val state: ChatState) {
fun clearMessages() {
state.setMessages(emptyList())
state.setChannelMessages(emptyMap())
}
// MARK: - Channel Message Management
@@ -42,7 +42,7 @@ class NotificationManager(
private const val SUMMARY_NOTIFICATION_ID = 999
private const val GEOHASH_SUMMARY_NOTIFICATION_ID = 998
private const val ACTIVE_PEERS_NOTIFICATION_ID = 997
private const val ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL = 300_000L
private const val ACTIVE_PEERS_NOTIFICATION_TIME_INTERVAL = com.bitchat.android.util.AppConstants.UI.ACTIVE_PEERS_NOTIFICATION_INTERVAL_MS
// Intent extras for notification handling
const val EXTRA_OPEN_PRIVATE_CHAT = "open_private_chat"
@@ -258,7 +258,10 @@ class NotificationManager(
}
if (messageCount > 5) {
style.setSummaryText("and ${messageCount - 5} more")
val extra = messageCount - 5
style.setSummaryText(context.resources.getQuantityString(
R.plurals.notification_and_more, extra, extra
))
}
builder.setStyle(style)
@@ -291,11 +294,11 @@ class NotificationManager(
)
// Build notification content
val contentTitle = "👥 bitchatters nearby!"
val contentTitle = context.getString(R.string.notification_active_peers_title)
val contentText = if (peersSize == 1) {
"1 person around"
context.getString(R.string.notification_active_peers_one)
} else {
"$peersSize people around"
context.getString(R.string.notification_active_peers_many, peersSize)
}
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
@@ -331,8 +334,8 @@ class NotificationManager(
val builder = NotificationCompat.Builder(context, CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
.setContentTitle("bitchat")
.setContentText("$totalMessages messages from $senderCount people")
.setContentTitle(context.getString(R.string.app_name))
.setContentText(context.getString(R.string.notification_messages_from_people, totalMessages, senderCount))
.setContentIntent(pendingIntent)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
@@ -342,7 +345,7 @@ class NotificationManager(
// Add inbox style showing recent senders
val style = NotificationCompat.InboxStyle()
.setBigContentTitle("New Messages")
.setBigContentTitle(context.getString(R.string.notification_new_location_messages))
pendingNotifications.entries.take(5).forEach { (peerID, notifications) ->
val latestNotif = notifications.last()
@@ -356,7 +359,7 @@ class NotificationManager(
}
if (pendingNotifications.size > 5) {
style.setSummaryText("and ${pendingNotifications.size - 5} more conversations")
style.setSummaryText(context.getString(R.string.notification_more_conversations, pendingNotifications.size - 5))
}
builder.setStyle(style)
@@ -459,15 +462,15 @@ class NotificationManager(
// Build notification content with location name if available
val geohashDisplay = latestNotification.locationName?.let { "$it (#$geohash)" } ?: "#$geohash"
val contentTitle = when {
mentionCount > 0 && firstMessageCount > 0 && messageCount > 1 -> "Mentioned in $geohashDisplay (+${messageCount - 1} more)"
mentionCount > 0 -> if (mentionCount == 1) "Mentioned in $geohashDisplay" else "$mentionCount mentions in $geohashDisplay"
firstMessageCount > 0 -> "New activity in $geohashDisplay"
else -> "Messages in $geohashDisplay"
mentionCount > 0 && firstMessageCount > 0 && messageCount > 1 -> context.getString(R.string.notification_mentions_in_more, geohashDisplay, messageCount - 1)
mentionCount > 0 -> if (mentionCount == 1) context.getString(R.string.notification_mentions_in, geohashDisplay) else context.getString(R.string.notification_mentions_in_plural, mentionCount, geohashDisplay)
firstMessageCount > 0 -> context.getString(R.string.notification_new_activity_in, geohashDisplay)
else -> context.getString(R.string.notification_messages_in, geohashDisplay)
}
val contentText = when {
latestNotification.isMention -> "${latestNotification.senderNickname}: ${latestNotification.messageContent}"
latestNotification.isFirstMessage -> "${latestNotification.senderNickname} joined the conversation"
latestNotification.isFirstMessage -> context.getString(R.string.notification_joined_conversation, latestNotification.senderNickname)
else -> "${latestNotification.senderNickname}: ${latestNotification.messageContent}"
}
@@ -503,7 +506,8 @@ class NotificationManager(
}
if (messageCount > 5) {
style.setSummaryText("and ${messageCount - 5} more")
val extra = messageCount - 5
style.setSummaryText(context.resources.getQuantityString(R.plurals.notification_and_more, extra, extra))
}
builder.setStyle(style)
@@ -543,12 +547,12 @@ class NotificationManager(
)
val contentTitle = if (totalMentions > 0) {
"bitchat - $totalMentions mentions"
context.getString(R.string.notification_geohash_summary_title_mentions, totalMentions)
} else {
"bitchat - location chats"
context.getString(R.string.notification_geohash_summary_title)
}
val contentText = "$totalMessages messages from $geohashCount locations"
val contentText = context.getString(R.string.notification_geohash_summary_text, totalMessages, geohashCount)
val builder = NotificationCompat.Builder(context, GEOHASH_CHANNEL_ID)
.setSmallIcon(R.drawable.ic_notification)
@@ -563,7 +567,7 @@ class NotificationManager(
// Add inbox style showing recent geohashes
val style = NotificationCompat.InboxStyle()
.setBigContentTitle("New Location Messages")
.setBigContentTitle(context.getString(R.string.notification_new_messages))
pendingGeohashNotifications.entries.take(5).forEach { (geohash, notifications) ->
val mentionCount = notifications.count { it.isMention }
@@ -579,7 +583,7 @@ class NotificationManager(
}
if (pendingGeohashNotifications.size > 5) {
style.setSummaryText("and ${pendingGeohashNotifications.size - 5} more locations")
style.setSummaryText(context.getString(R.string.notification_more_locations, pendingGeohashNotifications.size - 5))
}
builder.setStyle(style)
@@ -676,9 +680,9 @@ class NotificationManager(
// Build notification content
val contentTitle = if (messageCount == 1) {
"Mentioned in Mesh Chat"
context.getString(R.string.notification_mesh_mention_title_singular)
} else {
"$messageCount mentions in Mesh Chat"
context.getString(R.string.notification_mesh_mention_title_plural, messageCount)
}
val contentText = "${latestNotification.senderNickname}: ${latestNotification.messageContent}"
@@ -710,7 +714,8 @@ class NotificationManager(
}
if (messageCount > 5) {
style.setSummaryText("and ${messageCount - 5} more")
val extra = messageCount - 5
style.setSummaryText(context.resources.getQuantityString(R.plurals.notification_and_more, extra, extra))
}
builder.setStyle(style)
@@ -0,0 +1,28 @@
package com.bitchat.android.ui
import android.content.pm.ActivityInfo
import android.os.Bundle
import androidx.activity.ComponentActivity
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() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setOrientationBasedOnDeviceType()
}
private fun setOrientationBasedOnDeviceType() {
requestedOrientation = if (DeviceUtils.isTablet(this)) {
// Allow all orientations on tablets
ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
} else {
// Lock to portrait on phones
ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
}
}
}
@@ -15,6 +15,8 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.bitchat.android.nostr.NostrProofOfWork
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import com.bitchat.android.nostr.PoWPreferenceManager
/**
@@ -54,7 +56,7 @@ fun PoWStatusIndicator(
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "Mining PoW",
contentDescription = stringResource(R.string.cd_mining_pow),
tint = Color(0xFFFF9500), // Orange for mining
modifier = Modifier
.size(12.dp)
@@ -63,7 +65,7 @@ fun PoWStatusIndicator(
} else {
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "PoW Enabled",
contentDescription = stringResource(R.string.cd_pow_enabled),
tint = if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D), // Green when ready
modifier = Modifier.size(12.dp)
)
@@ -85,7 +87,7 @@ fun PoWStatusIndicator(
// PoW icon
Icon(
imageVector = Icons.Filled.Security,
contentDescription = "Proof of Work",
contentDescription = stringResource(R.string.cd_proof_of_work),
tint = if (isMining) Color(0xFFFF9500) else {
if (isDark) Color(0xFF32D74B) else Color(0xFF248A3D)
},
@@ -95,9 +97,9 @@ fun PoWStatusIndicator(
// Status text
Text(
text = if (isMining) {
"mining..."
stringResource(R.string.pow_mining_ellipsis)
} else {
"pow: ${powDifficulty}bit"
stringResource(R.string.pow_label_format, powDifficulty)
},
fontSize = 11.sp,
fontFamily = FontFamily.Monospace,
@@ -109,7 +111,7 @@ fun PoWStatusIndicator(
// Time estimate
if (!isMining && powDifficulty > 0) {
Text(
text = "(~${NostrProofOfWork.estimateMiningTime(powDifficulty)})",
text = stringResource(R.string.pow_time_estimate, NostrProofOfWork.estimateMiningTime(powDifficulty)),
fontSize = 9.sp,
fontFamily = FontFamily.Monospace,
color = colorScheme.onSurface.copy(alpha = 0.5f)
@@ -237,7 +237,7 @@ fun ChannelsSection(
) {
Icon(
imageVector = Icons.Default.Close,
contentDescription = "Leave channel",
contentDescription = stringResource(com.bitchat.android.R.string.cd_leave_channel),
modifier = Modifier.size(14.dp),
tint = colorScheme.onSurface.copy(alpha = 0.5f)
)
@@ -552,7 +552,7 @@ private fun PeerItem(
// Show mail icon for unread DMs (iOS orange)
Icon(
imageVector = Icons.Filled.Email,
contentDescription = "Unread message",
contentDescription = stringResource(com.bitchat.android.R.string.cd_unread_message),
modifier = Modifier.size(16.dp),
tint = Color(0xFFFF9500) // iOS orange
)
@@ -562,7 +562,7 @@ private fun PeerItem(
// Purple globe to indicate Nostr availability
Icon(
imageVector = Icons.Filled.Public,
contentDescription = "Reachable via Nostr",
contentDescription = stringResource(com.bitchat.android.R.string.cd_reachable_via_nostr),
modifier = Modifier.size(16.dp),
tint = Color(0xFF9C27B0) // Purple
)
@@ -571,7 +571,7 @@ private fun PeerItem(
Icon(
//painter = androidx.compose.ui.res.painterResource(id = R.drawable.ic_offline_favorite),
imageVector = Icons.Outlined.Circle,
contentDescription = "Offline favorite",
contentDescription = stringResource(com.bitchat.android.R.string.cd_offline_favorite),
modifier = Modifier.size(16.dp),
tint = Color.Gray
)
@@ -15,6 +15,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.unit.dp
@@ -129,7 +130,7 @@ fun VoiceRecordButton(
) {
Icon(
imageVector = Icons.Filled.Mic,
contentDescription = "Record voice note",
contentDescription = stringResource(com.bitchat.android.R.string.cd_record_voice),
tint = Color.Black,
modifier = Modifier.size(20.dp)
)
@@ -29,6 +29,8 @@ import kotlinx.coroutines.launch
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.graphics.drawscope.drawIntoCanvas
import androidx.compose.ui.graphics.nativeCanvas
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
@Composable
fun MeshTopologySection() {
@@ -182,10 +184,10 @@ fun DebugSettingsSheet(
item {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.BugReport, contentDescription = null, tint = Color(0xFFFF9500))
Text("debug tools", fontFamily = FontFamily.Monospace, fontSize = 18.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_tools), fontFamily = FontFamily.Monospace, fontSize = 18.sp, fontWeight = FontWeight.Medium)
}
Text(
text = "developer utilities for diagnostics and control",
text = stringResource(R.string.debug_tools_desc),
fontFamily = FontFamily.Monospace,
fontSize = 12.sp,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -198,12 +200,12 @@ fun DebugSettingsSheet(
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.SettingsEthernet, contentDescription = null, tint = Color(0xFF00C851))
Text("verbose logging", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_verbose_logging), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.weight(1f))
Switch(checked = verboseLogging, onCheckedChange = { manager.setVerboseLoggingEnabled(it) })
}
Text(
"logs peer joins/leaves, connection direction, packet routing and relays",
stringResource(R.string.debug_verbose_hint),
fontFamily = FontFamily.Monospace,
fontSize = 11.sp,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -223,10 +225,10 @@ fun DebugSettingsSheet(
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.Bluetooth, contentDescription = null, tint = Color(0xFF007AFF))
Text("bluetooth roles", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_bluetooth_roles), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text("gatt server", fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Text(stringResource(R.string.debug_gatt_server), fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Switch(checked = gattServerEnabled, onCheckedChange = {
manager.setGattServerEnabled(it)
scope.launch {
@@ -235,9 +237,9 @@ fun DebugSettingsSheet(
})
}
val serverCount = connectedDevices.count { it.connectionType == ConnectionType.GATT_SERVER }
Text("connections: $serverCount / $maxServer", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_connections_fmt, serverCount, maxServer), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Row(verticalAlignment = Alignment.CenterVertically) {
Text("max server", fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Text(stringResource(R.string.debug_max_server), fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Slider(
value = maxServer.toFloat(),
onValueChange = { manager.setMaxServerConnections(it.toInt().coerceAtLeast(1)) },
@@ -246,7 +248,7 @@ fun DebugSettingsSheet(
)
}
Row(verticalAlignment = Alignment.CenterVertically) {
Text("gatt client", fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Text(stringResource(R.string.debug_gatt_client), fontFamily = FontFamily.Monospace, modifier = Modifier.weight(1f))
Switch(checked = gattClientEnabled, onCheckedChange = {
manager.setGattClientEnabled(it)
scope.launch {
@@ -255,9 +257,9 @@ fun DebugSettingsSheet(
})
}
val clientCount = connectedDevices.count { it.connectionType == ConnectionType.GATT_CLIENT }
Text("connections: $clientCount / $maxClient", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_connections_fmt, clientCount, maxClient), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Row(verticalAlignment = Alignment.CenterVertically) {
Text("max client", fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Text(stringResource(R.string.debug_max_client), fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Slider(
value = maxClient.toFloat(),
onValueChange = { manager.setMaxClientConnections(it.toInt().coerceAtLeast(1)) },
@@ -266,9 +268,9 @@ fun DebugSettingsSheet(
)
}
val overallCount = connectedDevices.size
Text("connections: $overallCount / $maxOverall", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_overall_connections_fmt, overallCount, maxOverall), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Row(verticalAlignment = Alignment.CenterVertically) {
Text("max overall", fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Text(stringResource(R.string.debug_max_overall), fontFamily = FontFamily.Monospace, modifier = Modifier.width(90.dp))
Slider(
value = maxOverall.toFloat(),
onValueChange = { manager.setMaxConnectionsOverall(it.toInt().coerceAtLeast(1)) },
@@ -277,7 +279,7 @@ fun DebugSettingsSheet(
)
}
Text(
"turn roles on/off and close all connections when disabled",
stringResource(R.string.debug_roles_hint),
fontFamily = FontFamily.Monospace,
fontSize = 11.sp,
color = colorScheme.onSurface.copy(alpha = 0.7f)
@@ -292,12 +294,12 @@ fun DebugSettingsSheet(
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.PowerSettingsNew, contentDescription = null, tint = Color(0xFFFF9500))
Text("packet relay", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_packet_relay), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.weight(1f))
Switch(checked = packetRelayEnabled, onCheckedChange = { manager.setPacketRelayEnabled(it) })
}
Text("since start: ${relayStats.totalRelaysCount}", fontFamily = FontFamily.Monospace, fontSize = 11.sp)
Text("last 10s: ${relayStats.last10SecondRelays} • 1m: ${relayStats.lastMinuteRelays} • 15m: ${relayStats.last15MinuteRelays}", fontFamily = FontFamily.Monospace, fontSize = 11.sp)
Text(stringResource(R.string.debug_since_start_fmt, relayStats.totalRelaysCount), fontFamily = FontFamily.Monospace, fontSize = 11.sp)
Text(stringResource(R.string.debug_relays_window_fmt, relayStats.last10SecondRelays, relayStats.lastMinuteRelays, relayStats.last15MinuteRelays), fontFamily = FontFamily.Monospace, fontSize = 11.sp)
// Realtime graph: per-second relays, full-width canvas, bottom-up bars, fast decay
var series by remember { mutableStateOf(List(60) { 0f }) }
LaunchedEffect(isPresented) {
@@ -428,29 +430,32 @@ fun MeshTopologySection() {
Icon(Icons.Filled.SettingsEthernet, contentDescription = null, tint = Color(0xFF9C27B0))
Text("sync settings", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
}
Text("max packets per sync: $seenCapacity", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_max_packets_per_sync_fmt, seenCapacity), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Slider(value = seenCapacity.toFloat(), onValueChange = { manager.setSeenPacketCapacity(it.toInt()) }, valueRange = 10f..1000f, steps = 99)
Text("max GCS filter size: $gcsMaxBytes bytes (1281024)", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_max_gcs_filter_size_fmt, gcsMaxBytes), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Slider(value = gcsMaxBytes.toFloat(), onValueChange = { manager.setGcsMaxBytes(it.toInt()) }, valueRange = 128f..1024f, steps = 0)
Text("target FPR: ${String.format("%.2f", gcsFpr)}%", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_target_fpr_fmt, gcsFpr), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Slider(value = gcsFpr.toFloat(), onValueChange = { manager.setGcsFprPercent(it.toDouble()) }, valueRange = 0.1f..5.0f, steps = 49)
val p = remember(gcsFpr) { com.bitchat.android.sync.GCSFilter.deriveP(gcsFpr / 100.0) }
val nmax = remember(gcsFpr, gcsMaxBytes) { com.bitchat.android.sync.GCSFilter.estimateMaxElementsForSize(gcsMaxBytes, p) }
Text("derived P: $p • est. max elements: $nmax", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_derived_p_fmt, p.toString(), nmax.toString()), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
}
}
}
// Connected devices
item {
Surface(shape = RoundedCornerShape(12.dp), color = colorScheme.surfaceVariant.copy(alpha = 0.2f)) {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.Devices, contentDescription = null, tint = Color(0xFF4CAF50))
Text("connected devices", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_connected_devices), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
}
val localAddr = remember { meshService.connectionManager.getLocalAdapterAddress() }
Text("our device id: ${localAddr ?: "unknown"}", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text(stringResource(R.string.debug_our_device_id_fmt, localAddr ?: stringResource(R.string.unknown)), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
if (connectedDevices.isEmpty()) {
Text("none", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.6f))
} else {
@@ -458,11 +463,11 @@ fun MeshTopologySection() {
Surface(shape = RoundedCornerShape(8.dp), color = colorScheme.surface.copy(alpha = 0.6f)) {
Row(Modifier.fillMaxWidth().padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text("${dev.peerID ?: "unknown"}${dev.deviceAddress}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
val roleLabel = if (dev.connectionType == ConnectionType.GATT_SERVER) "as server (we host)" else "as client (we connect)"
Text("${dev.nickname ?: ""}RSSI: ${dev.rssi ?: "?"}$roleLabel${if (dev.isDirectConnection) " • direct" else ""}", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text((dev.peerID ?: stringResource(R.string.unknown)) + "${dev.deviceAddress}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
val roleLabel = if (dev.connectionType == ConnectionType.GATT_SERVER) stringResource(R.string.debug_role_server) else stringResource(R.string.debug_role_client)
Text("${dev.nickname ?: ""}" + stringResource(R.string.debug_rssi_fmt, dev.rssi ?: stringResource(R.string.debug_question_mark)) + "$roleLabel" + (if (dev.isDirectConnection) stringResource(R.string.debug_direct_suffix) else ""), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
}
Text("disconnect", color = Color(0xFFBF1A1A), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
Text(stringResource(R.string.debug_disconnect), color = Color(0xFFBF1A1A), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
meshService.connectionManager.disconnectAddress(dev.deviceAddress)
})
}
@@ -479,19 +484,19 @@ fun MeshTopologySection() {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.Bluetooth, contentDescription = null, tint = Color(0xFF007AFF))
Text("recent scan results", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_recent_scan_results), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
}
if (scanResults.isEmpty()) {
Text("none", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.6f))
Text(stringResource(R.string.debug_none), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.6f))
} else {
scanResults.forEach { res ->
Surface(shape = RoundedCornerShape(8.dp), color = colorScheme.surface.copy(alpha = 0.6f)) {
Row(Modifier.fillMaxWidth().padding(10.dp), verticalAlignment = Alignment.CenterVertically) {
Column(Modifier.weight(1f)) {
Text("${res.peerID ?: "unknown"}${res.deviceAddress}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
Text("${res.deviceName ?: ""} • RSSI: ${res.rssi}", fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
Text((res.peerID ?: stringResource(R.string.unknown)) + "${res.deviceAddress}", fontFamily = FontFamily.Monospace, fontSize = 12.sp)
Text(stringResource(R.string.debug_rssi_fmt, res.rssi.toString()), fontFamily = FontFamily.Monospace, fontSize = 11.sp, color = colorScheme.onSurface.copy(alpha = 0.7f))
}
Text("connect", color = Color(0xFF00C851), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
Text(stringResource(R.string.debug_connect), color = Color(0xFF00C851), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
meshService.connectionManager.connectToAddress(res.deviceAddress)
})
}
@@ -508,9 +513,9 @@ fun MeshTopologySection() {
Column(Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
Icon(Icons.Filled.BugReport, contentDescription = null, tint = Color(0xFFFF9500))
Text("debug console", fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Text(stringResource(R.string.debug_debug_console), fontFamily = FontFamily.Monospace, fontSize = 14.sp, fontWeight = FontWeight.Medium)
Spacer(Modifier.weight(1f))
Text("clear", color = Color(0xFFBF1A1A), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
Text(stringResource(R.string.debug_clear), color = Color(0xFFBF1A1A), fontFamily = FontFamily.Monospace, modifier = Modifier.clickable {
manager.clearDebugMessages()
})
}
@@ -19,6 +19,8 @@ import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import com.bitchat.android.mesh.BluetoothMeshService
import com.bitchat.android.model.BitchatMessage
import androidx.compose.material3.ColorScheme
@@ -91,7 +93,7 @@ fun AudioMessageItem(
.clickable { onCancelTransfer?.invoke(message) },
contentAlignment = Alignment.Center
) {
Icon(imageVector = Icons.Filled.Close, contentDescription = "Cancel", tint = Color.White, modifier = Modifier.size(16.dp))
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(R.string.cd_cancel), tint = Color.White, modifier = Modifier.size(16.dp))
}
}
}
@@ -19,6 +19,8 @@ import androidx.compose.material3.CardDefaults
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
@@ -28,6 +30,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import com.bitchat.android.features.file.FileUtils
import com.bitchat.android.model.BitchatFilePacket
@@ -60,7 +63,7 @@ fun FileMessageItem(
// File icon
Icon(
imageVector = Icons.Filled.Description,
contentDescription = "File",
contentDescription = stringResource(com.bitchat.android.R.string.cd_file),
tint = getFileIconColor(packet.fileName),
modifier = Modifier.size(32.dp)
)
@@ -70,13 +73,13 @@ fun FileMessageItem(
verticalArrangement = Arrangement.spacedBy(4.dp)
) {
// File name
Text(
text = packet.fileName,
style = MaterialTheme.typography.bodyLarge,
fontWeight = androidx.compose.ui.text.font.FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
Text(
text = packet.fileName,
style = MaterialTheme.typography.bodyLarge,
fontWeight = androidx.compose.ui.text.font.FontWeight.Medium,
maxLines = 1,
overflow = TextOverflow.Ellipsis
)
// File details
Row(
@@ -14,6 +14,8 @@ import androidx.compose.ui.draw.rotate
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import com.bitchat.android.features.file.FileUtils
@Composable
@@ -44,7 +46,7 @@ fun FilePickerButton(
) {
Icon(
imageVector = Icons.Filled.Attachment,
contentDescription = "Pick file",
contentDescription = stringResource(R.string.cd_pick_file),
tint = Color.Gray,
modifier = Modifier.size(20.dp).rotate(90f)
)
@@ -28,6 +28,9 @@ import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.unit.dp
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import kotlinx.coroutines.delay
/**
@@ -77,7 +80,7 @@ fun FileSendingAnimation(
// File icon
Icon(
imageVector = Icons.Filled.Description,
contentDescription = "File",
contentDescription = stringResource(R.string.cd_file),
tint = Color(0xFF00C851), // Green like app theme
modifier = Modifier.size(32.dp)
)
@@ -102,7 +105,7 @@ fun FileSendingAnimation(
// Blinking cursor (only if not fully revealed)
if (animatedChars < fileName.length && showCursor) {
androidx.compose.material3.Text(
text = "_",
text = stringResource(R.string.underscore),
style = MaterialTheme.typography.bodyMedium.copy(
fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace,
color = Color.White
@@ -132,10 +135,12 @@ private fun FileProgressBars(
val filledBars = (progress * bars).toInt()
// Create a matrix-style progress bar string
val ctx = LocalContext.current
val progressString = buildString {
val brackets = ctx.getString(R.string.progress_bar_brackets, "", 0)
append("[")
for (i in 0 until bars) {
append(if (i < filledBars) "" else "")
append(if (i < filledBars) ctx.getString(R.string.progress_filled) else ctx.getString(R.string.progress_empty))
}
append("] ")
append("${(progress * 100).toInt()}%")
@@ -20,9 +20,11 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import com.bitchat.android.R
import com.bitchat.android.features.file.FileUtils
import com.bitchat.android.model.BitchatFilePacket
import kotlinx.coroutines.launch
@@ -54,7 +56,7 @@ fun FileViewerDialog(
) {
// File received header
Text(
text = "📎 File Received",
text = stringResource(R.string.file_viewer_title),
style = MaterialTheme.typography.headlineSmall,
color = MaterialTheme.colorScheme.primary
)
@@ -65,17 +67,17 @@ fun FileViewerDialog(
horizontalAlignment = Alignment.Start
) {
Text(
text = "📄 ${packet.fileName}",
text = stringResource(R.string.file_viewer_name, packet.fileName),
style = MaterialTheme.typography.bodyLarge,
fontWeight = androidx.compose.ui.text.font.FontWeight.Medium
)
Text(
text = "📏 Size: ${FileUtils.formatFileSize(packet.fileSize)}",
text = stringResource(R.string.file_viewer_size, FileUtils.formatFileSize(packet.fileSize)),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = "🏷️ Type: ${packet.mimeType}",
text = stringResource(R.string.file_viewer_type, packet.mimeType),
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
@@ -108,7 +110,7 @@ fun FileViewerDialog(
containerColor = MaterialTheme.colorScheme.primary
)
) {
Text("📂 Open / Save")
Text(stringResource(R.string.file_viewer_open_save))
}
// Dismiss button
@@ -119,13 +121,13 @@ fun FileViewerDialog(
containerColor = MaterialTheme.colorScheme.secondary
)
) {
Text("❌ Close")
Text(stringResource(R.string.close_with_emoji))
}
}
}
}
}
}
}
/**
* Attempts to open a file using system viewers or save to device
@@ -32,6 +32,8 @@ import androidx.compose.foundation.Image
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
import java.io.File
/**
@@ -75,13 +77,13 @@ fun FullScreenImageViewer(imagePaths: List<String>, initialIndex: Int = 0, onClo
bmp?.let {
androidx.compose.foundation.Image(
bitmap = it.asImageBitmap(),
contentDescription = "Image ${page + 1} of ${imagePaths.size}",
contentDescription = stringResource(R.string.cd_image_index_of, page + 1, imagePaths.size),
modifier = Modifier.fillMaxSize(),
contentScale = ContentScale.Fit
)
} ?: run {
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text(text = "Image unavailable", color = Color.White)
Text(text = stringResource(R.string.image_unavailable), color = Color.White)
}
}
}
@@ -96,7 +98,7 @@ fun FullScreenImageViewer(imagePaths: List<String>, initialIndex: Int = 0, onClo
.padding(horizontal = 12.dp, vertical = 4.dp)
) {
Text(
text = "${(pagerState.currentPage ?: 0) + 1} / ${imagePaths.size}",
text = stringResource(R.string.image_counter, (pagerState.currentPage ?: 0) + 1, imagePaths.size),
color = Color.White,
fontSize = 14.sp,
fontFamily = androidx.compose.ui.text.font.FontFamily.Monospace
@@ -118,7 +120,7 @@ fun FullScreenImageViewer(imagePaths: List<String>, initialIndex: Int = 0, onClo
.clickable { saveToDownloads(context, imagePaths[pagerState.currentPage].toString()) },
contentAlignment = Alignment.Center
) {
androidx.compose.material3.Icon(Icons.Filled.Download, "Save current image", tint = Color.White)
androidx.compose.material3.Icon(Icons.Filled.Download, stringResource(R.string.cd_save_current_image), tint = Color.White)
}
Spacer(Modifier.width(12.dp))
Box(
@@ -128,7 +130,7 @@ fun FullScreenImageViewer(imagePaths: List<String>, initialIndex: Int = 0, onClo
.clickable { onClose() },
contentAlignment = Alignment.Center
) {
androidx.compose.material3.Icon(Icons.Filled.Close, "Close", tint = Color.White)
androidx.compose.material3.Icon(Icons.Filled.Close, stringResource(R.string.cd_close), tint = Color.White)
}
}
}
@@ -161,10 +163,10 @@ private fun saveToDownloads(context: android.content.Context, path: String) {
context.contentResolver.update(uri, v2, null, null)
}
// Show toast message indicating the image has been saved
Toast.makeText(context, "Image saved to Downloads", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.toast_image_saved), Toast.LENGTH_SHORT).show()
}
}.onFailure {
// Optionally handle failure case (e.g., show error toast)
Toast.makeText(context, "Failed to save image", Toast.LENGTH_SHORT).show()
Toast.makeText(context, context.getString(R.string.toast_failed_to_save_image), Toast.LENGTH_SHORT).show()
}
}
@@ -16,15 +16,17 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.hapticfeedback.HapticFeedbackType
import androidx.compose.ui.platform.LocalHapticFeedback
import androidx.compose.ui.text.TextLayoutResult
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.text.font.FontFamily
import com.bitchat.android.mesh.BluetoothMeshService
import com.bitchat.android.model.BitchatMessage
import com.bitchat.android.model.BitchatMessageType
@@ -113,7 +115,7 @@ fun ImageMessageItem(
// Fully revealed image
Image(
bitmap = img,
contentDescription = "Image",
contentDescription = stringResource(com.bitchat.android.R.string.cd_image),
modifier = Modifier
.widthIn(max = 300.dp)
.aspectRatio(aspect)
@@ -137,13 +139,13 @@ fun ImageMessageItem(
.clickable { onCancelTransfer?.invoke(message) },
contentAlignment = Alignment.Center
) {
Icon(imageVector = Icons.Filled.Close, contentDescription = "Cancel", tint = Color.White, modifier = Modifier.size(14.dp))
Icon(imageVector = Icons.Filled.Close, contentDescription = stringResource(com.bitchat.android.R.string.cd_cancel), tint = Color.White, modifier = Modifier.size(14.dp))
}
}
}
}
} else {
Text(text = "[image unavailable]", fontFamily = FontFamily.Monospace, color = Color.Gray)
Text(text = stringResource(com.bitchat.android.R.string.image_unavailable), fontFamily = FontFamily.Monospace, color = Color.Gray)
}
}
}
@@ -1,25 +1,37 @@
package com.bitchat.android.ui.media
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.combinedClickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.size
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Camera
import androidx.compose.material.icons.filled.Photo
import androidx.compose.material.icons.filled.PhotoCamera
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.core.content.FileProvider
import com.bitchat.android.features.media.ImageUtils
import java.io.File
@OptIn(ExperimentalFoundationApi::class)
@Composable
fun ImagePickerButton(
modifier: Modifier = Modifier,
onImageReady: (String) -> Unit
) {
val context = LocalContext.current
var capturedImagePath by remember { mutableStateOf<String?>(null) }
val imagePicker = rememberLauncherForActivityResult(
contract = ActivityResultContracts.GetContent()
) { uri: android.net.Uri? ->
@@ -28,17 +40,57 @@ fun ImagePickerButton(
if (!outPath.isNullOrBlank()) onImageReady(outPath)
}
}
val takePictureLauncher = rememberLauncherForActivityResult(
contract = ActivityResultContracts.TakePicture()
) { success ->
val path = capturedImagePath
if (success && !path.isNullOrBlank()) {
// Downscale + correct orientation, then send; delete original
val outPath = com.bitchat.android.features.media.ImageUtils.downscalePathAndSaveToAppFiles(context, path)
if (!outPath.isNullOrBlank()) {
onImageReady(outPath)
}
runCatching { File(path).delete() }
} else {
// Cleanup on cancel/failure
path?.let { runCatching { File(it).delete() } }
}
capturedImagePath = null
}
IconButton(
onClick = { imagePicker.launch("image/*") },
modifier = modifier.size(32.dp)
fun startCameraCapture() {
try {
val dir = File(context.filesDir, "images/outgoing").apply { mkdirs() }
val file = File(dir, "camera_${System.currentTimeMillis()}.jpg")
val uri = FileProvider.getUriForFile(
context,
context.packageName + ".fileprovider",
file
)
capturedImagePath = file.absolutePath
takePictureLauncher.launch(uri)
} catch (_: Exception) {
// Ignore errors; no-op
}
}
Box(
modifier = modifier
.size(32.dp)
.combinedClickable(
onClick = { imagePicker.launch("image/*") },
onLongClick = { startCameraCapture() }
),
contentAlignment = Alignment.Center
) {
Icon(
imageVector = Icons.Filled.Photo,
contentDescription = "Pick image",
imageVector = Icons.Filled.PhotoCamera,
contentDescription = stringResource(com.bitchat.android.R.string.pick_image),
tint = Color.Gray,
modifier = Modifier.size(20.dp)
)
}
}
// No custom preview: native camera UI handles confirmation
}
@@ -26,6 +26,8 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import androidx.compose.ui.res.stringResource
import com.bitchat.android.R
/**
* Media picker that offers image and file options
@@ -53,7 +55,7 @@ fun MediaPickerOptions(
) {
Icon(
imageVector = Icons.Filled.Add,
contentDescription = "Pick media",
contentDescription = stringResource(R.string.cd_pick_media),
tint = Color.Black,
modifier = Modifier.size(20.dp)
)
@@ -98,7 +100,7 @@ fun MediaPickerOptions(
modifier = Modifier.size(16.dp)
)
androidx.compose.material3.Text(
text = "Image",
text = stringResource(R.string.media_type_image),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onPrimaryContainer
)
@@ -126,7 +128,7 @@ fun MediaPickerOptions(
modifier = Modifier.size(16.dp)
)
androidx.compose.material3.Text(
text = "File",
text = stringResource(R.string.media_type_file),
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSecondaryContainer
)
@@ -7,7 +7,7 @@ import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.sp
// Base font size for consistent scaling across the app
const val BASE_FONT_SIZE = 15 // sp - increased from 14sp for better readability
internal const val BASE_FONT_SIZE = com.bitchat.android.util.AppConstants.UI.BASE_FONT_SIZE_SP // sp - increased from 14sp for better readability
// Typography matching the iOS monospace design - using BASE_FONT_SIZE for consistency
val Typography = Typography(
@@ -0,0 +1,127 @@
package com.bitchat.android.util
import java.util.UUID
/**
* Centralized application-wide constants.
*/
object AppConstants {
// Packet time-to-live (hops)
val MESSAGE_TTL_HOPS: UByte = 7u // Default TTL for regular packets
val SYNC_TTL_HOPS: UByte = 0u // TTL for neighbor-only sync packets
object Mesh {
// Peer lifecycle
const val STALE_PEER_TIMEOUT_MS: Long = 180_000L // 3 minutes
const val PEER_CLEANUP_INTERVAL_MS: Long = 60_000L
// BLE connection tracking
const val CONNECTION_RETRY_DELAY_MS: Long = 5_000L
const val MAX_CONNECTION_ATTEMPTS: Int = 3
const val CONNECTION_CLEANUP_DELAY_MS: Long = 500L
const val CONNECTION_CLEANUP_INTERVAL_MS: Long = 30_000L
const val BROADCAST_CLEANUP_DELAY_MS: Long = 500L
// GATT client RSSI updates
const val RSSI_UPDATE_INTERVAL_MS: Long = 5_000L
object Gatt {
val SERVICE_UUID: UUID = UUID.fromString("F47B5E2D-4A9E-4C5A-9B3F-8E1D2C3A4B5C")
val CHARACTERISTIC_UUID: UUID = UUID.fromString("A1B2C3D4-E5F6-4A5B-8C9D-0E1F2A3B4C5D")
val DESCRIPTOR_UUID: UUID = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb")
}
}
object Sync {
const val CLEANUP_INTERVAL_MS: Long = 60_000L
}
object Fragmentation {
const val FRAGMENT_SIZE_THRESHOLD: Int = 512
const val MAX_FRAGMENT_SIZE: Int = 469
const val FRAGMENT_TIMEOUT_MS: Long = 30_000L
const val CLEANUP_INTERVAL_MS: Long = 10_000L
}
object Security {
const val MESSAGE_TIMEOUT_MS: Long = 300_000L
const val CLEANUP_INTERVAL_MS: Long = 300_000L
const val MAX_PROCESSED_MESSAGES: Int = 10_000
const val MAX_PROCESSED_KEY_EXCHANGES: Int = 1_000
}
object Noise {
const val REKEY_TIME_LIMIT_MS: Long = 3_600_000L // 1 hour
const val REKEY_MESSAGE_LIMIT_ENCRYPTION: Long = 1_000L // per session, encryption service policy
const val REKEY_MESSAGE_LIMIT_SESSION: Long = 10_000L // session-level ceiling
const val MAX_PAYLOAD_SIZE_BYTES: Int = 256
const val HIGH_NONCE_WARNING_THRESHOLD: Long = 1_000_000_000L
}
object Protocol {
const val COMPRESSION_THRESHOLD_BYTES: Int = 100
}
object StoreForward {
const val MESSAGE_CACHE_TIMEOUT_MS: Long = 43_200_000L // 12h
const val MAX_CACHED_MESSAGES: Int = 100
const val MAX_CACHED_MESSAGES_FAVORITES: Int = 1_000
const val CLEANUP_INTERVAL_MS: Long = 600_000L
}
object Power {
const val CRITICAL_BATTERY_PERCENT: Int = 10
const val LOW_BATTERY_PERCENT: Int = 20
const val MEDIUM_BATTERY_PERCENT: Int = 50
const val SCAN_ON_DURATION_NORMAL_MS: Long = 8_000L
const val SCAN_OFF_DURATION_NORMAL_MS: Long = 2_000L
const val SCAN_ON_DURATION_POWER_SAVE_MS: Long = 2_000L
const val SCAN_OFF_DURATION_POWER_SAVE_MS: Long = 8_000L
const val SCAN_ON_DURATION_ULTRA_LOW_MS: Long = 1_000L
const val SCAN_OFF_DURATION_ULTRA_LOW_MS: Long = 10_000L
const val MAX_CONNECTIONS_NORMAL: Int = 8
const val MAX_CONNECTIONS_POWER_SAVE: Int = 4
const val MAX_CONNECTIONS_ULTRA_LOW: Int = 2
}
object Nostr {
// Relay backoff
const val INITIAL_BACKOFF_INTERVAL_MS: Long = 1_000L
const val MAX_BACKOFF_INTERVAL_MS: Long = 300_000L
const val BACKOFF_MULTIPLIER: Double = 2.0
const val MAX_RECONNECT_ATTEMPTS: Int = 10
// Transport
const val READ_ACK_INTERVAL_MS: Long = 350L
// Deduplicator
const val DEFAULT_DEDUP_CAPACITY: Int = 10_000
// Relay subscription validation
const val SUBSCRIPTION_VALIDATION_INTERVAL_MS: Long = 30_000L
}
object Tor {
const val DEFAULT_SOCKS_PORT: Int = 9060
const val RESTART_DELAY_MS: Long = 2_000L
const val INACTIVITY_TIMEOUT_MS: Long = 5_000L
const val MAX_RETRY_ATTEMPTS: Int = 5
const val STOP_TIMEOUT_MS: Long = 7_000L
}
object UI {
const val MAX_NICKNAME_LENGTH: Int = 15
const val BASE_FONT_SIZE_SP: Int = 15
const val MESSAGE_DEDUP_TIMEOUT_MS: Long = 30_000L
const val SYSTEM_EVENT_DEDUP_TIMEOUT_MS: Long = 5_000L
const val ACTIVE_PEERS_NOTIFICATION_INTERVAL_MS: Long = 300_000L
}
object Media {
const val MAX_FILE_SIZE_BYTES: Long = 50L * 1024 * 1024
}
object Services {
const val SEEN_MESSAGE_MAX_IDS: Int = 10_000
}
}
@@ -0,0 +1,39 @@
package com.bitchat.android.utils
import android.content.Context
import android.content.res.Configuration
import android.util.DisplayMetrics
import android.view.WindowManager
import androidx.core.content.getSystemService
import kotlin.math.sqrt
object DeviceUtils {
/**
* Determines if the current device is a tablet based on screen size and density.
* Uses multiple criteria to accurately detect tablets vs phones.
*/
fun isTablet(context: Context): Boolean {
val windowManager = context.getSystemService<WindowManager>()
val displayMetrics = DisplayMetrics()
windowManager?.defaultDisplay?.getMetrics(displayMetrics)
// Calculate screen size in inches
val widthInches = displayMetrics.widthPixels / displayMetrics.xdpi
val heightInches = displayMetrics.heightPixels / displayMetrics.ydpi
val diagonalInches = sqrt((widthInches * widthInches) + (heightInches * heightInches))
// Check if device has tablet configuration
val configuration = context.resources.configuration
val isLargeScreen = (configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) >= Configuration.SCREENLAYOUT_SIZE_LARGE
val isXLargeScreen = (configuration.screenLayout and Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE
// A device is considered a tablet if:
// 1. Screen diagonal is 7 inches or larger, OR
// 2. Configuration indicates large or xlarge screen, OR
// 3. Smallest width is 600dp or more (sw600dp)
val smallestWidthDp = context.resources.configuration.smallestScreenWidthDp
return diagonalInches >= 7.0 || isLargeScreen || isXLargeScreen || smallestWidthDp >= 600
}
}
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- مبررات الأذونات -->
<string name="permission_bluetooth_rationale">إذن البلوتوث مطلوب للدردشة مباشرة مع الآخرين بدون إنترنت.</string>
<string name="permission_location_rationale">إذن الموقع مطلوب للعثور على الأجهزة القريبة عبر البلوتوث.</string>
<string name="permission_notification_rationale">إذن الإشعارات مطلوب لتنبيهك بالرسائل الجديدة.</string>
<!-- عناصر نائبة / واجهة أساسية -->
<string name="nickname_hint">اسم مستعار</string>
<string name="message_hint">اكتب رسالة…</string>
<string name="channel_password_hint">كلمة المرور</string>
<string name="join_channel">الانضمام إلى القناة</string>
<string name="leave_channel">مغادرة</string>
<string name="send_message">إرسال</string>
<string name="show_commands">عرض الأوامر</string>
<string name="back">رجوع</string>
<string name="people">أشخاص</string>
<string name="channels">القنوات</string>
<string name="online_users">مستخدمون متصلون</string>
<string name="no_one_connected">لا أحد متصل</string>
<string name="emergency_clear_hint">انقر ثلاث مرات لمسح جميع البيانات</string>
<string name="your_network">شبكتك</string>
<!-- تحسين البطارية -->
<string name="battery_optimization_detected">تم اكتشاف تحسين البطارية</string>
<string name="battery_optimization_disabled">تحسين البطارية معطّل</string>
<string name="battery_optimization_not_required">لا حاجة لتحسين البطارية</string>
<string name="battery_optimization_checking">جارٍ التحقق من تحسين البطارية</string>
<string name="battery_optimization_why_disable">لماذا تعطيل تحسين البطارية؟</string>
<string name="battery_optimization_explanation">تعمل bitchat في الخلفية للحفاظ على اتصالات الشبكة المتشابكة مع الأجهزة القريبة. قد يقطع تحسين البطارية هذه الاتصالات مما يؤدي إلى تأخير الرسائل أو فقدانها.\n\nيساعد تعطيل تحسين البطارية في ضمان اتصال موثوق بين النظراء.</string>
<string name="battery_optimization_disable_button">تعطيل تحسين البطارية</string>
<string name="battery_optimization_note">ملاحظة: يمكنك تغيير ذلك لاحقًا من إعدادات أندرويد &gt; التطبيقات &gt; bitchat &gt; البطارية.</string>
<string name="battery_optimization_not_supported_explanation">جهازك لا يحتاج إلى إعدادات تحسين البطارية. ستعمل bitchat بشكل طبيعي.</string>
<string name="battery_optimization_not_supported_message">جهازك لا يحتاج إلى إعدادات تحسين البطارية. ستعمل bitchat بشكل طبيعي.</string>
<string name="battery_optimization_success_message">يمكن لـ bitchat العمل بشكل موثوق في الخلفية</string>
<string name="battery_optimization_benefits">• تسليم موثوق للرسائل\n• الحفاظ على اتصال الشبكة المتشابكة\n• تمرير الرسائل في الخلفية\n• منع انقطاع الاتصال</string>
<string name="battery_optimization_check_again">التحقق مرة أخرى</string>
<string name="battery_optimization_skip">تخطي الآن</string>
<string name="battery_optimization_continue">متابعة</string>
<string name="retry">إعادة المحاولة</string>
<string name="skip">تخطي</string>
<!-- الإشعارات -->
<string name="notification_summary_more">و%1$d إضافية</string>
<string name="notification_messages_from_people">%1$d رسالة من %2$d أشخاص</string>
<string name="notification_more_conversations">و%1$d محادثات أخرى</string>
<string name="notification_active_peers_title">👥 مستخدمون قريبون!</string>
<string name="notification_active_peers_one">شخص واحد قريب</string>
<string name="notification_active_peers_many">%1$d أشخاص قريبون</string>
<string name="notification_new_messages">رسائل جديدة</string>
<string name="notification_new_location_messages">رسائل موقع جديدة</string>
<string name="notification_mentions_in">تم ذكرك في %1$s</string>
<string name="notification_mentions_in_more">تم ذكرك في %1$s (+%2$d أخرى)</string>
<string name="notification_mentions_in_plural">%1$d من الإشارات في %2$s</string>
<string name="notification_new_activity_in">نشاط جديد في %1$s</string>
<string name="notification_messages_in">رسائل في %1$s</string>
<string name="notification_joined_conversation">%1$s انضم إلى المحادثة</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d إشارات</string>
<string name="notification_geohash_summary_title">bitchat – محادثات المواقع</string>
<string name="notification_geohash_summary_text">%1$d رسائل من %2$d مواقع</string>
<string name="notification_mesh_mention_title_singular">تم ذكرك في محادثة الشبكة</string>
<string name="notification_mesh_mention_title_plural">%1$d من الإشارات في محادثة الشبكة</string>
<string name="notification_more_locations">و%1$d مواقع أخرى</string>
<string name="notification_and_more">و%1$d إضافية</string>
<!-- سهولة الوصول للمفضلة -->
<string name="cd_add_favorite">إضافة إلى المفضلة</string>
<string name="cd_remove_favorite">إزالة من المفضلة</string>
<string name="cd_add_bookmark">إضافة إشارة مرجعية</string>
<!-- ترويسة الدردشة وسهولة الوصول -->
<string name="chat_back">رجوع</string>
<string name="chat_channel_prefix">القناة: %1$s</string>
<string name="chat_leave">مغادرة</string>
<string name="cd_nostr_reachable">يمكن الوصول عبر Nostr</string>
<string name="cd_unread_private_messages">رسائل خاصة غير مقروءة</string>
<string name="cd_toggle_bookmark">تبديل الإشارة المرجعية</string>
<string name="cd_teleported">تم الانتقال</string>
<string name="cd_tor_status">حالة Tor</string>
<string name="cd_connected_peers">الأقران المتصلون</string>
<string name="cd_geohash_participants">مشاركو geohash</string>
<string name="cd_ready_for_handshake">جاهز للمصافحة</string>
<string name="cd_handshake_in_progress">المصافحة جارية</string>
<string name="cd_encrypted">تشفير طرف إلى طرف</string>
<string name="cd_handshake_failed">فشلت المصافحة</string>
<!-- مربع عرض الملفات -->
<string name="file_viewer_title">📎 تم استلام ملف</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 الحجم: %1$s</string>
<string name="file_viewer_type">🏷️ النوع: %1$s</string>
<string name="file_viewer_open_save">📂 فتح / حفظ</string>
<string name="close_with_emoji">❌ إغلاق</string>
<string name="pick_image">اختيار صورة</string>
<!-- ورقة حول التطبيق -->
<string name="about_tagline">دردشة شبكية لامركزية مع تشفير طرف إلى طرف</string>
<string name="about_offline_mesh_title">دردشة شبكية دون اتصال</string>
<string name="about_offline_mesh_desc">تواصل مباشرة عبر Bluetooth LE بدون إنترنت أو خوادم. تُعاد توجيه الرسائل عبر الأجهزة القريبة لتوسيع النطاق.</string>
<string name="about_online_geohash_title">قنوات geohash عبر الإنترنت</string>
<string name="about_online_geohash_desc">تواصل مع أشخاص بالقرب منك عبر قنوات تعتمد على geohash. وسّع الشبكة عبر مرحلات الإنترنت العامة.</string>
<string name="about_e2e_title">تشفير طرف إلى طرف</string>
<string name="about_e2e_desc">الرسائل الخاصة مشفّرة. رسائل القنوات عامة.</string>
<string name="about_appearance">المظهر</string>
<string name="about_system">النظام</string>
<string name="about_light">فاتح</string>
<string name="about_dark">داكن</string>
<string name="about_pow">برهان العمل</string>
<string name="about_pow_off">PoW معطّل</string>
<string name="about_pow_on">PoW مفعّل</string>
<string name="about_pow_tip">أضف برهان العمل لرسائل geohash للحد من الرسائل المزعجة.</string>
<string name="about_pow_difficulty">الصعوبة: %1$d بت (~%2$s)</string>
<string name="about_pow_difficulty_attempts">الصعوبة %1$d تتطلب ~%2$s من محاولات الهاش</string>
<string name="about_pow_desc_none">لا حاجة لبرهان العمل</string>
<string name="about_pow_desc_very_low">منخفض جدًا – حماية دنيا من الرسائل المزعجة</string>
<string name="about_pow_desc_low">منخفض – حماية أساسية</string>
<string name="about_pow_desc_medium">متوسط حماية جيدة</string>
<string name="about_pow_desc_high">عالٍ حماية قوية</string>
<string name="about_pow_desc_very_high">عالٍ جدًا – قد يسبب تأخيرًا</string>
<string name="about_pow_desc_extreme">شديد – يتطلب قدرة حوسبية كبيرة</string>
<string name="about_network">الشبكة</string>
<string name="about_tor_off">Tor معطّل</string>
<string name="about_tor_on">Tor مفعّل</string>
<string name="about_tor_route">توجيه حركة الإنترنت عبر Tor لمزيد من الخصوصية.</string>
<string name="about_tor_status">حالة Tor: %1$s، التمهيد %2$d%%</string>
<string name="about_last">آخر: %1$s</string>
<string name="about_emergency_title">مسح البيانات الطارئ</string>
<string name="about_emergency_tip">تلميح: انقر ثلاث مرات على عنوان التطبيق لمسح كل البيانات المحفوظة – بما في ذلك الرسائل والمفاتيح والإعدادات.</string>
<string name="about_debug_settings">إعدادات التصحيح</string>
<string name="about_footer">مفتوح المصدر • الخصوصية أولاً • لامركزي</string>
<string name="close_plain">إغلاق</string>
<string name="cancel_lower">إلغاء</string>
<!-- أوصاف عامة للمحتوى -->
<string name="cd_warning">تحذير</string>
<string name="cd_location_services">خدمات الموقع</string>
<string name="cd_privacy">الخصوصية</string>
<string name="cd_error">خطأ</string>
<string name="cd_battery_optimization">تحسين البطارية</string>
<string name="cd_benefits">الفوائد</string>
<string name="cd_checking_battery_optimization">جارٍ التحقق من تحسين البطارية</string>
<string name="cd_not_supported_battery_optimization">تحسين البطارية غير مدعوم</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">رسالة غير مقروءة</string>
<string name="cd_open_map">فتح الخريطة</string>
<string name="cd_remove_bookmark">إزالة الإشارة المرجعية</string>
<string name="cd_teleport">انتقال</string>
<string name="cd_selected">محدد</string>
<string name="cd_leave_channel">مغادرة القناة</string>
<string name="cd_reachable_via_nostr">يمكن الوصول عبر Nostr</string>
<string name="cd_offline_favorite">مفضل (غير متصل)</string>
<string name="cd_decrease_precision">خفض الدقة</string>
<string name="cd_increase_precision">رفع الدقة</string>
<string name="cd_select_geohash">اختر geohash</string>
<string name="cd_scroll_to_bottom">التمرير إلى الأسفل</string>
<string name="cd_file">ملف</string>
<string name="cd_image">صورة</string>
<string name="cd_cancel">إلغاء</string>
<string name="cd_link">رابط</string>
<string name="cd_pick_media">اختيار وسائط</string>
<string name="cd_pick_file">اختيار ملف</string>
<string name="cd_save_current_image">حفظ الصورة الحالية</string>
<string name="cd_close">إغلاق</string>
<string name="cd_image_index_of">صورة %1$d من %2$d</string>
<string name="cd_privacy_protected">الخصوصية محمية</string>
<string name="cd_record_voice">تسجيل مذكرة صوتية</string>
<string name="cd_offline_mesh_chat">دردشة شبكية دون اتصال</string>
<string name="cd_online_geohash_channels">قنوات geohash عبر الإنترنت</string>
<string name="cd_end_to_end_encryption">تشفير طرف إلى طرف</string>
<!-- الصور والملفات -->
<string name="image_page_of">صورة %1$d من %2$d</string>
<string name="image_unavailable">الصورة غير متاحة</string>
<string name="image_saved_to_downloads">تم حفظ الصورة في "التنزيلات"</string>
<string name="image_save_failed">تعذّر حفظ الصورة</string>
<string name="toast_image_saved">تم حفظ الصورة في "التنزيلات"</string>
<string name="toast_failed_to_save_image">تعذّر حفظ الصورة</string>
<string name="pick_file">اختيار ملف</string>
<string name="file_unavailable">[الملف غير متاح]</string>
<string name="unknown">غير معروف</string>
<!-- ورقة إجراءات المستخدم -->
<string name="choose_action_message_or_user">اختر إجراءً لهذه الرسالة أو هذا المستخدم</string>
<string name="choose_action_user">اختر إجراءً لهذا المستخدم</string>
<string name="action_copy_message_title">نسخ الرسالة</string>
<string name="action_copy_message_subtitle">انسخ هذه الرسالة إلى الحافظة</string>
<string name="action_slap_title">صفع %1$s</string>
<string name="action_slap_subtitle">إرسال صفعة ودّية</string>
<string name="action_hug_title">عناق %1$s</string>
<string name="action_hug_subtitle">إرسال عناق ودي</string>
<string name="action_block_title">حظر %1$s</string>
<string name="action_block_subtitle">حظر جميع رسائل هذا المستخدم</string>
<!-- ورقة قنوات geohash -->
<string name="location_channels_title">#قنوات الموقع</string>
<string name="location_channels_desc">دردش مع أشخاص قريبين منك عبر قنوات geohash. تتم مشاركة geohash تقريبي فقط، وليس بيانات GPS الدقيقة. للحفاظ على خصوصيتك، لا تلتقط لقطات شاشة ولا تشارك هذه الشاشة.</string>
<string name="grant_location_permission">منح إذن الموقع</string>
<string name="location_permission_denied">تم رفض إذن الموقع. فعّله من الإعدادات لاستخدام قنوات الموقع.</string>
<string name="open_settings">فتح الإعدادات</string>
<string name="location_permission_granted">\u2713 تم منح إذن الموقع</string>
<string name="checking_permissions">جارٍ التحقق من الأذونات…</string>
<string name="finding_nearby_channels">البحث عن قنوات قريبة…</string>
<string name="bookmarked">محفوظة</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">geohash غير صالح</string>
<string name="teleport">انتقال</string>
<string name="disable_location_services">تعطيل خدمات الموقع</string>
<string name="enable_location_services">تمكين خدمات الموقع</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">مربّع سكني</string>
<string name="location_level_neighborhood">حيّ</string>
<string name="location_level_city">مدينة</string>
<string name="location_level_province">إقليم</string>
<string name="location_level_region">منطقة</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- التصحيح / التشخيص -->
<string name="debug_tools">أدوات التصحيح</string>
<string name="debug_tools_desc">أدوات المطوّر للتشخيص والتحكم</string>
<string name="debug_verbose_logging">سجل تفصيلي</string>
<string name="debug_verbose_hint">تسجّل انضمام/مغادرة الأقران، اتجاه الاتصال، تمرير الحزم والمرحلين</string>
<string name="debug_bluetooth_roles">أدوار البلوتوث</string>
<string name="debug_gatt_server">خادم GATT</string>
<string name="debug_connections_fmt">الاتصالات: %1$d / %2$d</string>
<string name="debug_max_server">الحد الأقصى للخادم</string>
<string name="debug_gatt_client">عميل GATT</string>
<string name="debug_max_client">الحد الأقصى للعميل</string>
<string name="debug_overall_connections_fmt">الاتصالات: %1$d / %2$d</string>
<string name="debug_max_overall">الحد الأقصى الكلي</string>
<string name="debug_packet_relay">تمرير الحزم</string>
<string name="debug_since_start_fmt">منذ البدء: %1$d</string>
<string name="debug_roles_hint">تبديل الأدوار وإغلاق جميع الاتصالات عند التعطيل</string>
<string name="debug_sync_settings">إعدادات المزامنة</string>
<string name="debug_max_packets_per_sync_fmt">الحد الأقصى للحزم لكل مزامنة: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">الحد الأقصى لحجم مرشح GCS: %1$d بايت (1281024)</string>
<string name="debug_target_fpr_fmt">نسبة الإيجابيات الكاذبة المستهدفة: %1$.2f%%</string>
<string name="debug_connected_devices">الأجهزة المتصلة</string>
<string name="debug_our_device_id_fmt">معرّف جهازنا: %1$s</string>
<string name="debug_none">لا شيء</string>
<string name="debug_disconnect">قطع الاتصال</string>
<string name="debug_recent_scan_results">الأجهزة التي تم فحصها مؤخرًا</string>
<string name="debug_connect">اتصال</string>
<string name="debug_debug_console">وحدة تصحيح</string>
<string name="debug_clear">مسح</string>
<string name="debug_relays_window_fmt">آخر 10 ثوان: %1$d • 1 دقيقة: %2$d • 15 دقيقة: %3$d</string>
<string name="debug_derived_p_fmt">قيمة P المشتقة: %1$s • الحد الأقصى للعناصر المقدّر: %2$s</string>
<string name="debug_direct_suffix"> • مباشر</string>
<string name="debug_role_server">كخادم (نحن نستضيف)</string>
<string name="debug_role_client">كعميل (نحن نتصل)</string>
<!-- شاشات البدء -->
<string name="location_services_required">خدمات الموقع مطلوبة</string>
<string name="privacy_first">الخصوصية أولاً</string>
<string name="location_explanation">bitchat لا يتتبع موقعك.\n\nخدمات الموقع مطلوبة لمسح البلوتوث وميزة دردشة geohash.</string>
<string name="location_needs_for">bitchat يحتاج خدمات الموقع من أجل:</string>
<string name="location_needs_bullets">• مسح أجهزة البلوتوث\n• اكتشاف المستخدمين القريبين في شبكة mesh\n• ميزة دردشة geohash\n• بدون تتبع أو جمع للموقع</string>
<string name="open_location_settings">فتح إعدادات الموقع</string>
<string name="check_again">التحقق مرة أخرى</string>
<string name="location_services_unavailable">خدمات الموقع غير متاحة</string>
<string name="location_unavailable_explanation">خدمات الموقع غير متاحة على هذا الجهاز. هذا غير معتاد لأن خدمات الموقع قياسية في أجهزة أندرويد.\n\nتتطلب bitchat خدمات الموقع لعمل مسح البلوتوث بشكل صحيح (متطلب أندرويد). بدون ذلك لا يمكن للتطبيق اكتشاف المستخدمين القريبين.</string>
<string name="checking_location_services">جارٍ التحقق من خدمات الموقع…</string>
<string name="bluetooth_required">البلوتوث مطلوب</string>
<string name="bluetooth_needs_for">bitchat يحتاج البلوتوث من أجل:</string>
<string name="bluetooth_needs_bullets">• اكتشاف المستخدمين القريبين\n• إنشاء اتصالات شبكة mesh\n• إرسال واستقبال الرسائل\n• العمل بدون إنترنت أو خوادم</string>
<string name="enable_bluetooth">تفعيل البلوتوث</string>
<string name="bluetooth_not_supported">البلوتوث غير مدعوم</string>
<string name="bluetooth_unsupported_explanation">هذا الجهاز لا يدعم Bluetooth Low Energy (BLE) المطلوب لعمل bitchat.\n\nتحتاج bitchat إلى BLE لإنشاء شبكات mesh والتواصل مع الأجهزة القريبة بدون إنترنت.</string>
<string name="checking_bluetooth_status">جارٍ التحقق من حالة البلوتوث…</string>
<string name="battery_optimization_detected_title">تم اكتشاف تحسين البطارية</string>
<string name="battery_optimization_enabled_title">تحسين البطارية مفعّل</string>
<string name="battery_optimization_explanation_short">تحتاج bitchat للعمل في الخلفية للحفاظ على اتصالات mesh. قد يقطع تحسين البطارية هذه الاتصالات.</string>
<string name="benefits_of_disabling">فوائد التعطيل</string>
<string name="battery_benefits_short">• تسليم موثوق للرسائل\n• يحافظ على اتصال mesh\n• يمنع انقطاع الاتصال</string>
<string name="disable_battery_optimization">تعطيل تحسين البطارية</string>
<string name="battery_optimization_disabled_title">تم تعطيل تحسين البطارية</string>
<string name="continue_btn">متابعة</string>
<string name="initializing_mesh_network">جارٍ تهيئة شبكة mesh</string>
<string name="setting_up_bluetooth">جارٍ إعداد شبكة Bluetooth mesh…</string>
<string name="should_take_seconds">يجب أن يستغرق ذلك بضع ثوانٍ فقط</string>
<string name="setup_not_complete">الإعداد غير مكتمل</string>
<string name="try_again">حاول مرة أخرى</string>
<string name="privacy_protected">خصوصيتك محمية</string>
<string name="privacy_bullets">• بدون تتبع أو جمع للبيانات\n• دردشات Bluetooth mesh تعمل دون اتصال بالكامل\n• دردشات geohash تستخدم الإنترنت</string>
<string name="permissions_header">الأذونات</string>
<string name="grant_permissions">منح الأذونات</string>
<string name="location_tracking_warning">bitchat لا يتتبع موقعك</string>
<string name="geohash_people_header">الأشخاص</string>
<string name="nobody_around">لا أحد هنا…</string>
<string name="you_suffix"> (أنت)</string>
<string name="pan_zoom_instruction">حرّك وقرّب لاختيار geohash</string>
<string name="select">اختيار</string>
<string name="type_a_message_placeholder">اكتب رسالة…</string>
<string name="mention">إشارة</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">صورة</string>
<string name="media_type_file">ملف</string>
<!-- مساعدو نص الإشعارات -->
<string name="notification_sent_image">📷 أرسل صورة</string>
<string name="notification_sent_voice">🎤 أرسل مذكرة صوتية</string>
<string name="notification_sent_file">📎 أرسل ملفًا</string>
<!-- سهولة استخدام مشغّل الصوت -->
<string name="cd_play_voice">تشغيل</string>
<string name="cd_pause_voice">إيقاف مؤقت</string>
<string name="cd_mining_pow">تعدين PoW</string>
<string name="cd_pow_enabled">PoW مفعّل</string>
<string name="cd_proof_of_work">برهان العمل</string>
<string name="pow_mining_ellipsis">يتم التعدين…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- أوصاف الأذونات -->
<string name="perm_nearby_devices_desc">مطلوب لاكتشاف مستخدمي bitchat عبر البلوتوث</string>
<string name="perm_nearby_devices_system">اسمح لـ bitchat بالاتصال بالأجهزة القريبة</string>
<string name="perm_location_desc">مطلوب من أندرويد لاكتشاف مستخدمي bitchat القريبين عبر البلوتوث</string>
<string name="perm_location_system">bitchat يحتاج ذلك لمسح الأجهزة القريبة</string>
<string name="perm_notifications_desc">تلقي إشعارات عند استلام رسائل خاصة</string>
<string name="perm_notifications_system">اسمح لـ bitchat بإرسال الإشعارات إليك</string>
<string name="perm_battery_desc">تعطيل تحسين البطارية لضمان أن bitchat يعمل بشكل موثوق في الخلفية ويحافظ على اتصالات الشبكة المتشابكة</string>
<string name="perm_battery_system">اسمح لـ bitchat بالعمل بدون قيود البطارية</string>
<!-- أنواع الأذونات -->
<string name="perm_type_nearby_devices">الأجهزة القريبة</string>
<string name="perm_type_precise_location">موقع دقيق</string>
<string name="perm_type_microphone">ميكروفون</string>
<string name="perm_type_notifications">إشعارات</string>
<string name="perm_type_battery_optimization">تحسين البطارية</string>
<string name="perm_type_other">أخرى</string>
<!-- مربع كلمة المرور -->
<string name="pwd_prompt_title">أدخل كلمة مرور القناة</string>
<string name="pwd_prompt_message">القناة %1$s محمية بكلمة مرور. أدخل كلمة المرور للانضمام.</string>
<string name="pwd_label">كلمة المرور</string>
<string name="join">انضمام</string>
<string name="cancel">إلغاء</string>
<!-- صيغ الجمع -->
<plurals name="notification_and_more">
<item quantity="one">و%d إضافية</item>
<item quantity="other">و%d إضافية</item>
</plurals>
<plurals name="people_count">
<item quantity="one">شخص واحد</item>
<item quantity="other">%d أشخاص</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d ملاحظة</item>
<item quantity="other">#%1$s ± 1 • %2$d ملاحظات</item>
</plurals>
<string name="location_notes_description">أضف ملاحظات قصيرة ودائمة إلى هذا المكان ليتمكن الزوار الآخرون من العثور عليها.</string>
<string name="location_notes_relays_unavailable">قنوات الترحيل الجغرافية غير متاحة؛ تم إيقاف الملاحظات</string>
<string name="location_notes_no_relays_title">لا توجد قنوات ترحيل جغرافية قريبة</string>
<string name="location_notes_no_relays_desc">تعتمد الملاحظات على قنوات الترحيل الجغرافية. تحقق من الاتصال ثم أعد المحاولة.</string>
<string name="loading_location_notes">جارٍ تحميل الملاحظات…</string>
<string name="location_notes_empty_title">لا توجد ملاحظات بعد</string>
<string name="location_notes_empty_desc">كن أول من يضيف ملاحظة لهذا المكان.</string>
<string name="dismiss">إغلاق</string>
<string name="location_notes_input_placeholder">أضف ملاحظة لهذا المكان</string>
</resources>
+352
View File
@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- অনুমতির যৌক্তিকতা -->
<string name="permission_bluetooth_rationale">ইন্টারনেট ছাড়াই অন্যদের সাথে সরাসরি চ্যাট করার জন্য ব্লুটুথ অনুমতি প্রয়োজন।</string>
<string name="permission_location_rationale">ব্লুটুথের মাধ্যমে কাছাকাছি ডিভাইস খুঁজে পেতে অবস্থান অনুমতি প্রয়োজন।</string>
<string name="permission_notification_rationale">নতুন বার্তা সম্পর্কে আপনাকে জানাতে বিজ্ঞপ্তি অনুমতি প্রয়োজন।</string>
<!-- প্লেসহোল্ডার / মৌলিক UI -->
<string name="nickname_hint">ডাকনাম</string>
<string name="message_hint">বার্তা টাইপ করুন…</string>
<string name="channel_password_hint">পাসওয়ার্ড</string>
<string name="join_channel">চ্যানেলে যোগ দিন</string>
<string name="leave_channel">ছেড়ে দিন</string>
<string name="send_message">পাঠান</string>
<string name="show_commands">কমান্ড দেখান</string>
<string name="back">ফিরে যান</string>
<string name="people">মানুষ</string>
<string name="channels">চ্যানেল</string>
<string name="online_users">অনলাইন ব্যবহারকারী</string>
<string name="no_one_connected">কেউ সংযুক্ত নেই</string>
<string name="emergency_clear_hint">সমস্ত ডেটা সাফ করতে তিনবার ট্যাপ করুন</string>
<string name="your_network">নেটওয়ার্ক</string>
<!-- ব্যাটারি অপ্টিমাইজেশন -->
<string name="battery_optimization_detected">ব্যাটারি অপ্টিমাইজেশন সনাক্ত</string>
<string name="battery_optimization_disabled">ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয়</string>
<string name="battery_optimization_not_required">ব্যাটারি অপ্টিমাইজেশন প্রয়োজন নেই</string>
<string name="battery_optimization_checking">ব্যাটারি অপ্টিমাইজেশন পরীক্ষা করা হচ্ছে</string>
<string name="battery_optimization_why_disable">কেন ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয় করবেন?</string>
<string name="battery_optimization_explanation">bitchat ব্যাকগ্রাউন্ডে চলে কাছাকাছি ডিভাইসগুলির সাথে মেশ সংযোগ বজায় রাখতে। ব্যাটারি অপ্টিমাইজেশন এই সংযোগগুলি বাধাগ্রস্ত করতে পারে, যার ফলে বার্তা বিলম্বিত বা হারিয়ে যেতে পারে।\n\nব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয় করা নির্ভরযোগ্য পিয়ার-টু-পিয়ার যোগাযোগ নিশ্চিত করে।</string>
<string name="battery_optimization_disable_button">ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয় করুন</string>
<string name="battery_optimization_note">নোট: আপনি পরে Android Settings &gt; Apps &gt; bitchat &gt; Battery এ এটি পরিবর্তন করতে পারেন।</string>
<string name="battery_optimization_not_supported_explanation">আপনার ডিভাইসে ব্যাটারি অপ্টিমাইজেশন সেটিংসের প্রয়োজন নেই। bitchat স্বাভাবিকভাবে চলবে।</string>
<string name="battery_optimization_not_supported_message">আপনার ডিভাইসে ব্যাটারি অপ্টিমাইজেশন সেটিংসের প্রয়োজন নেই। bitchat স্বাভাবিকভাবে চলবে।</string>
<string name="battery_optimization_success_message">bitchat নির্ভরযোগ্যভাবে ব্যাকগ্রাউন্ডে চলতে পারে</string>
<string name="battery_optimization_benefits">• নির্ভরযোগ্য বার্তা ডেলিভারি\n• মেশ সংযোগ বজায় রাখা\n• ব্যাকগ্রাউন্ড বার্তা রিলে\n• সংযোগ বিচ্ছিন্নতা প্রতিরোধ</string>
<string name="battery_optimization_check_again">আবার পরীক্ষা করুন</string>
<string name="battery_optimization_skip">এখন এড়িয়ে যান</string>
<string name="battery_optimization_continue">চালিয়ে যান</string>
<string name="retry">আবার চেষ্টা করুন</string>
<string name="skip">এড়িয়ে যান</string>
<!-- বিজ্ঞপ্তি -->
<string name="notification_summary_more">এবং %1$d আরো</string>
<string name="notification_messages_from_people">%2$d জন থেকে %1$d বার্তা</string>
<string name="notification_more_conversations">এবং %1$d আরো কথোপকথন</string>
<string name="notification_active_peers_title">👥 কাছাকাছি bitchatter!</string>
<string name="notification_active_peers_one">কাছাকাছি ১ জন</string>
<string name="notification_active_peers_many">কাছাকাছি %1$d জন</string>
<string name="notification_new_messages">নতুন বার্তা</string>
<string name="notification_new_location_messages">নতুন অবস্থান বার্তা</string>
<string name="notification_mentions_in">%1$s এ উল্লিখিত</string>
<string name="notification_mentions_in_more">%1$s এ উল্লিখিত (+%2$d আরো)</string>
<string name="notification_mentions_in_plural">%2$s এ %1$d উল্লেখ</string>
<string name="notification_new_activity_in">%1$s এ নতুন কার্যকলাপ</string>
<string name="notification_messages_in">%1$s এ বার্তা</string>
<string name="notification_joined_conversation">%1$s কথোপকথনে যোগ দিয়েছে</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d উল্লেখ</string>
<string name="notification_geohash_summary_title">bitchat – অবস্থান চ্যাট</string>
<string name="notification_geohash_summary_text">%2$d অবস্থান থেকে %1$d বার্তা</string>
<string name="notification_mesh_mention_title_singular">মেশ চ্যাটে উল্লিখিত</string>
<string name="notification_mesh_mention_title_plural">মেশ চ্যাটে %1$d উল্লেখ</string>
<string name="notification_more_locations">এবং %1$d আরো অবস্থান</string>
<string name="notification_and_more">এবং %1$d আরো</string>
<!-- প্রিয় অ্যাক্সেসিবিলিটি -->
<string name="cd_add_favorite">প্রিয়তে যোগ করুন</string>
<string name="cd_remove_favorite">প্রিয় থেকে সরান</string>
<string name="cd_add_bookmark">বুকমার্ক যোগ করুন</string>
<!-- চ্যাট হেডার ও অ্যাক্সেসিবিলিটি -->
<string name="chat_back">ফিরে যান</string>
<string name="chat_channel_prefix">চ্যানেল: %1$s</string>
<string name="chat_leave">ছেড়ে দিন</string>
<string name="cd_nostr_reachable">Nostr এর মাধ্যমে পৌঁছানো যায়</string>
<string name="cd_unread_private_messages">অপঠিত ব্যক্তিগত বার্তা</string>
<string name="cd_toggle_bookmark">বুকমার্ক টগল করুন</string>
<string name="cd_teleported">টেলিপোর্ট করা হয়েছে</string>
<string name="cd_tor_status">Tor অবস্থা</string>
<string name="cd_connected_peers">সংযুক্ত পিয়ার</string>
<string name="cd_geohash_participants">জিওহ্যাশ অংশগ্রহণকারী</string>
<string name="cd_ready_for_handshake">হ্যান্ডশেকের জন্য প্রস্তুত</string>
<string name="cd_handshake_in_progress">হ্যান্ডশেক চলছে</string>
<string name="cd_encrypted">এন্ড-টু-এন্ড এনক্রিপ্ট করা</string>
<string name="cd_handshake_failed">হ্যান্ডশেক ব্যর্থ</string>
<!-- ফাইল ভিউয়ার ডায়ালগ -->
<string name="file_viewer_title">📎 ফাইল প্রাপ্ত</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 আকার: %1$s</string>
<string name="file_viewer_type">🏷️ ধরণ: %1$s</string>
<string name="file_viewer_open_save">📂 খুলুন / সংরক্ষণ করুন</string>
<string name="close_with_emoji">❌ বন্ধ করুন</string>
<string name="pick_image">ছবি নির্বাচন করুন</string>
<!-- সম্পর্কে শিট -->
<string name="about_tagline">এন্ড-টু-এন্ড এনক্রিপশন সহ বিকেন্দ্রীভূত মেশ চ্যাট</string>
<string name="about_offline_mesh_title">অফলাইন মেশ চ্যাট</string>
<string name="about_offline_mesh_desc">ইন্টারনেট বা সার্ভার ছাড়াই Bluetooth LE এর মাধ্যমে সরাসরি যোগাযোগ করুন। পরিসর বাড়ানোর জন্য কাছাকাছি ডিভাইসের মাধ্যমে বার্তা রিলে করা হয়।</string>
<string name="about_online_geohash_title">অনলাইন জিওহ্যাশ চ্যানেল</string>
<string name="about_online_geohash_desc">জিওহ্যাশ-ভিত্তিক চ্যানেলের মাধ্যমে আপনার এলাকার মানুষদের সাথে সংযুক্ত হন। পাবলিক ইন্টারনেট রিলেগুলির মাধ্যমে মেশ বিস্তৃত করুন।</string>
<string name="about_e2e_title">এন্ড-টু-এন্ড এনক্রিপশন</string>
<string name="about_e2e_desc">ব্যক্তিগত বার্তাগুলি এনক্রিপ্ট করা। চ্যানেল বার্তাগুলি পাবলিক।</string>
<string name="about_appearance">চেহারা</string>
<string name="about_system">সিস্টেম</string>
<string name="about_light">হালকা</string>
<string name="about_dark">অন্ধকার</string>
<string name="about_pow">প্রুফ অফ ওয়ার্ক</string>
<string name="about_pow_off">PoW বন্ধ</string>
<string name="about_pow_on">PoW চালু</string>
<string name="about_pow_tip">স্প্যাম কঠিন করতে জিওহ্যাশ বার্তায় প্রুফ অফ ওয়ার্ক যোগ করুন।</string>
<string name="about_pow_difficulty">কঠিনতা: %1$d বিট (~%2$s)</string>
<string name="about_pow_difficulty_attempts">কঠিনতা %1$d প্রয়োজন ~%2$s হ্যাশ প্রচেষ্টা</string>
<string name="about_pow_desc_none">কোন প্রুফ অফ ওয়ার্ক প্রয়োজন নেই</string>
<string name="about_pow_desc_very_low">খুব কম – ন্যূনতম স্প্যাম সুরক্ষা</string>
<string name="about_pow_desc_low">কম – মৌলিক স্প্যাম সুরক্ষা</string>
<string name="about_pow_desc_medium">মাঝারি – ভাল স্প্যাম সুরক্ষা</string>
<string name="about_pow_desc_high">উচ্চ – শক্তিশালী স্প্যাম সুরক্ষা</string>
<string name="about_pow_desc_very_high">খুব উচ্চ – বিলম্ব ঘটাতে পারে</string>
<string name="about_pow_desc_extreme">চরম – উল্লেখযোগ্য কম্পিউটিং পাওয়ার প্রয়োজন</string>
<string name="about_network">নেটওয়ার্ক</string>
<string name="about_tor_off">Tor বন্ধ</string>
<string name="about_tor_on">Tor চালু</string>
<string name="about_tor_route">আরো গোপনীয়তার জন্য Tor এর মাধ্যমে ইন্টারনেট ট্রাফিক রুট করুন।</string>
<string name="about_tor_status">Tor অবস্থা: %1$s, বুটস্ট্র্যাপ %2$d%%</string>
<string name="about_last">শেষ: %1$s</string>
<string name="about_emergency_title">জরুরী ডেটা ক্লিয়ার</string>
<string name="about_emergency_tip">টিপ: সংরক্ষিত সমস্ত ডেটা – বার্তা, কী এবং সেটিংস সহ – সাফ করতে অ্যাপ শিরোনামে তিনবার ট্যাপ করুন।</string>
<string name="about_debug_settings">ডিবাগ সেটিংস</string>
<string name="about_footer">ওপেন সোর্স • গোপনীয়তা প্রথম • বিকেন্দ্রীভূত</string>
<string name="close_plain">বন্ধ করুন</string>
<string name="cancel_lower">বাতিল</string>
<!-- সাধারণ বিষয়বস্তু বিবরণ -->
<string name="cd_warning">সতর্কতা</string>
<string name="cd_location_services">অবস্থান সেবা</string>
<string name="cd_privacy">গোপনীয়তা</string>
<string name="cd_error">ত্রুটি</string>
<string name="cd_battery_optimization">ব্যাটারি অপ্টিমাইজেশন</string>
<string name="cd_benefits">সুবিধা</string>
<string name="cd_checking_battery_optimization">ব্যাটারি অপ্টিমাইজেশন পরীক্ষা করা হচ্ছে</string>
<string name="cd_not_supported_battery_optimization">ব্যাটারি অপ্টিমাইজেশন সমর্থিত নয়</string>
<string name="cd_bluetooth">ব্লুটুথ</string>
<string name="cd_unread_message">অপঠিত বার্তা</string>
<string name="cd_open_map">মানচিত্র খুলুন</string>
<string name="cd_remove_bookmark">বুকমার্ক সরান</string>
<string name="cd_teleport">টেলিপোর্ট</string>
<string name="cd_selected">নির্বাচিত</string>
<string name="cd_leave_channel">চ্যানেল ছেড়ে দিন</string>
<string name="cd_reachable_via_nostr">Nostr এর মাধ্যমে পৌঁছানো যায়</string>
<string name="cd_offline_favorite">প্রিয় (অফলাইন)</string>
<string name="cd_decrease_precision">নির্ভুলতা কমান</string>
<string name="cd_increase_precision">নির্ভুলতা বাড়ান</string>
<string name="cd_select_geohash">জিওহ্যাশ নির্বাচন করুন</string>
<string name="cd_scroll_to_bottom">নিচে স্ক্রল করুন</string>
<string name="cd_file">ফাইল</string>
<string name="cd_image">ছবি</string>
<string name="cd_cancel">বাতিল</string>
<string name="cd_link">লিঙ্ক</string>
<string name="cd_pick_media">মিডিয়া নির্বাচন করুন</string>
<string name="cd_pick_file">ফাইল নির্বাচন করুন</string>
<string name="cd_save_current_image">বর্তমান ছবি সংরক্ষণ করুন</string>
<string name="cd_close">বন্ধ করুন</string>
<string name="cd_image_index_of">ছবি %1$d এর %2$d</string>
<string name="cd_privacy_protected">গোপনীয়তা সুরক্ষিত</string>
<string name="cd_record_voice">ভয়েস বার্তা রেকর্ড করুন</string>
<string name="cd_offline_mesh_chat">অফলাইন মেশ চ্যাট</string>
<string name="cd_online_geohash_channels">অনলাইন জিওহ্যাশ চ্যানেল</string>
<string name="cd_end_to_end_encryption">এন্ড-টু-এন্ড এনক্রিপশন</string>
<!-- ছবি ও ফাইল -->
<string name="image_page_of">ছবি %1$d এর %2$d</string>
<string name="image_unavailable">ছবি অনুপলব্ধ</string>
<string name="image_saved_to_downloads">ছবি \"Downloads\" এ সংরক্ষিত</string>
<string name="image_save_failed">ছবি সংরক্ষণ করতে ব্যর্থ</string>
<string name="toast_image_saved">ছবি \"Downloads\" এ সংরক্ষিত</string>
<string name="toast_failed_to_save_image">ছবি সংরক্ষণ করতে ব্যর্থ</string>
<string name="pick_file">ফাইল নির্বাচন করুন</string>
<string name="file_unavailable">[ফাইল অনুপলব্ধ]</string>
<string name="unknown">অজানা</string>
<!-- ব্যবহারকারী অ্যাকশন শিট -->
<string name="choose_action_message_or_user">এই বার্তা বা ব্যবহারকারীর জন্য অ্যাকশন নির্বাচন করুন</string>
<string name="choose_action_user">এই ব্যবহারকারীর জন্য অ্যাকশন নির্বাচন করুন</string>
<string name="action_copy_message_title">বার্তা কপি করুন</string>
<string name="action_copy_message_subtitle">এই বার্তাটি ক্লিপবোর্ডে কপি করুন</string>
<string name="action_slap_title">%1$s কে চড় দিন</string>
<string name="action_slap_subtitle">একটি কৌতুকপূর্ণ চড় পাঠান</string>
<string name="action_hug_title">%1$s কে আলিঙ্গন করুন</string>
<string name="action_hug_subtitle">একটি বন্ধুত্বপূর্ণ আলিঙ্গন পাঠান</string>
<string name="action_block_title">%1$s কে ব্লক করুন</string>
<string name="action_block_subtitle">এই ব্যবহারকারীর সমস্ত বার্তা ব্লক করুন</string>
<!-- জিওহ্যাশ চ্যানেল শিট -->
<string name="location_channels_title">#অবস্থান চ্যানেল</string>
<string name="location_channels_desc">জিওহ্যাশ চ্যানেলের মাধ্যমে আপনার কাছাকাছি মানুষদের সাথে চ্যাট করুন। শুধুমাত্র রূঢ় জিওহ্যাশ শেয়ার করা হয়, সঠিক GPS ডেটা নয়। গোপনীয়তার জন্য দয়া করে এই ভিউ স্ক্রিনশট করবেন না বা শেয়ার করবেন না।</string>
<string name="grant_location_permission">অবস্থান অনুমতি দিন</string>
<string name="location_permission_denied">অবস্থান অনুমতি প্রত্যাখ্যাত। অবস্থান চ্যানেল ব্যবহার করতে সেটিংসে সক্ষম করুন।</string>
<string name="open_settings">সেটিংস খুলুন</string>
<string name="location_permission_granted">\u2713 অবস্থান অনুমতি দেওয়া হয়েছে</string>
<string name="checking_permissions">অনুমতি পরীক্ষা করা হচ্ছে …</string>
<string name="finding_nearby_channels">কাছাকাছি চ্যানেল খোঁজা হচ্ছে …</string>
<string name="bookmarked">বুকমার্ক করা</string>
<string name="geohash_placeholder">জিওহ্যাশ</string>
<string name="invalid_geohash">অবৈধ জিওহ্যাশ</string>
<string name="teleport">টেলিপোর্ট</string>
<string name="disable_location_services">অবস্থান সেবা নিষ্ক্রিয় করুন</string>
<string name="enable_location_services">অবস্থান সেবা সক্রিয় করুন</string>
<string name="mesh_label">মেশ</string>
<string name="location_level_block">ব্লক</string>
<string name="location_level_neighborhood">আশপাশ</string>
<string name="location_level_city">শহর</string>
<string name="location_level_province">প্রদেশ</string>
<string name="location_level_region">অঞ্চল</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- ডিবাগ / ডায়াগনস্টিক -->
<string name="debug_tools">ডিবাগ টুল</string>
<string name="debug_tools_desc">ডায়াগনস্টিক এবং নিয়ন্ত্রণের জন্য ডেভেলপার টুল</string>
<string name="debug_verbose_logging">বিস্তারিত লগিং</string>
<string name="debug_verbose_hint">পিয়ার জয়েন/লিভ, সংযোগ দিক, প্যাকেট ফরওয়ার্ডিং এবং রিলে লগ করে</string>
<string name="debug_bluetooth_roles">ব্লুটুথ ভূমিকা</string>
<string name="debug_gatt_server">GATT সার্ভার</string>
<string name="debug_connections_fmt">সংযোগ: %1$d / %2$d</string>
<string name="debug_max_server">সর্বোচ্চ সার্ভার</string>
<string name="debug_gatt_client">GATT ক্লায়েন্ট</string>
<string name="debug_max_client">সর্বোচ্চ ক্লায়েন্ট</string>
<string name="debug_overall_connections_fmt">সংযোগ: %1$d / %2$d</string>
<string name="debug_max_overall">সর্বোচ্চ সামগ্রিক</string>
<string name="debug_packet_relay">প্যাকেট রিলে</string>
<string name="debug_since_start_fmt">শুরু থেকে: %1$d</string>
<string name="debug_roles_hint">ভূমিকা চালু/বন্ধ করুন এবং নিষ্ক্রিয় করার সময় সমস্ত সংযোগ বন্ধ করুন</string>
<string name="debug_sync_settings">সিঙ্ক সেটিংস</string>
<string name="debug_max_packets_per_sync_fmt">প্রতি সিঙ্কে সর্বোচ্চ প্যাকেট: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">সর্বোচ্চ GCS ফিল্টার আকার: %1$d বাইট (1281024)</string>
<string name="debug_target_fpr_fmt">লক্ষ্য FPR: %1$.2f%%</string>
<string name="debug_connected_devices">সংযুক্ত ডিভাইস</string>
<string name="debug_our_device_id_fmt">আমাদের ডিভাইস ID: %1$s</string>
<string name="debug_none">কোনটি নেই</string>
<string name="debug_disconnect">সংযোগ বিচ্ছিন্ন করুন</string>
<string name="debug_recent_scan_results">সাম্প্রতিক স্ক্যান করা ডিভাইস</string>
<string name="debug_connect">সংযোগ করুন</string>
<string name="debug_debug_console">ডিবাগ কনসোল</string>
<string name="debug_clear">সাফ করুন</string>
<string name="debug_relays_window_fmt">শেষ 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">উৎপন্ন P: %1$s • আনুমানিক সর্বোচ্চ উপাদান: %2$s</string>
<string name="debug_direct_suffix"> • সরাসরি</string>
<string name="debug_role_server">সার্ভার হিসেবে (আমরা হোস্ট করি)</string>
<string name="debug_role_client">ক্লায়েন্ট হিসেবে (আমরা সংযোগ করি)</string>
<!-- অনবোর্ডিং স্ক্রিন -->
<string name="location_services_required">অবস্থান সেবা প্রয়োজন</string>
<string name="privacy_first">গোপনীয়তা প্রথম</string>
<string name="location_explanation">bitchat আপনার অবস্থান ট্র্যাক করে না।\n\nব্লুটুথ স্ক্যানিং এবং জিওহ্যাশ চ্যাট বৈশিষ্ট্যের জন্য অবস্থান সেবা প্রয়োজন।</string>
<string name="location_needs_for">bitchat এর জন্য অবস্থান সেবা প্রয়োজন:</string>
<string name="location_needs_bullets">• ব্লুটুথ ডিভাইস স্ক্যানিং\n• মেশ নেটওয়ার্কে কাছাকাছি ব্যবহারকারী আবিষ্কার\n• জিওহ্যাশ চ্যাট বৈশিষ্ট্য\n• কোন ট্র্যাকিং বা অবস্থান সংগ্রহ নেই</string>
<string name="open_location_settings">অবস্থান সেটিংস খুলুন</string>
<string name="check_again">আবার পরীক্ষা করুন</string>
<string name="location_services_unavailable">অবস্থান সেবা অনুপলব্ধ</string>
<string name="location_unavailable_explanation">এই ডিভাইসে অবস্থান সেবা উপলব্ধ নেই। এটি অস্বাভাবিক কারণ অবস্থান সেবা Android ডিভাইসে স্ট্যান্ডার্ড।\n\nব্লুটুথ স্ক্যানিং সঠিকভাবে কাজ করার জন্য bitchat এর অবস্থান সেবা প্রয়োজন (Android প্রয়োজনীয়তা)। এটি ছাড়া অ্যাপ কাছাকাছি ব্যবহারকারী আবিষ্কার করতে পারে না।</string>
<string name="checking_location_services">অবস্থান সেবা পরীক্ষা করা হচ্ছে …</string>
<string name="bluetooth_required">ব্লুটুথ প্রয়োজন</string>
<string name="bluetooth_needs_for">bitchat এর জন্য ব্লুটুথ প্রয়োজন:</string>
<string name="bluetooth_needs_bullets">• কাছাকাছি ব্যবহারকারী আবিষ্কার\n• মেশ নেটওয়ার্ক সংযোগ তৈরি\n• বার্তা পাঠানো এবং গ্রহণ\n• ইন্টারনেট বা সার্ভার ছাড়া কাজ</string>
<string name="enable_bluetooth">ব্লুটুথ সক্রিয় করুন</string>
<string name="bluetooth_not_supported">ব্লুটুথ সমর্থিত নয়</string>
<string name="bluetooth_unsupported_explanation">এই ডিভাইস Bluetooth Low Energy (BLE) সমর্থন করে না, যা bitchat কাজ করার জন্য প্রয়োজন।\n\nbitchat এর মেশ নেটওয়ার্ক তৈরি এবং ইন্টারনেট ছাড়াই কাছাকাছি ডিভাইসের সাথে যোগাযোগের জন্য BLE প্রয়োজন।</string>
<string name="checking_bluetooth_status">ব্লুটুথ অবস্থা পরীক্ষা করা হচ্ছে …</string>
<string name="battery_optimization_detected_title">ব্যাটারি অপ্টিমাইজেশন সনাক্ত</string>
<string name="battery_optimization_enabled_title">ব্যাটারি অপ্টিমাইজেশন সক্রিয়</string>
<string name="battery_optimization_explanation_short">মেশ সংযোগ বজায় রাখতে bitchat অবশ্যই ব্যাকগ্রাউন্ডে চলতে হবে। ব্যাটারি অপ্টিমাইজেশন এই সংযোগগুলি বাধাগ্রস্ত করতে পারে।</string>
<string name="benefits_of_disabling">নিষ্ক্রিয় করার সুবিধা</string>
<string name="battery_benefits_short">• নির্ভরযোগ্য বার্তা ডেলিভারি\n• মেশ সংযোগ বজায় রাখা\n• সংযোগ বিচ্ছিন্নতা প্রতিরোধ</string>
<string name="disable_battery_optimization">ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয় করুন</string>
<string name="battery_optimization_disabled_title">ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয়</string>
<string name="continue_btn">চালিয়ে যান</string>
<string name="initializing_mesh_network">মেশ নেটওয়ার্ক শুরু করা হচ্ছে</string>
<string name="setting_up_bluetooth">ব্লুটুথ মেশ নেটওয়ার্ক সেটআপ করা হচ্ছে …</string>
<string name="should_take_seconds">এটি মাত্র কয়েক সেকেন্ড সময় নেওয়া উচিত</string>
<string name="setup_not_complete">সেটআপ সম্পূর্ণ নয়</string>
<string name="try_again">আবার চেষ্টা করুন</string>
<string name="privacy_protected">আপনার গোপনীয়তা সুরক্ষিত</string>
<string name="privacy_bullets">• কোন ট্র্যাকিং বা ডেটা সংগ্রহ নেই\n• ব্লুটুথ মেশ চ্যাট সম্পূর্ণ অফলাইন\n• জিওহ্যাশ চ্যাট ইন্টারনেট ব্যবহার করে</string>
<string name="permissions_header">অনুমতি</string>
<string name="grant_permissions">অনুমতি দিন</string>
<string name="location_tracking_warning">bitchat আপনার অবস্থান ট্র্যাক করে না</string>
<string name="geohash_people_header">মানুষ</string>
<string name="nobody_around">কেউ আশেপাশে নেই …</string>
<string name="you_suffix"> (আপনি)</string>
<string name="pan_zoom_instruction">জিওহ্যাশ নির্বাচন করতে প্যান এবং জুম করুন</string>
<string name="select">নির্বাচন করুন</string>
<string name="type_a_message_placeholder">বার্তা টাইপ করুন …</string>
<string name="mention">উল্লেখ</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">ছবি</string>
<string name="media_type_file">ফাইল</string>
<!-- বিজ্ঞপ্তি টেক্সট সহায়ক -->
<string name="notification_sent_image">📷 একটি ছবি পাঠিয়েছে</string>
<string name="notification_sent_voice">🎤 একটি ভয়েস বার্তা পাঠিয়েছে</string>
<string name="notification_sent_file">📎 একটি ফাইল পাঠিয়েছে</string>
<!-- ভয়েস প্লেয়ার অ্যাক্সেসিবিলিটি -->
<string name="cd_play_voice">প্লে করুন</string>
<string name="cd_pause_voice">বিরাম</string>
<string name="cd_mining_pow">মাইনিং PoW</string>
<string name="cd_pow_enabled">PoW সক্রিয়</string>
<string name="cd_proof_of_work">প্রুফ অফ ওয়ার্ক</string>
<string name="pow_mining_ellipsis">মাইনিং …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- অনুমতি বিবরণ -->
<string name="perm_nearby_devices_desc">ব্লুটুথের মাধ্যমে bitchat ব্যবহারকারী আবিষ্কার করতে প্রয়োজন</string>
<string name="perm_nearby_devices_system">bitchat কে কাছাকাছি ডিভাইসের সাথে সংযোগ করার অনুমতি দিন</string>
<string name="perm_location_desc">ব্লুটুথের মাধ্যমে কাছাকাছি bitchat ব্যবহারকারী আবিষ্কার করার জন্য Android এর প্রয়োজন</string>
<string name="perm_location_system">bitchat এর কাছাকাছি ডিভাইস স্ক্যান করার জন্য এটি প্রয়োজন</string>
<string name="perm_notifications_desc">ব্যক্তিগত বার্তা পেলে বিজ্ঞপ্তি পান</string>
<string name="perm_notifications_system">bitchat কে আপনাকে বিজ্ঞপ্তি পাঠানোর অনুমতি দিন</string>
<string name="perm_battery_desc">bitchat নির্ভরযোগ্যভাবে ব্যাকগ্রাউন্ডে চলে এবং মেশ নেটওয়ার্ক সংযোগ বজায় রাখে তা নিশ্চিত করতে ব্যাটারি অপ্টিমাইজেশন নিষ্ক্রিয় করুন</string>
<string name="perm_battery_system">bitchat কে ব্যাটারি সীমাবদ্ধতা ছাড়াই চলার অনুমতি দিন</string>
<!-- অনুমতির ধরণ -->
<string name="perm_type_nearby_devices">কাছাকাছি ডিভাইস</string>
<string name="perm_type_precise_location">সঠিক অবস্থান</string>
<string name="perm_type_microphone">মাইক্রোফোন</string>
<string name="perm_type_notifications">বিজ্ঞপ্তি</string>
<string name="perm_type_battery_optimization">ব্যাটারি অপ্টিমাইজেশন</string>
<string name="perm_type_other">অন্যান্য</string>
<!-- পাসওয়ার্ড ডায়ালগ -->
<string name="pwd_prompt_title">চ্যানেল পাসওয়ার্ড লিখুন</string>
<string name="pwd_prompt_message">চ্যানেল %1$s পাসওয়ার্ড দিয়ে সুরক্ষিত। যোগ দিতে পাসওয়ার্ড লিখুন।</string>
<string name="pwd_label">পাসওয়ার্ড</string>
<string name="join">যোগ দিন</string>
<string name="cancel">বাতিল</string>
<!-- বহুবচন -->
<plurals name="notification_and_more">
<item quantity="one">এবং %d আরো</item>
<item quantity="other">এবং %d আরো</item>
</plurals>
<plurals name="people_count">
<item quantity="one">১ জন</item>
<item quantity="other">%d জন</item>
</plurals>
</resources>
+366
View File
@@ -0,0 +1,366 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Berechtigungsbegründungen -->
<string name="permission_bluetooth_rationale">Die BluetoothBerechtigung ist erforderlich, um ohne Internet direkt mit anderen zu chatten.</string>
<string name="permission_location_rationale">Die StandortBerechtigung ist erforderlich, um in der Nähe befindliche Geräte per Bluetooth zu finden.</string>
<string name="permission_notification_rationale">Die BenachrichtigungsBerechtigung ist erforderlich, um dich über neue Nachrichten zu informieren.</string>
<!-- Platzhalter / grundlegende UI -->
<string name="nickname_hint">Spitzname</string>
<string name="message_hint">Nachricht eingeben…</string>
<string name="channel_password_hint">Passwort</string>
<string name="join_channel">Kanal beitreten</string>
<string name="leave_channel">Verlassen</string>
<string name="send_message">Senden</string>
<string name="show_commands">Befehle anzeigen</string>
<string name="back">Zurück</string>
<string name="people">Personen</string>
<string name="channels">Kanäle</string>
<string name="online_users">OnlineBenutzer</string>
<string name="no_one_connected">Niemand verbunden</string>
<string name="emergency_clear_hint">Dreifach tippen, um alle Daten zu löschen</string>
<string name="your_network">Netzwerk</string>
<!-- AkkuOptimierung -->
<string name="battery_optimization_detected">AkkuOptimierung erkannt</string>
<string name="battery_optimization_disabled">AkkuOptimierung deaktiviert</string>
<string name="battery_optimization_not_required">AkkuOptimierung nicht erforderlich</string>
<string name="battery_optimization_checking">AkkuOptimierung wird geprüft</string>
<string name="battery_optimization_why_disable">Warum AkkuOptimierung deaktivieren?</string>
<string name="battery_optimization_explanation">bitchat läuft im Hintergrund, um MeshVerbindungen zu nahegelegenen Geräten aufrechtzuerhalten. Die AkkuOptimierung kann diese Verbindungen unterbrechen, wodurch Nachrichten verspätet zugestellt werden oder verloren gehen.\n\nDas Deaktivieren der AkkuOptimierung sorgt für eine zuverlässige PeertoPeerKommunikation.</string>
<string name="battery_optimization_disable_button">AkkuOptimierung deaktivieren</string>
<string name="battery_optimization_note">Hinweis: Du kannst dies später unter AndroidEinstellungen &gt; Apps &gt; bitchat &gt; Akku ändern.</string>
<string name="battery_optimization_not_supported_explanation">Dein Gerät benötigt keine AkkuOptimierungs­einstellungen. bitchat läuft normal.</string>
<string name="battery_optimization_not_supported_message">Dein Gerät benötigt keine AkkuOptimierungs­einstellungen. bitchat läuft normal.</string>
<string name="battery_optimization_success_message">bitchat kann zuverlässig im Hintergrund laufen</string>
<string name="battery_optimization_benefits">• Zuverlässige Zustellung von Nachrichten\n• Aufrechterhaltung der MeshVerbindung\n• Hintergrundweiterleitung von Nachrichten\n• Verhindert Verbindungsabbrüche</string>
<string name="battery_optimization_check_again">Erneut prüfen</string>
<string name="battery_optimization_skip">Jetzt überspringen</string>
<string name="battery_optimization_continue">Fortfahren</string>
<string name="retry">Erneut versuchen</string>
<string name="skip">Überspringen</string>
<!-- Benachrichtigungen -->
<string name="notification_summary_more">und %1$d weitere</string>
<string name="notification_messages_from_people">%1$d Nachrichten von %2$d Personen</string>
<string name="notification_more_conversations">und %1$d weitere Unterhaltungen</string>
<string name="notification_active_peers_title">👥 bitchatter in der Nähe!</string>
<string name="notification_active_peers_one">1 Person in der Nähe</string>
<string name="notification_active_peers_many">%1$d Personen in der Nähe</string>
<string name="notification_new_messages">Neue Nachrichten</string>
<string name="notification_new_location_messages">Neue StandortNachrichten</string>
<string name="notification_mentions_in">Erwähnt in %1$s</string>
<string name="notification_mentions_in_more">Erwähnt in %1$s (+%2$d weitere)</string>
<string name="notification_mentions_in_plural">%1$d Erwähnungen in %2$s</string>
<string name="notification_new_activity_in">Neue Aktivität in %1$s</string>
<string name="notification_messages_in">Nachrichten in %1$s</string>
<string name="notification_joined_conversation">%1$s ist der Unterhaltung beigetreten</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d Erwähnungen</string>
<string name="notification_geohash_summary_title">bitchat OrtsChats</string>
<string name="notification_geohash_summary_text">%1$d Nachrichten aus %2$d Orten</string>
<string name="notification_mesh_mention_title_singular">In MeshChat erwähnt</string>
<string name="notification_mesh_mention_title_plural">%1$d Erwähnungen im MeshChat</string>
<string name="notification_more_locations">und %1$d weitere Orte</string>
<string name="notification_and_more">und %1$d weitere</string>
<!-- Favoriten Zugänglichkeit -->
<string name="cd_add_favorite">Zu Favoriten hinzufügen</string>
<string name="cd_remove_favorite">Aus Favoriten entfernen</string>
<string name="cd_add_bookmark">Lesezeichen hinzufügen</string>
<!-- ChatKopf & Barrierefreiheit -->
<string name="chat_back">zurück</string>
<string name="chat_channel_prefix">Kanal: %1$s</string>
<string name="chat_leave">verlassen</string>
<string name="cd_nostr_reachable">Über Nostr erreichbar</string>
<string name="cd_unread_private_messages">Ungelesene private Nachrichten</string>
<string name="cd_toggle_bookmark">Lesezeichen umschalten</string>
<string name="cd_teleported">Teleportiert</string>
<string name="cd_tor_status">TorStatus</string>
<string name="cd_connected_peers">Verbundenen Peers</string>
<string name="cd_geohash_participants">GeohashTeilnehmer</string>
<string name="cd_ready_for_handshake">Bereit für Handshake</string>
<string name="cd_handshake_in_progress">Handshake läuft</string>
<string name="cd_encrypted">EndezuEnde verschlüsselt</string>
<string name="cd_handshake_failed">Handshake fehlgeschlagen</string>
<!-- DateiansichtDialog -->
<string name="file_viewer_title">📎 Datei empfangen</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Größe: %1$s</string>
<string name="file_viewer_type">🏷️ Typ: %1$s</string>
<string name="file_viewer_open_save">📂 Öffnen / Speichern</string>
<string name="close_with_emoji">❌ Schließen</string>
<string name="pick_image">Bild auswählen</string>
<!-- ÜberSheet -->
<string name="about_tagline">dezentraler MeshChat mit EndezuEndeVerschlüsselung</string>
<string name="about_offline_mesh_title">OfflineMeshChat</string>
<string name="about_offline_mesh_desc">Kommuniziere direkt über Bluetooth LE ohne Internet oder Server. Nachrichten werden über nahe Geräte weitergeleitet, um die Reichweite zu erhöhen.</string>
<string name="about_online_geohash_title">OnlineGeohashKanäle</string>
<string name="about_online_geohash_desc">Vernetze dich mit Menschen in deiner Umgebung über geohashbasierte Kanäle. Erweitere das Mesh über öffentliche InternetRelays.</string>
<string name="about_e2e_title">EndezuEndeVerschlüsselung</string>
<string name="about_e2e_desc">Private Nachrichten sind verschlüsselt. KanalNachrichten sind öffentlich.</string>
<string name="about_appearance">Darstellung</string>
<string name="about_system">System</string>
<string name="about_light">Hell</string>
<string name="about_dark">Dunkel</string>
<string name="about_pow">Proof of Work</string>
<string name="about_pow_off">PoW aus</string>
<string name="about_pow_on">PoW an</string>
<string name="about_pow_tip">Füge GeohashNachrichten einen Proof of Work hinzu, um Spam zu erschweren.</string>
<string name="about_pow_difficulty">Schwierigkeit: %1$d Bit (~%2$s)</string>
<string name="about_pow_difficulty_attempts">Schwierigkeit %1$d erfordert ~%2$s HashVersuche</string>
<string name="about_pow_desc_none">kein Proof of Work erforderlich</string>
<string name="about_pow_desc_very_low">sehr niedrig minimaler Spamschutz</string>
<string name="about_pow_desc_low">niedrig grundlegender Spamschutz</string>
<string name="about_pow_desc_medium">mittel guter Spamschutz</string>
<string name="about_pow_desc_high">hoch starker Spamschutz</string>
<string name="about_pow_desc_very_high">sehr hoch kann Verzögerungen verursachen</string>
<string name="about_pow_desc_extreme">extrem erhebliche Rechenleistung erforderlich</string>
<string name="about_network">Netzwerk</string>
<string name="about_tor_off">Tor aus</string>
<string name="about_tor_on">Tor an</string>
<string name="about_tor_route">Leite Internetverkehr über Tor für mehr Privatsphäre.</string>
<string name="about_tor_status">TorStatus: %1$s, Bootstrap %2$d%%</string>
<string name="about_last">Zuletzt: %1$s</string>
<string name="about_emergency_title">NotfallDatenlöschung</string>
<string name="about_emergency_tip">Tipp: Dreifach auf den AppTitel tippen, um alle gespeicherten Daten einschließlich Nachrichten, Schlüssel und Einstellungen zu löschen.</string>
<string name="about_debug_settings">DebugEinstellungen</string>
<string name="about_footer">Open Source • Privacy First • Dezentral</string>
<string name="close_plain">Schließen</string>
<string name="cancel_lower">abbrechen</string>
<!-- Allgemeine ContentDescriptions -->
<string name="cd_warning">Warnung</string>
<string name="cd_location_services">Standortdienste</string>
<string name="cd_privacy">Privatsphäre</string>
<string name="cd_error">Fehler</string>
<string name="cd_battery_optimization">AkkuOptimierung</string>
<string name="cd_benefits">Vorteile</string>
<string name="cd_checking_battery_optimization">AkkuOptimierung wird geprüft</string>
<string name="cd_not_supported_battery_optimization">AkkuOptimierung nicht unterstützt</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Ungelesene Nachricht</string>
<string name="cd_open_map">Karte öffnen</string>
<string name="cd_remove_bookmark">Lesezeichen entfernen</string>
<string name="cd_teleport">Teleportieren</string>
<string name="cd_selected">Ausgewählt</string>
<string name="cd_leave_channel">Kanal verlassen</string>
<string name="cd_reachable_via_nostr">Über Nostr erreichbar</string>
<string name="cd_offline_favorite">Favorit (offline)</string>
<string name="cd_decrease_precision">Genauigkeit verringern</string>
<string name="cd_increase_precision">Genauigkeit erhöhen</string>
<string name="cd_select_geohash">Geohash auswählen</string>
<string name="cd_scroll_to_bottom">Nach unten scrollen</string>
<string name="cd_file">Datei</string>
<string name="cd_image">Bild</string>
<string name="cd_cancel">Abbrechen</string>
<string name="cd_link">Link</string>
<string name="cd_pick_media">Medien auswählen</string>
<string name="cd_pick_file">Datei auswählen</string>
<string name="cd_save_current_image">Aktuelles Bild speichern</string>
<string name="cd_close">Schließen</string>
<string name="cd_image_index_of">Bild %1$d von %2$d</string>
<string name="cd_privacy_protected">Privatsphäre geschützt</string>
<string name="cd_record_voice">Sprachnotiz aufnehmen</string>
<string name="cd_offline_mesh_chat">OfflineMeshChat</string>
<string name="cd_online_geohash_channels">OnlineGeohashKanäle</string>
<string name="cd_end_to_end_encryption">EndezuEndeVerschlüsselung</string>
<!-- Bilder & Dateien -->
<string name="image_page_of">Bild %1$d von %2$d</string>
<string name="image_unavailable">Bild nicht verfügbar</string>
<string name="image_saved_to_downloads">Bild in "Downloads" gespeichert</string>
<string name="image_save_failed">Bild konnte nicht gespeichert werden</string>
<string name="toast_image_saved">Bild in "Downloads" gespeichert</string>
<string name="toast_failed_to_save_image">Bild konnte nicht gespeichert werden</string>
<string name="pick_file">Datei auswählen</string>
<string name="file_unavailable">[Datei nicht verfügbar]</string>
<string name="unknown">unbekannt</string>
<!-- NutzerAktionsSheet -->
<string name="choose_action_message_or_user">Aktion für diese Nachricht oder diesen Benutzer wählen</string>
<string name="choose_action_user">Aktion für diesen Benutzer wählen</string>
<string name="action_copy_message_title">Nachricht kopieren</string>
<string name="action_copy_message_subtitle">Diese Nachricht in die Zwischenablage kopieren</string>
<string name="action_slap_title">%1$s ohrfeigen</string>
<string name="action_slap_subtitle">Eine spielerische Ohrfeige senden</string>
<string name="action_hug_title">%1$s umarmen</string>
<string name="action_hug_subtitle">Eine freundliche Umarmung senden</string>
<string name="action_block_title">%1$s blockieren</string>
<string name="action_block_subtitle">Alle Nachrichten dieses Benutzers blockieren</string>
<!-- GeohashKanäle Sheet -->
<string name="location_channels_title">#StandortKanäle</string>
<string name="location_channels_desc">Chatte mit Menschen in deiner Nähe über GeohashKanäle. Es wird nur ein grober Geohash geteilt, niemals exakte GPSDaten. Mache zur Wahrung deiner Privatsphäre keine Screenshots und teile diesen Bildschirm nicht.</string>
<string name="grant_location_permission">Standortberechtigung erteilen</string>
<string name="location_permission_denied">Standortberechtigung verweigert. In den Einstellungen aktivieren, um StandortKanäle zu nutzen.</string>
<string name="open_settings">Einstellungen öffnen</string>
<string name="location_permission_granted">\u2713 Standortberechtigung erteilt</string>
<string name="checking_permissions">Berechtigungen werden geprüft …</string>
<string name="finding_nearby_channels">Nahe Kanäle werden gesucht …</string>
<string name="bookmarked">Lesezeichen</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">Ungültiger Geohash</string>
<string name="teleport">teleportieren</string>
<string name="disable_location_services">Standortdienste deaktivieren</string>
<string name="enable_location_services">Standortdienste aktivieren</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">Block</string>
<string name="location_level_neighborhood">Nachbarschaft</string>
<string name="location_level_city">Stadt</string>
<string name="location_level_province">Provinz</string>
<string name="location_level_region">Region</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnostik -->
<string name="debug_tools">DebugWerkzeuge</string>
<string name="debug_tools_desc">EntwicklerWerkzeuge für Diagnose und Steuerung</string>
<string name="debug_verbose_logging">ausführliches Logging</string>
<string name="debug_verbose_hint">Protokolliert PeerBeitritte/Austritte, Verbindungsrichtung, Paketweiterleitung und Relays</string>
<string name="debug_bluetooth_roles">BluetoothRollen</string>
<string name="debug_gatt_server">GATTServer</string>
<string name="debug_connections_fmt">Verbindungen: %1$d / %2$d</string>
<string name="debug_max_server">max. Server</string>
<string name="debug_gatt_client">GATTClient</string>
<string name="debug_max_client">max. Client</string>
<string name="debug_overall_connections_fmt">Verbindungen: %1$d / %2$d</string>
<string name="debug_max_overall">max. gesamt</string>
<string name="debug_packet_relay">PaketRelay</string>
<string name="debug_since_start_fmt">seit Start: %1$d</string>
<string name="debug_roles_hint">Rollen ein/aus schalten und beim Deaktivieren alle Verbindungen schließen</string>
<string name="debug_sync_settings">SyncEinstellungen</string>
<string name="debug_max_packets_per_sync_fmt">max. Pakete pro Sync: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">max. GCSFiltergröße: %1$d Bytes (1281024)</string>
<string name="debug_target_fpr_fmt">ZielFPR: %1$.2f%%</string>
<string name="debug_connected_devices">verbundene Geräte</string>
<string name="debug_our_device_id_fmt">unsere GeräteID: %1$s</string>
<string name="debug_none">keine</string>
<string name="debug_disconnect">trennen</string>
<string name="debug_recent_scan_results">zuletzt gescannte Geräte</string>
<string name="debug_connect">verbinden</string>
<string name="debug_debug_console">DebugKonsole</string>
<string name="debug_clear">leeren</string>
<string name="debug_relays_window_fmt">letzte 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">abgeleitetes P: %1$s • geschätzte max. Elemente: %2$s</string>
<string name="debug_direct_suffix"> • direkt</string>
<string name="debug_role_server">als Server (wir hosten)</string>
<string name="debug_role_client">als Client (wir verbinden)</string>
<!-- OnboardingBildschirme -->
<string name="location_services_required">Standortdienste erforderlich</string>
<string name="privacy_first">Privatsphäre zuerst</string>
<string name="location_explanation">bitchat verfolgt NICHT deinen Standort.\n\nStandortdienste sind für BluetoothScanning und das GeohashChatFeature erforderlich.</string>
<string name="location_needs_for">bitchat benötigt Standortdienste für:</string>
<string name="location_needs_bullets">• BluetoothGerätescanning\n• Entdecken nahegelegener Benutzer im MeshNetzwerk\n• GeohashChatFeature\n• Keine Verfolgung oder Standortsammlung</string>
<string name="open_location_settings">Standorteinstellungen öffnen</string>
<string name="check_again">Erneut prüfen</string>
<string name="location_services_unavailable">Standortdienste nicht verfügbar</string>
<string name="location_unavailable_explanation">Standortdienste sind auf diesem Gerät nicht verfügbar. Das ist ungewöhnlich, da Standortdienste bei AndroidGeräten Standard sind.\n\nbitchat benötigt Standortdienste für das ordnungsgemäße Funktionieren des BluetoothScannings (AndroidAnforderung). Ohne diese kann die App keine nahegelegenen Benutzer entdecken.</string>
<string name="checking_location_services">Standortdienste werden geprüft …</string>
<string name="bluetooth_required">Bluetooth erforderlich</string>
<string name="bluetooth_needs_for">bitchat benötigt Bluetooth für:</string>
<string name="bluetooth_needs_bullets">• Entdecken nahegelegener Benutzer\n• Erstellen von MeshNetzwerkverbindungen\n• Senden und Empfangen von Nachrichten\n• Funktionieren ohne Internet oder Server</string>
<string name="enable_bluetooth">Bluetooth aktivieren</string>
<string name="bluetooth_not_supported">Bluetooth nicht unterstützt</string>
<string name="bluetooth_unsupported_explanation">Dieses Gerät unterstützt kein Bluetooth Low Energy (BLE), das für das Funktionieren von bitchat erforderlich ist.\n\nbitchat benötigt BLE, um MeshNetzwerke zu erstellen und ohne Internet mit nahegelegenen Geräten zu kommunizieren.</string>
<string name="checking_bluetooth_status">BluetoothStatus wird geprüft …</string>
<string name="battery_optimization_detected_title">AkkuOptimierung erkannt</string>
<string name="battery_optimization_enabled_title">AkkuOptimierung aktiviert</string>
<string name="battery_optimization_explanation_short">bitchat muss im Hintergrund laufen, um MeshVerbindungen aufrechtzuerhalten. Die AkkuOptimierung kann diese Verbindungen unterbrechen.</string>
<string name="benefits_of_disabling">Vorteile der Deaktivierung</string>
<string name="battery_benefits_short">• zuverlässige Nachrichtenzustellung\n• Aufrechterhaltung der MeshKonnektivität\n• verhindert Verbindungsabbrüche</string>
<string name="disable_battery_optimization">AkkuOptimierung deaktivieren</string>
<string name="battery_optimization_disabled_title">AkkuOptimierung deaktiviert</string>
<string name="continue_btn">Fortfahren</string>
<string name="initializing_mesh_network">MeshNetzwerk wird initialisiert</string>
<string name="setting_up_bluetooth">BluetoothMeshNetzwerk wird eingerichtet …</string>
<string name="should_take_seconds">Das sollte nur wenige Sekunden dauern</string>
<string name="setup_not_complete">Setup nicht abgeschlossen</string>
<string name="try_again">Erneut versuchen</string>
<string name="privacy_protected">Deine Privatsphäre ist geschützt</string>
<string name="privacy_bullets">• keine Verfolgung oder Datensammlung\n• BluetoothMeshChats sind vollständig offline\n• GeohashChats nutzen das Internet</string>
<string name="permissions_header">Berechtigungen</string>
<string name="grant_permissions">Berechtigungen erteilen</string>
<string name="location_tracking_warning">bitchat verfolgt NICHT deinen Standort</string>
<string name="geohash_people_header">PERSONEN</string>
<string name="nobody_around">niemand da …</string>
<string name="you_suffix"> (du)</string>
<string name="pan_zoom_instruction">schwenken und zoomen, um einen Geohash auszuwählen</string>
<string name="select">auswählen</string>
<string name="type_a_message_placeholder">Nachricht eingeben …</string>
<string name="mention">erwähnen</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Bild</string>
<string name="media_type_file">Datei</string>
<!-- BenachrichtigungsTextHelfer -->
<string name="notification_sent_image">📷 hat ein Bild gesendet</string>
<string name="notification_sent_voice">🎤 hat eine Sprachnachricht gesendet</string>
<string name="notification_sent_file">📎 hat eine Datei gesendet</string>
<!-- Sprachplayer Barrierefreiheit -->
<string name="cd_play_voice">Abspielen</string>
<string name="cd_pause_voice">Pause</string>
<string name="cd_mining_pow">MiningPoW</string>
<string name="cd_pow_enabled">PoW aktiviert</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">Mining …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Berechtigungsbeschreibungen -->
<string name="perm_nearby_devices_desc">Erforderlich, um bitchatBenutzer über Bluetooth zu entdecken</string>
<string name="perm_nearby_devices_system">Erlaube bitchat, sich mit nahegelegenen Geräten zu verbinden</string>
<string name="perm_location_desc">Von Android erforderlich, um nahegelegene bitchatBenutzer über Bluetooth zu entdecken</string>
<string name="perm_location_system">bitchat benötigt dies, um nach nahegelegenen Geräten zu scannen</string>
<string name="perm_notifications_desc">Benachrichtigungen erhalten, wenn du private Nachrichten erhältst</string>
<string name="perm_notifications_system">Erlaube bitchat, dir Benachrichtigungen zu senden</string>
<string name="perm_battery_desc">AkkuOptimierung deaktivieren, um sicherzustellen, dass bitchat zuverlässig im Hintergrund läuft und MeshNetzwerkverbindungen aufrechterhält</string>
<string name="perm_battery_system">Erlaube bitchat, ohne AkkuBeschränkungen zu laufen</string>
<!-- Berechtigungstypen -->
<string name="perm_type_nearby_devices">Nahegelegene Geräte</string>
<string name="perm_type_precise_location">Genauer Standort</string>
<string name="perm_type_microphone">Mikrofon</string>
<string name="perm_type_notifications">Benachrichtigungen</string>
<string name="perm_type_battery_optimization">AkkuOptimierung</string>
<string name="perm_type_other">Andere</string>
<!-- PasswortDialog -->
<string name="pwd_prompt_title">Kanalpasswort eingeben</string>
<string name="pwd_prompt_message">Kanal %1$s ist passwortgeschützt. Gib zum Beitreten das Passwort ein.</string>
<string name="pwd_label">Passwort</string>
<string name="join">Beitreten</string>
<string name="cancel">Abbrechen</string>
<!-- Plurals -->
<plurals name="notification_and_more">
<item quantity="one">und %d weitere</item>
<item quantity="other">und %d weitere</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 Person</item>
<item quantity="other">%d Personen</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d Notiz</item>
<item quantity="other">#%1$s ± 1 • %2$d Notizen</item>
</plurals>
<string name="location_notes_description">füge kurze dauerhafte Notizen zu diesem Ort hinzu, damit andere Besucher sie finden.</string>
<string name="location_notes_relays_unavailable">Geo-Relays nicht verfügbar; Notizen pausiert</string>
<string name="location_notes_no_relays_title">keine Geo-Relays in der Nähe</string>
<string name="location_notes_no_relays_desc">Notizen basieren auf Geo-Relays. Verbindung prüfen und erneut versuchen.</string>
<string name="loading_location_notes">Notizen werden geladen…</string>
<string name="location_notes_empty_title">noch keine Notizen</string>
<string name="location_notes_empty_desc">sei der Erste, der hier eine Notiz hinterlässt.</string>
<string name="dismiss">schließen</string>
<string name="location_notes_input_placeholder">füge eine Notiz zu diesem Ort hinzu</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Justificaciones de permisos -->
<string name="permission_bluetooth_rationale">El permiso de Bluetooth es necesario para chatear directamente con otros sin internet.</string>
<string name="permission_location_rationale">El permiso de ubicación es necesario para encontrar dispositivos cercanos a través de Bluetooth.</string>
<string name="permission_notification_rationale">El permiso de notificaciones es necesario para alertarte sobre nuevos mensajes.</string>
<!-- Placeholders / UI básica -->
<string name="nickname_hint">Apodo</string>
<string name="message_hint">Escribe un mensaje…</string>
<string name="channel_password_hint">Contraseña</string>
<string name="join_channel">Unirse al canal</string>
<string name="leave_channel">Salir</string>
<string name="send_message">Enviar</string>
<string name="show_commands">Mostrar comandos</string>
<string name="back">Atrás</string>
<string name="people">Personas</string>
<string name="channels">Canales</string>
<string name="online_users">Usuarios en línea</string>
<string name="no_one_connected">Nadie conectado</string>
<string name="emergency_clear_hint">Toca tres veces para borrar todos los datos</string>
<string name="your_network">Tu red</string>
<!-- Optimización de batería -->
<string name="battery_optimization_detected">Optimización de batería detectada</string>
<string name="battery_optimization_disabled">Optimización de batería deshabilitada</string>
<string name="battery_optimization_not_required">Optimización de batería no requerida</string>
<string name="battery_optimization_checking">Verificando optimización de batería</string>
<string name="battery_optimization_why_disable">¿Por qué deshabilitar la optimización de batería?</string>
<string name="battery_optimization_explanation">bitchat funciona en segundo plano para mantener conexiones de red mesh con dispositivos cercanos. La optimización de batería puede interrumpir estas conexiones, causando que los mensajes lleguen tarde o se pierdan.\n\nDeshabilitar la optimización de batería asegura una comunicación peer-to-peer confiable.</string>
<string name="battery_optimization_disable_button">Deshabilitar optimización de batería</string>
<string name="battery_optimization_note">Nota: Puedes cambiar esto más tarde en Configuración de Android > Apps > bitchat > Batería.</string>
<string name="battery_optimization_not_supported_explanation">Tu dispositivo no requiere configuraciones de optimización de batería. bitchat funcionará normalmente.</string>
<string name="battery_optimization_not_supported_message">Tu dispositivo no requiere configuraciones de optimización de batería. bitchat funcionará normalmente.</string>
<string name="battery_optimization_success_message">bitchat puede funcionar de manera confiable en segundo plano</string>
<string name="battery_optimization_benefits">• Entrega confiable de mensajes\n• Mantiene conexión de red mesh\n• Retransmisión de mensajes en segundo plano\n• Previene desconexiones</string>
<string name="battery_optimization_check_again">Verificar de nuevo</string>
<string name="battery_optimization_skip">Omitir por ahora</string>
<string name="battery_optimization_continue">Continuar</string>
<string name="retry">Reintentar</string>
<string name="skip">Omitir</string>
<!-- Notificaciones -->
<string name="notification_summary_more">y %1$d más</string>
<string name="notification_messages_from_people">%1$d mensajes de %2$d personas</string>
<string name="notification_more_conversations">y %1$d conversaciones más</string>
<string name="notification_active_peers_title">👥 ¡bitchatters cerca!</string>
<string name="notification_active_peers_one">1 persona cerca</string>
<string name="notification_active_peers_many">%1$d personas cerca</string>
<string name="notification_new_messages">Nuevos mensajes</string>
<string name="notification_new_location_messages">Nuevos mensajes de ubicación</string>
<string name="notification_mentions_in">Mencionado en %1$s</string>
<string name="notification_mentions_in_more">Mencionado en %1$s (+%2$d más)</string>
<string name="notification_mentions_in_plural">%1$d menciones en %2$s</string>
<string name="notification_new_activity_in">Nueva actividad en %1$s</string>
<string name="notification_messages_in">Mensajes en %1$s</string>
<string name="notification_joined_conversation">%1$s se unió a la conversación</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d menciones</string>
<string name="notification_geohash_summary_title">bitchat Chats de ubicación</string>
<string name="notification_geohash_summary_text">%1$d mensajes desde %2$d ubicaciones</string>
<string name="notification_mesh_mention_title_singular">Mencionado en chat mesh</string>
<string name="notification_mesh_mention_title_plural">%1$d menciones en chat mesh</string>
<string name="notification_more_locations">y %1$d ubicaciones más</string>
<string name="notification_and_more">y %1$d más</string>
<!-- Accesibilidad de favoritos -->
<string name="cd_add_favorite">Agregar a favoritos</string>
<string name="cd_remove_favorite">Quitar de favoritos</string>
<string name="cd_add_bookmark">Agregar marcador</string>
<!-- Encabezado de chat y accesibilidad -->
<string name="chat_back">atrás</string>
<string name="chat_channel_prefix">Canal: %1$s</string>
<string name="chat_leave">salir</string>
<string name="cd_nostr_reachable">Accesible vía Nostr</string>
<string name="cd_unread_private_messages">Mensajes privados sin leer</string>
<string name="cd_toggle_bookmark">Alternar marcador</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Estado de Tor</string>
<string name="cd_connected_peers">Pares conectados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Listo para handshake</string>
<string name="cd_handshake_in_progress">Handshake en progreso</string>
<string name="cd_encrypted">Cifrado de extremo a extremo</string>
<string name="cd_handshake_failed">Handshake fallido</string>
<!-- Diálogo de visor de archivos -->
<string name="file_viewer_title">📎 Archivo recibido</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Tamaño: %1$s</string>
<string name="file_viewer_type">🏷️ Tipo: %1$s</string>
<string name="file_viewer_open_save">📂 Abrir / Guardar</string>
<string name="close_with_emoji">❌ Cerrar</string>
<string name="pick_image">Elegir imagen</string>
<!-- Hoja Acerca de -->
<string name="about_tagline">chat mesh descentralizado con cifrado de extremo a extremo</string>
<string name="about_offline_mesh_title">Chat mesh sin conexión</string>
<string name="about_offline_mesh_desc">Comunícate directamente a través de Bluetooth LE sin internet o servidores. Los mensajes se retransmiten a través de dispositivos cercanos para extender el alcance.</string>
<string name="about_online_geohash_title">Canales geohash en línea</string>
<string name="about_online_geohash_desc">Conéctate con personas cerca de ti a través de canales basados en geohash. Extiende la red mesh a través de repetidores de internet público.</string>
<string name="about_e2e_title">Cifrado de extremo a extremo</string>
<string name="about_e2e_desc">Los mensajes privados están cifrados. Los mensajes de canal son públicos.</string>
<string name="about_appearance">Apariencia</string>
<string name="about_system">Sistema</string>
<string name="about_light">Claro</string>
<string name="about_dark">Oscuro</string>
<string name="about_pow">Prueba de trabajo</string>
<string name="about_pow_off">PoW desactivado</string>
<string name="about_pow_on">PoW activado</string>
<string name="about_pow_tip">Agregar prueba de trabajo a mensajes geohash para hacer el spam más difícil.</string>
<string name="about_pow_difficulty">Dificultad: %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">Dificultad %1$d requiere ~%2$s intentos de hash</string>
<string name="about_pow_desc_none">no se requiere prueba de trabajo</string>
<string name="about_pow_desc_very_low">muy bajo protección mínima contra spam</string>
<string name="about_pow_desc_low">bajo protección básica contra spam</string>
<string name="about_pow_desc_medium">medio buena protección contra spam</string>
<string name="about_pow_desc_high">alto protección fuerte contra spam</string>
<string name="about_pow_desc_very_high">muy alto puede causar retrasos</string>
<string name="about_pow_desc_extreme">extremo requiere potencia computacional significativa</string>
<string name="about_network">Red</string>
<string name="about_tor_off">Tor desactivado</string>
<string name="about_tor_on">Tor activado</string>
<string name="about_tor_route">Enrutar tráfico de internet a través de Tor para mayor privacidad.</string>
<string name="about_tor_status">Estado de Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Último: %1$s</string>
<string name="about_emergency_title">Borrado de datos de emergencia</string>
<string name="about_emergency_tip">Consejo: Toca tres veces en el título de la app para borrar todos los datos almacenados, incluyendo mensajes, claves y configuraciones.</string>
<string name="about_debug_settings">Configuraciones de depuración</string>
<string name="about_footer">Código abierto • Privacidad primero • Descentralizado</string>
<string name="close_plain">Cerrar</string>
<string name="cancel_lower">cancelar</string>
<!-- Descripciones de contenido generales -->
<string name="cd_warning">Advertencia</string>
<string name="cd_location_services">Servicios de ubicación</string>
<string name="cd_privacy">Privacidad</string>
<string name="cd_error">Error</string>
<string name="cd_battery_optimization">Optimización de batería</string>
<string name="cd_benefits">Beneficios</string>
<string name="cd_checking_battery_optimization">Verificando optimización de batería</string>
<string name="cd_not_supported_battery_optimization">Optimización de batería no soportada</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Mensaje sin leer</string>
<string name="cd_open_map">Abrir mapa</string>
<string name="cd_remove_bookmark">Quitar marcador</string>
<string name="cd_teleport">Teletransportar</string>
<string name="cd_selected">Seleccionado</string>
<string name="cd_leave_channel">Salir del canal</string>
<string name="cd_reachable_via_nostr">Accesible vía Nostr</string>
<string name="cd_offline_favorite">Favorito (sin conexión)</string>
<string name="cd_decrease_precision">Disminuir precisión</string>
<string name="cd_increase_precision">Aumentar precisión</string>
<string name="cd_select_geohash">Seleccionar geohash</string>
<string name="cd_scroll_to_bottom">Desplazar al final</string>
<string name="cd_file">Archivo</string>
<string name="cd_image">Imagen</string>
<string name="cd_cancel">Cancelar</string>
<string name="cd_link">Enlace</string>
<string name="cd_pick_media">Elegir medios</string>
<string name="cd_pick_file">Elegir archivo</string>
<string name="cd_save_current_image">Guardar imagen actual</string>
<string name="cd_close">Cerrar</string>
<string name="cd_image_index_of">Imagen %1$d de %2$d</string>
<string name="cd_privacy_protected">Privacidad protegida</string>
<string name="cd_record_voice">Grabar nota de voz</string>
<string name="cd_offline_mesh_chat">Chat mesh sin conexión</string>
<string name="cd_online_geohash_channels">Canales geohash en línea</string>
<string name="cd_end_to_end_encryption">Cifrado de extremo a extremo</string>
<!-- Imágenes y archivos -->
<string name="image_page_of">Imagen %1$d de %2$d</string>
<string name="image_unavailable">Imagen no disponible</string>
<string name="image_saved_to_downloads">Imagen guardada en "Descargas"</string>
<string name="image_save_failed">No se pudo guardar la imagen</string>
<string name="toast_image_saved">Imagen guardada en "Descargas"</string>
<string name="toast_failed_to_save_image">No se pudo guardar la imagen</string>
<string name="pick_file">Elegir archivo</string>
<string name="file_unavailable">[Archivo no disponible]</string>
<string name="unknown">desconocido</string>
<!-- Hoja de acciones de usuario -->
<string name="choose_action_message_or_user">Elegir acción para este mensaje o usuario</string>
<string name="choose_action_user">Elegir acción para este usuario</string>
<string name="action_copy_message_title">Copiar mensaje</string>
<string name="action_copy_message_subtitle">Copiar este mensaje al portapapeles</string>
<string name="action_slap_title">Abofetear a %1$s</string>
<string name="action_slap_subtitle">Enviar una bofetada juguetona</string>
<string name="action_hug_title">Abrazar a %1$s</string>
<string name="action_hug_subtitle">Enviar un abrazo amistoso</string>
<string name="action_block_title">Bloquear a %1$s</string>
<string name="action_block_subtitle">Bloquear todos los mensajes de este usuario</string>
<!-- Hoja de canales geohash -->
<string name="location_channels_title">#Canales de ubicación</string>
<string name="location_channels_desc">Chatea con personas cerca de ti a través de canales geohash. Solo se comparte un geohash aproximado, nunca datos GPS exactos. Para preservar tu privacidad, no tomes capturas de pantalla ni compartas esta pantalla.</string>
<string name="grant_location_permission">Otorgar permiso de ubicación</string>
<string name="location_permission_denied">Permiso de ubicación denegado. Habilítalo en configuraciones para usar canales de ubicación.</string>
<string name="open_settings">Abrir configuraciones</string>
<string name="location_permission_granted">\u2713 Permiso de ubicación otorgado</string>
<string name="checking_permissions">Verificando permisos…</string>
<string name="finding_nearby_channels">Buscando canales cercanos…</string>
<string name="bookmarked">Marcado</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">Geohash inválido</string>
<string name="teleport">teletransportar</string>
<string name="disable_location_services">Deshabilitar servicios de ubicación</string>
<string name="enable_location_services">Habilitar servicios de ubicación</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">Cuadra</string>
<string name="location_level_neighborhood">Barrio</string>
<string name="location_level_city">Ciudad</string>
<string name="location_level_province">Provincia</string>
<string name="location_level_region">Región</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnóstico -->
<string name="debug_tools">Herramientas de depuración</string>
<string name="debug_tools_desc">Herramientas de desarrollador para diagnóstico y control</string>
<string name="debug_verbose_logging">registro detallado</string>
<string name="debug_verbose_hint">Registra uniones/salidas de pares, dirección de conexión, retransmisión de paquetes y repetidores</string>
<string name="debug_bluetooth_roles">Roles de Bluetooth</string>
<string name="debug_gatt_server">Servidor GATT</string>
<string name="debug_connections_fmt">Conexiones: %1$d / %2$d</string>
<string name="debug_max_server">máx. servidor</string>
<string name="debug_gatt_client">Cliente GATT</string>
<string name="debug_max_client">máx. cliente</string>
<string name="debug_overall_connections_fmt">Conexiones: %1$d / %2$d</string>
<string name="debug_max_overall">máx. general</string>
<string name="debug_packet_relay">Retransmisión de paquetes</string>
<string name="debug_since_start_fmt">desde inicio: %1$d</string>
<string name="debug_roles_hint">Alternar roles activado/desactivado y cerrar todas las conexiones al desactivar</string>
<string name="debug_sync_settings">Configuraciones de sincronización</string>
<string name="debug_max_packets_per_sync_fmt">máx. paquetes por sincronización: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">máx. tamaño del filtro GCS: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">FPR objetivo: %1$.2f%%</string>
<string name="debug_connected_devices">dispositivos conectados</string>
<string name="debug_our_device_id_fmt">nuestro ID de dispositivo: %1$s</string>
<string name="debug_none">ninguno</string>
<string name="debug_disconnect">desconectar</string>
<string name="debug_recent_scan_results">dispositivos escaneados recientemente</string>
<string name="debug_connect">conectar</string>
<string name="debug_debug_console">Consola de depuración</string>
<string name="debug_clear">limpiar</string>
<string name="debug_relays_window_fmt">últimos 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P derivado: %1$s • máx. elementos estimados: %2$s</string>
<string name="debug_direct_suffix"> • directo</string>
<string name="debug_role_server">como servidor (nosotros hospedamos)</string>
<string name="debug_role_client">como cliente (nosotros conectamos)</string>
<!-- Pantallas de incorporación -->
<string name="location_services_required">Servicios de ubicación requeridos</string>
<string name="privacy_first">Privacidad primero</string>
<string name="location_explanation">bitchat NO rastrea tu ubicación.\n\nLos servicios de ubicación son requeridos para el escaneo Bluetooth y la función de chat geohash.</string>
<string name="location_needs_for">bitchat necesita servicios de ubicación para:</string>
<string name="location_needs_bullets">• Escaneo de dispositivos Bluetooth\n• Descubrir usuarios cercanos en la red mesh\n• Función de chat geohash\n• Sin rastreo o recolección de ubicación</string>
<string name="open_location_settings">Abrir configuraciones de ubicación</string>
<string name="check_again">Verificar de nuevo</string>
<string name="location_services_unavailable">Servicios de ubicación no disponibles</string>
<string name="location_unavailable_explanation">Los servicios de ubicación no están disponibles en este dispositivo. Esto es inusual ya que los servicios de ubicación son estándar en dispositivos Android.\n\nbitchat requiere servicios de ubicación para el funcionamiento adecuado del escaneo Bluetooth (requisito de Android). Sin esto, la app no puede descubrir usuarios cercanos.</string>
<string name="checking_location_services">Verificando servicios de ubicación…</string>
<string name="bluetooth_required">Bluetooth requerido</string>
<string name="bluetooth_needs_for">bitchat necesita Bluetooth para:</string>
<string name="bluetooth_needs_bullets">• Descubrir usuarios cercanos\n• Crear conexiones de red mesh\n• Enviar y recibir mensajes\n• Funcionar sin internet o servidores</string>
<string name="enable_bluetooth">Habilitar Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth no soportado</string>
<string name="bluetooth_unsupported_explanation">Este dispositivo no soporta Bluetooth Low Energy (BLE), que es requerido para que bitchat funcione.\n\nbitchat requiere BLE para crear redes mesh y comunicarse con dispositivos cercanos sin internet.</string>
<string name="checking_bluetooth_status">Verificando estado de Bluetooth…</string>
<string name="battery_optimization_detected_title">Optimización de batería detectada</string>
<string name="battery_optimization_enabled_title">Optimización de batería habilitada</string>
<string name="battery_optimization_explanation_short">bitchat necesita funcionar en segundo plano para mantener conexiones mesh. La optimización de batería puede interrumpir estas conexiones.</string>
<string name="benefits_of_disabling">Beneficios de deshabilitar</string>
<string name="battery_benefits_short">• entrega confiable de mensajes\n• mantiene conectividad mesh\n• previene desconexiones</string>
<string name="disable_battery_optimization">Deshabilitar optimización de batería</string>
<string name="battery_optimization_disabled_title">Optimización de batería deshabilitada</string>
<string name="continue_btn">Continuar</string>
<string name="initializing_mesh_network">Inicializando red mesh</string>
<string name="setting_up_bluetooth">Configurando red mesh Bluetooth…</string>
<string name="should_take_seconds">Esto debería tomar solo unos segundos</string>
<string name="setup_not_complete">Configuración no completada</string>
<string name="try_again">Intentar de nuevo</string>
<string name="privacy_protected">Tu privacidad está protegida</string>
<string name="privacy_bullets">• sin rastreo o recolección de datos\n• chats mesh Bluetooth son completamente offline\n• chats geohash usan internet</string>
<string name="permissions_header">Permisos</string>
<string name="grant_permissions">Otorgar permisos</string>
<string name="location_tracking_warning">bitchat NO rastrea tu ubicación</string>
<string name="geohash_people_header">PERSONAS</string>
<string name="nobody_around">nadie por aquí…</string>
<string name="you_suffix"> (tú)</string>
<string name="pan_zoom_instruction">desplaza y hace zoom para seleccionar un geohash</string>
<string name="select">seleccionar</string>
<string name="type_a_message_placeholder">Escribe un mensaje…</string>
<string name="mention">mencionar</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Imagen</string>
<string name="media_type_file">Archivo</string>
<!-- Ayudantes de texto de notificación -->
<string name="notification_sent_image">📷 envió una imagen</string>
<string name="notification_sent_voice">🎤 envió una nota de voz</string>
<string name="notification_sent_file">📎 envió un archivo</string>
<!-- Accesibilidad del reproductor de voz -->
<string name="cd_play_voice">Reproducir</string>
<string name="cd_pause_voice">Pausar</string>
<string name="cd_mining_pow">Minando PoW</string>
<string name="cd_pow_enabled">PoW habilitado</string>
<string name="cd_proof_of_work">Prueba de trabajo</string>
<string name="pow_mining_ellipsis">Minando…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Descripciones de permisos -->
<string name="perm_nearby_devices_desc">Requerido para descubrir usuarios bitchat a través de Bluetooth</string>
<string name="perm_nearby_devices_system">Permitir que bitchat se conecte con dispositivos cercanos</string>
<string name="perm_location_desc">Requerido por Android para descubrir usuarios bitchat cercanos a través de Bluetooth</string>
<string name="perm_location_system">bitchat necesita esto para escanear dispositivos cercanos</string>
<string name="perm_notifications_desc">Recibir notificaciones cuando recibas mensajes privados</string>
<string name="perm_notifications_system">Permitir que bitchat te envíe notificaciones</string>
<string name="perm_battery_desc">Deshabilitar optimización de batería para asegurar que bitchat funcione de manera confiable en segundo plano y mantenga conexiones de red mesh</string>
<string name="perm_battery_system">Permitir que bitchat funcione sin restricciones de batería</string>
<!-- Tipos de permisos -->
<string name="perm_type_nearby_devices">Dispositivos cercanos</string>
<string name="perm_type_precise_location">Ubicación precisa</string>
<string name="perm_type_microphone">Micrófono</string>
<string name="perm_type_notifications">Notificaciones</string>
<string name="perm_type_battery_optimization">Optimización de batería</string>
<string name="perm_type_other">Otro</string>
<!-- Diálogo de contraseña -->
<string name="pwd_prompt_title">Ingresar contraseña del canal</string>
<string name="pwd_prompt_message">El canal %1$s está protegido con contraseña. Ingresa la contraseña para unirte.</string>
<string name="pwd_label">Contraseña</string>
<string name="join">Unirse</string>
<string name="cancel">Cancelar</string>
<!-- Plurales -->
<plurals name="notification_and_more">
<item quantity="one">y %d más</item>
<item quantity="other">y %d más</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 persona</item>
<item quantity="other">%d personas</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d nota</item>
<item quantity="other">#%1$s ± 1 • %2$d notas</item>
</plurals>
<string name="location_notes_description">agrega notas cortas y permanentes a este lugar para que otros visitantes las encuentren.</string>
<string name="location_notes_relays_unavailable">relés geográficos no disponibles; notas en pausa</string>
<string name="location_notes_no_relays_title">no hay relés geográficos cercanos</string>
<string name="location_notes_no_relays_desc">las notas dependen de relés geográficos. verifica la conexión e inténtalo de nuevo.</string>
<string name="loading_location_notes">cargando notas…</string>
<string name="location_notes_empty_title">aún no hay notas</string>
<string name="location_notes_empty_desc">sé el primero en añadir una para este sitio.</string>
<string name="dismiss">cerrar</string>
<string name="location_notes_input_placeholder">agrega una nota para este lugar</string>
</resources>
+352
View File
@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- توضیح مجوزها -->
<string name="permission_bluetooth_rationale">برای چت مستقیم با دیگران بدون اینترنت، به مجوز بلوتوث نیاز است.</string>
<string name="permission_location_rationale">برای یافتن دستگاه‌های نزدیک از طریق بلوتوث، به مجوز مکان نیاز است.</string>
<string name="permission_notification_rationale">برای آگاه‌سازی از پیام‌های جدید، به مجوز اعلان نیاز است.</string>
<!-- نگهدارنده‌ها / رابط کاربری پایه -->
<string name="nickname_hint">نام مستعار</string>
<string name="message_hint">نوشتن پیام…</string>
<string name="channel_password_hint">گذرواژه</string>
<string name="join_channel">پیوستن به کانال</string>
<string name="leave_channel">خروج</string>
<string name="send_message">ارسال</string>
<string name="show_commands">نمایش دستورات</string>
<string name="back">بازگشت</string>
<string name="people">افراد</string>
<string name="channels">کانال‌ها</string>
<string name="online_users">کاربران آنلاین</string>
<string name="no_one_connected">هیچ‌کس متصل نیست</string>
<string name="emergency_clear_hint">برای پاک کردن همهٔ داده‌ها سه بار ضربه بزنید</string>
<string name="your_network">شبکه</string>
<!-- بهینه‌سازی باتری -->
<string name="battery_optimization_detected">بهینه‌سازی باتری شناسایی شد</string>
<string name="battery_optimization_disabled">بهینه‌سازی باتری غیرفعال شد</string>
<string name="battery_optimization_not_required">بهینه‌سازی باتری لازم نیست</string>
<string name="battery_optimization_checking">در حال بررسی بهینه‌سازی باتری</string>
<string name="battery_optimization_why_disable">چرا بهینه‌سازی باتری را غیرفعال کنیم؟</string>
<string name="battery_optimization_explanation">bitchat برای حفظ اتصال مِش با دستگاه‌های نزدیک در پس‌زمینه اجرا می‌شود. بهینه‌سازی باتری می‌تواند این اتصال‌ها را قطع کند و باعث تأخیر یا از دست رفتن پیام‌ها شود.\n\nغیرفعال‌کردن بهینه‌سازی باتری، ارتباط همتابه‌همتای قابل اعتماد را تضمین می‌کند.</string>
<string name="battery_optimization_disable_button">غیرفعال‌کردن بهینه‌سازی باتری</string>
<string name="battery_optimization_note">توجه: می‌توانید بعداً در تنظیمات اندروید &gt; برنامه‌ها &gt; bitchat &gt; باتری این مورد را تغییر دهید.</string>
<string name="battery_optimization_not_supported_explanation">دستگاه شما به تنظیمات بهینه‌سازی باتری نیاز ندارد. bitchat به‌صورت عادی اجرا می‌شود.</string>
<string name="battery_optimization_not_supported_message">دستگاه شما به تنظیمات بهینه‌سازی باتری نیاز ندارد. bitchat به‌صورت عادی اجرا می‌شود.</string>
<string name="battery_optimization_success_message">bitchat می‌تواند با اطمینان در پس‌زمینه اجرا شود</string>
<string name="battery_optimization_benefits">• تحویل مطمئن پیام‌ها\n• حفظ اتصال مِش\n• رلهٔ پیام در پس‌زمینه\n• جلوگیری از قطع اتصال</string>
<string name="battery_optimization_check_again">بررسی مجدد</string>
<string name="battery_optimization_skip">فعلاً رد کردن</string>
<string name="battery_optimization_continue">ادامه</string>
<string name="retry">تلاش دوباره</string>
<string name="skip">رد کردن</string>
<!-- اعلان‌ها -->
<string name="notification_summary_more">و %1$d مورد دیگر</string>
<string name="notification_messages_from_people">%1$d پیام از %2$d نفر</string>
<string name="notification_more_conversations">و %1$d گفت‌وگوی دیگر</string>
<string name="notification_active_peers_title">👥 کاربران bitchat در نزدیکی!</string>
<string name="notification_active_peers_one">۱ نفر در نزدیکی</string>
<string name="notification_active_peers_many">%1$d نفر در نزدیکی</string>
<string name="notification_new_messages">پیام‌های جدید</string>
<string name="notification_new_location_messages">پیام‌های مکانی جدید</string>
<string name="notification_mentions_in">ذکر شده در %1$s</string>
<string name="notification_mentions_in_more">ذکر شده در %1$s (+%2$d مورد دیگر)</string>
<string name="notification_mentions_in_plural">%1$d مورد ذکر در %2$s</string>
<string name="notification_new_activity_in">فعالیت جدید در %1$s</string>
<string name="notification_messages_in">پیام‌ها در %1$s</string>
<string name="notification_joined_conversation">%1$s به گفت‌وگو پیوست</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d مورد ذکر</string>
<string name="notification_geohash_summary_title">bitchat – گفت‌وگوی مکانی</string>
<string name="notification_geohash_summary_text">%1$d پیام از %2$d موقعیت</string>
<string name="notification_mesh_mention_title_singular">ذکر در گفت‌وگوی مِش</string>
<string name="notification_mesh_mention_title_plural">%1$d مورد ذکر در گفت‌وگوی مِش</string>
<string name="notification_more_locations">و %1$d موقعیت دیگر</string>
<string name="notification_and_more">و %1$d مورد دیگر</string>
<!-- دسترسی‌پذیری موارد دلخواه -->
<string name="cd_add_favorite">افزودن به موارد دلخواه</string>
<string name="cd_remove_favorite">حذف از موارد دلخواه</string>
<string name="cd_add_bookmark">افزودن نشانک</string>
<!-- سربرگ چت و دسترسی‌پذیری -->
<string name="chat_back">بازگشت</string>
<string name="chat_channel_prefix">کانال: %1$s</string>
<string name="chat_leave">خروج</string>
<string name="cd_nostr_reachable">قابل دسترس از طریق Nostr</string>
<string name="cd_unread_private_messages">پیام‌های خصوصی خوانده‌نشده</string>
<string name="cd_toggle_bookmark">تغییر وضعیت نشانک</string>
<string name="cd_teleported">انتقال مکانی</string>
<string name="cd_tor_status">وضعیت Tor</string>
<string name="cd_connected_peers">همتایان متصل</string>
<string name="cd_geohash_participants">شرکت‌کنندگان geohash</string>
<string name="cd_ready_for_handshake">آمادهٔ دست‌دهی</string>
<string name="cd_handshake_in_progress">دست‌دهی در حال انجام</string>
<string name="cd_encrypted">رمزگذاری سرتاسری</string>
<string name="cd_handshake_failed">دست‌دهی ناموفق بود</string>
<!-- گفت‌وگوگر نمایش فایل -->
<string name="file_viewer_title">📎 فایل دریافت شد</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 اندازه: %1$s</string>
<string name="file_viewer_type">🏷️ نوع: %1$s</string>
<string name="file_viewer_open_save">📂 باز کردن / ذخیره</string>
<string name="close_with_emoji">❌ بستن</string>
<string name="pick_image">انتخاب تصویر</string>
<!-- برگهٔ درباره -->
<string name="about_tagline">گفت‌وگوی مِش غیرمتمرکز با رمزگذاری سرتاسری</string>
<string name="about_offline_mesh_title">گفت‌وگوی مِش آفلاین</string>
<string name="about_offline_mesh_desc">بدون اینترنت یا سرور، مستقیماً از طریق Bluetooth LE ارتباط برقرار کنید. پیام‌ها از طریق دستگاه‌های نزدیک رله می‌شوند تا بُرد افزایش یابد.</string>
<string name="about_online_geohash_title">کانال‌های geohash آنلاین</string>
<string name="about_online_geohash_desc">از طریق کانال‌های مبتنی بر geohash با افراد منطقهٔ خود ارتباط برقرار کنید. مِش را از طریق رله‌های عمومی اینترنت گسترش دهید.</string>
<string name="about_e2e_title">رمزگذاری سرتاسری</string>
<string name="about_e2e_desc">پیام‌های خصوصی رمزگذاری می‌شوند. پیام‌های کانال عمومی هستند.</string>
<string name="about_appearance">نما</string>
<string name="about_system">سامانه</string>
<string name="about_light">روشن</string>
<string name="about_dark">تیره</string>
<string name="about_pow">گواه کار (Proof of Work)</string>
<string name="about_pow_off">PoW خاموش</string>
<string name="about_pow_on">PoW روشن</string>
<string name="about_pow_tip">برای دشوارتر کردن هرزنامه، به پیام‌های geohash گواه کار بیفزایید.</string>
<string name="about_pow_difficulty">سختی: %1$d بیت (~%2$s)</string>
<string name="about_pow_difficulty_attempts">سختی %1$d به ~%2$s کوشش هش نیاز دارد</string>
<string name="about_pow_desc_none">نیازی به گواه کار نیست</string>
<string name="about_pow_desc_very_low">بسیار کم – کمینهٔ حفاظت در برابر هرزنامه</string>
<string name="about_pow_desc_low">کم – حفاظت پایه در برابر هرزنامه</string>
<string name="about_pow_desc_medium">متوسط حفاظت خوب</string>
<string name="about_pow_desc_high">زیاد حفاظت قوی</string>
<string name="about_pow_desc_very_high">بسیار زیاد – ممکن است تأخیر ایجاد کند</string>
<string name="about_pow_desc_extreme">فوق‌العاده – به توان محاسباتی قابل توجه نیاز دارد</string>
<string name="about_network">شبکه</string>
<string name="about_tor_off">Tor خاموش</string>
<string name="about_tor_on">Tor روشن</string>
<string name="about_tor_route">برای حفظ بیشتر حریم خصوصی، ترافیک اینترنت را از طریق Tor مسیریابی کنید.</string>
<string name="about_tor_status">وضعیت Tor: %1$s، بوت‌استرپ %2$d%%</string>
<string name="about_last">آخرین: %1$s</string>
<string name="about_emergency_title">پاکسازی اضطراری داده</string>
<string name="about_emergency_tip">نکته: برای پاک کردن همهٔ داده‌های ذخیره‌شده — شامل پیام‌ها، کلیدها و تنظیمات — سه بار روی عنوان برنامه ضربه بزنید.</string>
<string name="about_debug_settings">تنظیمات اشکال‌زدایی</string>
<string name="about_footer">متن‌باز • حریم خصوصی در اولویت • غیرمتمرکز</string>
<string name="close_plain">بستن</string>
<string name="cancel_lower">لغو</string>
<!-- توضیحات عمومی محتوا -->
<string name="cd_warning">هشدار</string>
<string name="cd_location_services">خدمات مکان</string>
<string name="cd_privacy">حریم خصوصی</string>
<string name="cd_error">خطا</string>
<string name="cd_battery_optimization">بهینه‌سازی باتری</string>
<string name="cd_benefits">مزایا</string>
<string name="cd_checking_battery_optimization">در حال بررسی بهینه‌سازی باتری</string>
<string name="cd_not_supported_battery_optimization">بهینه‌سازی باتری پشتیبانی نمی‌شود</string>
<string name="cd_bluetooth">بلوتوث</string>
<string name="cd_unread_message">پیام خوانده‌نشده</string>
<string name="cd_open_map">باز کردن نقشه</string>
<string name="cd_remove_bookmark">حذف نشانک</string>
<string name="cd_teleport">انتقال</string>
<string name="cd_selected">انتخاب شد</string>
<string name="cd_leave_channel">خروج از کانال</string>
<string name="cd_reachable_via_nostr">قابل دسترس از طریق Nostr</string>
<string name="cd_offline_favorite">دلخواه (آفلاین)</string>
<string name="cd_decrease_precision">کاهش دقت</string>
<string name="cd_increase_precision">افزایش دقت</string>
<string name="cd_select_geohash">انتخاب geohash</string>
<string name="cd_scroll_to_bottom">اسکرول به پایین</string>
<string name="cd_file">فایل</string>
<string name="cd_image">تصویر</string>
<string name="cd_cancel">لغو</string>
<string name="cd_link">پیوند</string>
<string name="cd_pick_media">انتخاب رسانه</string>
<string name="cd_pick_file">انتخاب فایل</string>
<string name="cd_save_current_image">ذخیرهٔ تصویر فعلی</string>
<string name="cd_close">بستن</string>
<string name="cd_image_index_of">تصویر %1$d از %2$d</string>
<string name="cd_privacy_protected">حریم خصوصی محافظت شده است</string>
<string name="cd_record_voice">ضبط پیام صوتی</string>
<string name="cd_offline_mesh_chat">گفت‌وگوی مِش آفلاین</string>
<string name="cd_online_geohash_channels">کانال‌های geohash آنلاین</string>
<string name="cd_end_to_end_encryption">رمزگذاری سرتاسری</string>
<!-- تصاویر و فایل‌ها -->
<string name="image_page_of">تصویر %1$d از %2$d</string>
<string name="image_unavailable">تصویر در دسترس نیست</string>
<string name="image_saved_to_downloads">تصویر در \"Downloads\" ذخیره شد</string>
<string name="image_save_failed">ذخیرهٔ تصویر ناموفق بود</string>
<string name="toast_image_saved">تصویر در \"Downloads\" ذخیره شد</string>
<string name="toast_failed_to_save_image">ذخیرهٔ تصویر ناموفق بود</string>
<string name="pick_file">انتخاب فایل</string>
<string name="file_unavailable">[فایل در دسترس نیست]</string>
<string name="unknown">نامشخص</string>
<!-- برگهٔ اقدامات کاربر -->
<string name="choose_action_message_or_user">اقدامی برای این پیام یا کاربر انتخاب کنید</string>
<string name="choose_action_user">اقدامی برای این کاربر انتخاب کنید</string>
<string name="action_copy_message_title">کپی پیام</string>
<string name="action_copy_message_subtitle">این پیام را در کلیپ‌بورد کپی کن</string>
<string name="action_slap_title">%1$s را سیلی بزن</string>
<string name="action_slap_subtitle">یک سیلی شوخی ارسال کن</string>
<string name="action_hug_title">%1$s را بغل کن</string>
<string name="action_hug_subtitle">یک بغل دوستانه ارسال کن</string>
<string name="action_block_title">%1$s را مسدود کن</string>
<string name="action_block_subtitle">همهٔ پیام‌های این کاربر را مسدود کن</string>
<!-- برگهٔ کانال‌های geohash -->
<string name="location_channels_title">#کانال‌های مکانی</string>
<string name="location_channels_desc">از طریق کانال‌های geohash با افراد نزدیک خود چت کنید. فقط geohash کلی به اشتراک گذاشته می‌شود، نه دادهٔ GPS دقیق. برای حفظ حریم خصوصی، لطفاً از این نما اسکرین‌شات نگیرید یا آن را به اشتراک نگذارید.</string>
<string name="grant_location_permission">اعطای مجوز مکان</string>
<string name="location_permission_denied">مجوز مکان رد شد. برای استفاده از کانال‌های مکانی، آن را در تنظیمات فعال کنید.</string>
<string name="open_settings">باز کردن تنظیمات</string>
<string name="location_permission_granted">\u2713 مجوز مکان اعطا شد</string>
<string name="checking_permissions">در حال بررسی مجوزها …</string>
<string name="finding_nearby_channels">در حال یافتن کانال‌های نزدیک …</string>
<string name="bookmarked">نشانک شده</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">geohash نامعتبر است</string>
<string name="teleport">انتقال مکانی</string>
<string name="disable_location_services">غیرفعال‌کردن خدمات مکان</string>
<string name="enable_location_services">فعال‌کردن خدمات مکان</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">بلوک</string>
<string name="location_level_neighborhood">محله</string>
<string name="location_level_city">شهر</string>
<string name="location_level_province">استان</string>
<string name="location_level_region">منطقه</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- اشکال‌زدایی / عیب‌یابی -->
<string name="debug_tools">ابزارهای اشکال‌زدایی</string>
<string name="debug_tools_desc">ابزارهای توسعه‌دهنده برای عیب‌یابی و کنترل</string>
<string name="debug_verbose_logging">گزارش‌گیری مفصل</string>
<string name="debug_verbose_hint">پیوستن/ترک همتا، جهت اتصال، رلهٔ بسته‌ها و مسیرها را ثبت می‌کند</string>
<string name="debug_bluetooth_roles">نقش‌های بلوتوث</string>
<string name="debug_gatt_server">سرور GATT</string>
<string name="debug_connections_fmt">اتصال‌ها: %1$d / %2$d</string>
<string name="debug_max_server">حداکثر سرور</string>
<string name="debug_gatt_client">کلاینت GATT</string>
<string name="debug_max_client">حداکثر کلاینت</string>
<string name="debug_overall_connections_fmt">اتصال‌ها: %1$d / %2$d</string>
<string name="debug_max_overall">حداکثر کل</string>
<string name="debug_packet_relay">رلهٔ بسته</string>
<string name="debug_since_start_fmt">از شروع: %1$d</string>
<string name="debug_roles_hint">روشن/خاموش‌کردن نقش‌ها و بستن همهٔ اتصال‌ها هنگام غیرفعالسازی</string>
<string name="debug_sync_settings">تنظیمات همگام‌سازی</string>
<string name="debug_max_packets_per_sync_fmt">حداکثر بسته در هر همگام‌سازی: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">حداکثر اندازهٔ فیلتر GCS: %1$d بایت (1281024)</string>
<string name="debug_target_fpr_fmt">FPR هدف: %1$.2f%%</string>
<string name="debug_connected_devices">دستگاه‌های متصل</string>
<string name="debug_our_device_id_fmt">شناسهٔ دستگاه ما: %1$s</string>
<string name="debug_none">هیچ</string>
<string name="debug_disconnect">قطع اتصال</string>
<string name="debug_recent_scan_results">دستگاه‌های اخیراً اسکن‌شده</string>
<string name="debug_connect">اتصال</string>
<string name="debug_debug_console">کنسول اشکال‌زدایی</string>
<string name="debug_clear">پاک‌کردن</string>
<string name="debug_relays_window_fmt">۱۰ث اخیر: %1$d • ۱د: %2$d • ۱۵د: %3$d</string>
<string name="debug_derived_p_fmt">P مشتق: %1$s • عناصر حداکثر تخمینی: %2$s</string>
<string name="debug_direct_suffix"> • مستقیم</string>
<string name="debug_role_server">به عنوان سرور (ما میزبانیم)</string>
<string name="debug_role_client">به عنوان کلاینت (ما متصل می‌شویم)</string>
<!-- صفحه‌های آغازین -->
<string name="location_services_required">خدمات مکان لازم است</string>
<string name="privacy_first">حریم خصوصی در اولویت</string>
<string name="location_explanation">bitchat موقعیت شما را پیگیری نمی‌کند.\n\nبرای اسکن بلوتوث و قابلیت گفت‌وگوی geohash، خدمات مکان لازم است.</string>
<string name="location_needs_for">bitchat به خدمات مکان برای موارد زیر نیاز دارد:</string>
<string name="location_needs_bullets">• اسکن دستگاه‌های بلوتوث\n• یافتن کاربران نزدیک در شبکهٔ مِش\n• قابلیت گفت‌وگوی geohash\n• بدون پیگیری یا جمع‌آوری موقعیت</string>
<string name="open_location_settings">باز کردن تنظیمات مکان</string>
<string name="check_again">بررسی دوباره</string>
<string name="location_services_unavailable">خدمات مکان در دسترس نیست</string>
<string name="location_unavailable_explanation">خدمات مکان در این دستگاه در دسترس نیست. این غیرمعمول است زیرا خدمات مکان در دستگاه‌های اندرویدی استاندارد است.\n\nبرای عملکرد صحیح اسکن بلوتوث (الزام اندروید) bitchat به خدمات مکان نیاز دارد. بدون آن، برنامه نمی‌تواند کاربران نزدیک را بیابد.</string>
<string name="checking_location_services">در حال بررسی خدمات مکان …</string>
<string name="bluetooth_required">بلوتوث لازم است</string>
<string name="bluetooth_needs_for">bitchat به بلوتوث برای موارد زیر نیاز دارد:</string>
<string name="bluetooth_needs_bullets">• یافتن کاربران نزدیک\n• ایجاد اتصال‌های شبکهٔ مِش\n• ارسال و دریافت پیام‌ها\n• کار بدون اینترنت یا سرور</string>
<string name="enable_bluetooth">فعال‌کردن بلوتوث</string>
<string name="bluetooth_not_supported">بلوتوث پشتیبانی نمی‌شود</string>
<string name="bluetooth_unsupported_explanation">این دستگاه از Bluetooth Low Energy (BLE) که برای کارکرد bitchat لازم است پشتیبانی نمی‌کند.\n\nbitchat برای ایجاد شبکهٔ مِش و ارتباط با دستگاه‌های نزدیک بدون اینترنت به BLE نیاز دارد.</string>
<string name="checking_bluetooth_status">در حال بررسی وضعیت بلوتوث …</string>
<string name="battery_optimization_detected_title">بهینه‌سازی باتری شناسایی شد</string>
<string name="battery_optimization_enabled_title">بهینه‌سازی باتری فعال است</string>
<string name="battery_optimization_explanation_short">برای حفظ اتصال مِش، bitchat باید در پس‌زمینه اجرا شود. بهینه‌سازی باتری می‌تواند این اتصال‌ها را مختل کند.</string>
<string name="benefits_of_disabling">مزایای غیرفعالسازی</string>
<string name="battery_benefits_short">• تحویل مطمئن پیام‌ها\n• حفظ اتصال مِش\n• جلوگیری از قطع اتصال</string>
<string name="disable_battery_optimization">غیرفعال‌کردن بهینه‌سازی باتری</string>
<string name="battery_optimization_disabled_title">بهینه‌سازی باتری غیرفعال شد</string>
<string name="continue_btn">ادامه</string>
<string name="initializing_mesh_network">در حال راه‌اندازی شبکهٔ مِش</string>
<string name="setting_up_bluetooth">در حال تنظیم شبکهٔ مِش بلوتوث …</string>
<string name="should_take_seconds">این کار فقط چند ثانیه طول می‌کشد</string>
<string name="setup_not_complete">راه‌اندازی کامل نشد</string>
<string name="try_again">تلاش دوباره</string>
<string name="privacy_protected">حریم خصوصی شما محافظت می‌شود</string>
<string name="privacy_bullets">• بدون پیگیری یا جمع‌آوری داده\n• گفت‌وگوی مِش بلوتوث کاملاً آفلاین است\n• گفت‌وگوی geohash از اینترنت استفاده می‌کند</string>
<string name="permissions_header">مجوزها</string>
<string name="grant_permissions">اعطای مجوزها</string>
<string name="location_tracking_warning">bitchat موقعیت شما را پیگیری نمی‌کند</string>
<string name="geohash_people_header">افراد</string>
<string name="nobody_around">کسی در اطراف نیست …</string>
<string name="you_suffix"> (شما)</string>
<string name="pan_zoom_instruction">برای انتخاب geohash، جابه‌جا و زوم کنید</string>
<string name="select">انتخاب</string>
<string name="type_a_message_placeholder">نوشتن پیام …</string>
<string name="mention">ذکر</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">تصویر</string>
<string name="media_type_file">فایل</string>
<!-- راهنمای متن اعلان -->
<string name="notification_sent_image">📷 یک تصویر ارسال کرد</string>
<string name="notification_sent_voice">🎤 یک پیام صوتی ارسال کرد</string>
<string name="notification_sent_file">📎 یک فایل ارسال کرد</string>
<!-- دسترسی‌پذیری پخش‌کنندهٔ صوت -->
<string name="cd_play_voice">پخش</string>
<string name="cd_pause_voice">توقف</string>
<string name="cd_mining_pow">استخراج PoW</string>
<string name="cd_pow_enabled">PoW فعال است</string>
<string name="cd_proof_of_work">گواه کار</string>
<string name="pow_mining_ellipsis">در حال استخراج …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- توضیحات مجوز -->
<string name="perm_nearby_devices_desc">برای یافتن کاربران bitchat از طریق بلوتوث لازم است</string>
<string name="perm_nearby_devices_system">به bitchat اجازه دهید با دستگاه‌های نزدیک متصل شود</string>
<string name="perm_location_desc">برای یافتن کاربران نزدیک bitchat از طریق بلوتوث به‌وسیلهٔ اندروید لازم است</string>
<string name="perm_location_system">bitchat برای اسکن دستگاه‌های نزدیک به این مورد نیاز دارد</string>
<string name="perm_notifications_desc">هنگام دریافت پیام خصوصی اعلان دریافت کنید</string>
<string name="perm_notifications_system">به bitchat اجازه دهید برای شما اعلان ارسال کند</string>
<string name="perm_battery_desc">بهینه‌سازی باتری را غیرفعال کنید تا اطمینان حاصل شود bitchat به‌طور قابل اعتماد در پس‌زمینه اجرا شده و اتصال‌های شبکهٔ مِش را حفظ می‌کند</string>
<string name="perm_battery_system">به bitchat اجازه دهید بدون محدودیت باتری اجرا شود</string>
<!-- گونه‌های مجوز -->
<string name="perm_type_nearby_devices">دستگاه‌های نزدیک</string>
<string name="perm_type_precise_location">مکان دقیق</string>
<string name="perm_type_microphone">میکروفون</string>
<string name="perm_type_notifications">اعلان‌ها</string>
<string name="perm_type_battery_optimization">بهینه‌سازی باتری</string>
<string name="perm_type_other">سایر</string>
<!-- گفت‌وگوی گذرواژه -->
<string name="pwd_prompt_title">گذرواژهٔ کانال را وارد کنید</string>
<string name="pwd_prompt_message">کانال %1$s با گذرواژه محافظت می‌شود. برای پیوستن، گذرواژه را وارد کنید.</string>
<string name="pwd_label">گذرواژه</string>
<string name="join">پیوستن</string>
<string name="cancel">لغو</string>
<!-- حالت جمع -->
<plurals name="notification_and_more">
<item quantity="one">و %d مورد دیگر</item>
<item quantity="other">و %d مورد دیگر</item>
</plurals>
<plurals name="people_count">
<item quantity="one">۱ نفر</item>
<item quantity="other">%d نفر</item>
</plurals>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Mga dahilan ng permiso -->
<string name="permission_bluetooth_rationale">Kailangan ang permiso sa Bluetooth para sa direktang pagusap kahit walang internet.</string>
<string name="permission_location_rationale">Kailangan ang permiso sa Lokasyon para mahanap ang mga kalapit na device gamit ang Bluetooth.</string>
<string name="permission_notification_rationale">Kailangan ang permiso sa Abiso para ipaalam ang mga bagong mensahe.</string>
<!-- Mga placeholder / batayang UI -->
<string name="nickname_hint">palayaw</string>
<string name="message_hint">magtype ng mensahe…</string>
<string name="channel_password_hint">Password</string>
<string name="join_channel">Sumali sa Channel</string>
<string name="leave_channel">Umalis</string>
<string name="send_message">Ipadala</string>
<string name="show_commands">Ipakita ang mga utos</string>
<string name="back">Bumalik</string>
<string name="people">Tao</string>
<string name="channels">Mga Channel</string>
<string name="online_users">Mga Online na User</string>
<string name="no_one_connected">Walang nakakonekta</string>
<string name="emergency_clear_hint">Itap nang tatlong beses para burahin ang lahat ng data</string>
<string name="your_network">Network</string>
<!-- Pagoptimize ng baterya -->
<string name="battery_optimization_detected">Natukoy ang pagoptimize ng baterya</string>
<string name="battery_optimization_disabled">Nakadisable ang pagoptimize ng baterya</string>
<string name="battery_optimization_not_required">Hindi kailangan ang pagoptimize ng baterya</string>
<string name="battery_optimization_checking">Sinusuri ang pagoptimize ng baterya</string>
<string name="battery_optimization_why_disable">Bakit idisable ang pagoptimize?</string>
<string name="battery_optimization_explanation">Tumatakbo ang bitchat sa background upang mapanatili ang mesh na koneksyon sa mga kalapit na device. Maaaring maputol ito ng pagoptimize ng baterya na nagdudulot ng pagkaantala o pagkawala ng mensahe.\n\nAng pagdisable nito ay tinitiyak ang maaasahang peertopeer na pagmemensahe.</string>
<string name="battery_optimization_disable_button">Idisable ang pagoptimize</string>
<string name="battery_optimization_note">Tandaan: Maaari itong baguhin sa Android Settings &gt; Apps &gt; bitchat &gt; Battery</string>
<string name="battery_optimization_not_supported_explanation">Hindi kailangan ng iyong device ng mga setting ng pagoptimize ng baterya. Normal na gagana ang bitchat.</string>
<string name="battery_optimization_not_supported_message">Hindi kailangan ng iyong device ng mga setting ng pagoptimize ng baterya. Normal na gagana ang bitchat.</string>
<string name="battery_optimization_success_message">Maaasahang tatakbo ang bitchat sa background</string>
<string name="battery_optimization_benefits">• Maaasahang paghatid ng mensahe\n• Pinananatili ang mesh na koneksyon\n• Background relay ng mensahe\n• Iwas putol ng koneksyon</string>
<string name="battery_optimization_check_again">Suriin muli</string>
<string name="battery_optimization_skip">Laktawan muna</string>
<string name="battery_optimization_continue">Magpatuloy</string>
<string name="retry">Subukang muli</string>
<string name="skip">Laktawan</string>
<!-- Mga Abiso -->
<string name="notification_summary_more">at %1$d pa</string>
<string name="notification_messages_from_people">%1$d mensahe mula sa %2$d tao</string>
<string name="notification_more_conversations">at %1$d pang usapan</string>
<string name="notification_active_peers_title">👥 mga bitchatter na malapit!</string>
<string name="notification_active_peers_one">1 tao sa paligid</string>
<string name="notification_active_peers_many">%1$d tao sa paligid</string>
<string name="notification_new_messages">Mga bagong mensahe</string>
<string name="notification_new_location_messages">Mga mensahe sa lokasyon</string>
<string name="notification_mentions_in">Nabanggit sa %1$s</string>
<string name="notification_mentions_in_more">Nabanggit sa %1$s (+%2$d pa)</string>
<string name="notification_mentions_in_plural">%1$d banggit sa %2$s</string>
<string name="notification_new_activity_in">Bagong aktibidad sa %1$s</string>
<string name="notification_messages_in">Mga mensahe sa %1$s</string>
<string name="notification_joined_conversation">Sumali si %1$s sa usapan</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d banggit</string>
<string name="notification_geohash_summary_title">bitchat mga chat sa lokasyon</string>
<string name="notification_geohash_summary_text">%1$d mensahe mula sa %2$d lokasyon</string>
<string name="notification_mesh_mention_title_singular">Nabanggit sa Mesh Chat</string>
<string name="notification_mesh_mention_title_plural">%1$d banggit sa Mesh Chat</string>
<string name="notification_more_locations">at %1$d pang lokasyon</string>
<string name="notification_and_more">at %1$d pa</string>
<!-- Paborito / Accessibility -->
<string name="cd_add_favorite">Idagdag sa paborito</string>
<string name="cd_remove_favorite">Alisin sa paborito</string>
<string name="cd_add_bookmark">Magbookmark</string>
<!-- Header at accessibility -->
<string name="chat_back">bumalik</string>
<string name="chat_channel_prefix">channel: %1$s</string>
<string name="chat_leave">umalis</string>
<string name="cd_nostr_reachable">Maabot sa Nostr</string>
<string name="cd_unread_private_messages">Hindi nabasang pribadong mensahe</string>
<string name="cd_toggle_bookmark">Itoggle ang bookmark</string>
<string name="cd_teleported">Naiteleport</string>
<string name="cd_tor_status">Katayuan ng Tor</string>
<string name="cd_connected_peers">Nakakonektang peers</string>
<string name="cd_geohash_participants">Mga kalahok sa geohash</string>
<string name="cd_ready_for_handshake">Handa para sa handshake</string>
<string name="cd_handshake_in_progress">Isinasagawa ang handshake</string>
<string name="cd_encrypted">Endtoend nakaencrypt</string>
<string name="cd_handshake_failed">Bigo ang handshake</string>
<!-- Dialog ng file -->
<string name="file_viewer_title">📎 Nakakuha ng file</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Laki: %1$s</string>
<string name="file_viewer_type">🏷️ Uri: %1$s</string>
<string name="file_viewer_open_save">📂 Buksan / Isave</string>
<string name="close_with_emoji">❌ Isara</string>
<string name="pick_image">Pumili ng larawan</string>
<!-- About sheet -->
<string name="about_tagline">desentralisadong mesh messaging na may endtoend encryption</string>
<string name="about_offline_mesh_title">Offline Mesh Chat</string>
<string name="about_offline_mesh_desc">Makipagusap direkta sa Bluetooth LE nang walang internet o server. Ang mga mensahe ay nirerelay ng mga kalapit na device.</string>
<string name="about_online_geohash_title">Online na Geohash na mga Channel</string>
<string name="about_online_geohash_desc">Makipagugnayan sa mga tao sa paligid gamit ang geohashbased na mga channel. Palawakin ang mesh sa pampublikong internet relays.</string>
<string name="about_e2e_title">EndtoEnd Encryption</string>
<string name="about_e2e_desc">Ang mga pribadong mensahe ay nakaencrypt. Ang mga mensahe sa channel ay publiko.</string>
<string name="about_appearance">hitsura</string>
<string name="about_system">system</string>
<string name="about_light">light</string>
<string name="about_dark">dark</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">pow off</string>
<string name="about_pow_on">pow on</string>
<string name="about_pow_tip">magdagdag ng proof of work sa mga geohash na mensahe para iwas spam.</string>
<string name="about_pow_difficulty">hirap: %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">ang hirap na %1$d ay ~%2$s hash attempts</string>
<string name="about_pow_desc_none">walang proof of work na kailangan</string>
<string name="about_pow_desc_very_low">napakababa minimal na proteksyon</string>
<string name="about_pow_desc_low">mababa batayang proteksyon</string>
<string name="about_pow_desc_medium">katamtaman magandang proteksyon</string>
<string name="about_pow_desc_high">mataas matibay na proteksyon</string>
<string name="about_pow_desc_very_high">napakataas posibleng may pagkaantala</string>
<string name="about_pow_desc_extreme">matindi malaking komputasyon ang kailangan</string>
<string name="about_network">network</string>
<string name="about_tor_off">tor off</string>
<string name="about_tor_on">tor on</string>
<string name="about_tor_route">iruta ang internet sa Tor para sa mas mataas na privacy.</string>
<string name="about_tor_status">katayuan ng Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Huli: %1$s</string>
<string name="about_emergency_title">Emergency Data Deletion</string>
<string name="about_emergency_tip">Tip: itap ang pamagat ng app nang 3 beses para burahin ang lahat ng data (mga mensahe, susi, setting).</string>
<string name="about_debug_settings">Debug Settings</string>
<string name="about_footer">Open Source • Privacy First • Desentralisado</string>
<string name="close_plain">Isara</string>
<string name="cancel_lower">kanselahin</string>
<!-- Generic CD -->
<string name="cd_warning">Babala</string>
<string name="cd_location_services">Mga serbisyo sa lokasyon</string>
<string name="cd_privacy">Privacy</string>
<string name="cd_error">Error</string>
<string name="cd_battery_optimization">Pagoptimize ng baterya</string>
<string name="cd_benefits">Mga benepisyo</string>
<string name="cd_checking_battery_optimization">Sinusuri ang pagoptimize</string>
<string name="cd_not_supported_battery_optimization">Hindi suportado</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Hindi nabasang mensahe</string>
<string name="cd_open_map">Buksan ang mapa</string>
<string name="cd_remove_bookmark">Alisin ang bookmark</string>
<string name="cd_teleport">Teleport</string>
<string name="cd_selected">Napili</string>
<string name="cd_leave_channel">Umalis sa channel</string>
<string name="cd_reachable_via_nostr">Maabot sa Nostr</string>
<string name="cd_offline_favorite">Paborito (offline)</string>
<string name="cd_decrease_precision">Bawasan ang precision</string>
<string name="cd_increase_precision">Dagdagan ang precision</string>
<string name="cd_select_geohash">Piliin ang geohash</string>
<string name="cd_scroll_to_bottom">Magscroll pababa</string>
<string name="cd_file">File</string>
<string name="cd_image">Larawan</string>
<string name="cd_cancel">Kanselahin</string>
<string name="cd_link">Link</string>
<string name="cd_pick_media">Pumili ng media</string>
<string name="cd_record_voice">Magrecord ng voice note</string>
<string name="cd_offline_mesh_chat">Offline Mesh Chat</string>
<string name="cd_online_geohash_channels">Online na Geohash Channels</string>
<string name="cd_end_to_end_encryption">EndtoEnd Encryption</string>
<!-- Larawan / File -->
<string name="image_page_of">Larawan %1$d ng %2$d</string>
<string name="image_unavailable">Hindi available ang larawan</string>
<string name="image_saved_to_downloads">Nasave ang larawan sa "Downloads"</string>
<string name="image_save_failed">Nabigo ang pagsave ng larawan</string>
<string name="pick_file">Pumili ng file</string>
<string name="file_unavailable">[hindi available ang file]</string>
<string name="unknown">hindi kilala</string>
<!-- User action sheet -->
<string name="choose_action_message_or_user">pumili ng aksyon para sa mensaheng ito o user</string>
<string name="choose_action_user">pumili ng aksyon para sa user na ito</string>
<string name="action_copy_message_title">kopyahin ang mensahe</string>
<string name="action_copy_message_subtitle">kopyahin ang mensaheng ito sa clipboard</string>
<string name="action_slap_title">sapakin si %1$s</string>
<string name="action_slap_subtitle">magpadala ng birong sampal</string>
<string name="action_hug_title">yakapin si %1$s</string>
<string name="action_hug_subtitle">magpadala ng magiliw na yakap</string>
<string name="action_block_title">harangan si %1$s</string>
<string name="action_block_subtitle">harangan ang lahat ng mensahe mula sa user na ito</string>
<!-- Location channels sheet -->
<string name="location_channels_title">#mga channel sa lokasyon</string>
<string name="location_channels_desc">makipagusap sa mga tao sa paligid gamit ang mga geohash na channel. tanging malabong geohash ang ibinabahagi, hindi eksaktong gps. huwag magscreenshot o ibahagi ang screen na ito para sa privacy.</string>
<string name="grant_location_permission">payagan ang lokasyon</string>
<string name="location_permission_denied">tinanggihan ang permiso sa lokasyon. ienable sa settings para magamit ang mga channel sa lokasyon.</string>
<string name="open_settings">Buksan ang Settings</string>
<string name="location_permission_granted">\u2713 pinayagan ang lokasyon</string>
<string name="checking_permissions">sinisiyasat ang mga permiso…</string>
<string name="finding_nearby_channels">naghahanap ng kalapit na channel…</string>
<string name="bookmarked">nabookmark</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">maling geohash</string>
<string name="teleport">teleport</string>
<string name="disable_location_services">idisable ang location services</string>
<string name="enable_location_services">ienable ang location services</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">bloke</string>
<string name="location_level_neighborhood">barangay</string>
<string name="location_level_city">lungsod</string>
<string name="location_level_province">probinsya</string>
<string name="location_level_region">rehiyon</string>
<!-- Debug / Diagnostics -->
<string name="debug_tools">mga kasangkapan sa debug</string>
<string name="debug_verbose_logging">masalitang paglog</string>
<string name="debug_bluetooth_roles">mga tungkulin sa Bluetooth</string>
<string name="debug_gatt_server">GATT server</string>
<string name="debug_connections_fmt">mga koneksyon: %1$d / %2$d</string>
<string name="debug_max_server">max server</string>
<string name="debug_gatt_client">GATT client</string>
<string name="debug_max_client">max client</string>
<string name="debug_overall_connections_fmt">mga koneksyon: %1$d / %2$d</string>
<string name="debug_max_overall">max kabuuan</string>
<string name="debug_packet_relay">packet relay</string>
<string name="debug_since_start_fmt">mula umpisa: %1$d</string>
<string name="debug_sync_settings">mga setting ng sync</string>
<string name="debug_max_packets_per_sync_fmt">max packet bawat sync: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">max laki ng GCS filter: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">target FPR: %1$.2f%%</string>
<string name="debug_connected_devices">mga nakakonektang device</string>
<string name="debug_our_device_id_fmt">ID ng aming device: %1$s</string>
<string name="debug_none">wala</string>
<string name="debug_disconnect">idisconnect</string>
<string name="debug_recent_scan_results">mga huling resulta ng scan</string>
<string name="debug_connect">kumonekta</string>
<string name="debug_debug_console">debug console</string>
<string name="debug_clear">limasin</string>
<string name="debug_relays_window_fmt">huling 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">hinangong P: %1$s • tantyang max na elemento: %2$s</string>
<string name="debug_direct_suffix"> • direkta</string>
<string name="debug_question_mark">?</string>
<string name="debug_role_server">bilang server (kami ang naghohost)</string>
<string name="debug_role_client">bilang client (kami ang kumokonekta)</string>
<!-- Onboarding screens -->
<string name="location_services_required">Kailangangkailangan ang Location Services</string>
<string name="privacy_first">Privacy muna</string>
<string name="location_explanation">HINDI sinusubaybayan ng bitchat ang iyong lokasyon.\n\nKailangan ang location services para sa Bluetooth scanning at Geohash chat.</string>
<string name="location_needs_for">Kailangan ng bitchat ang location services para sa:</string>
<string name="location_needs_bullets">• Bluetooth device scanning\n• Pagtuklas ng kalapit na user sa mesh\n• Geohash chat\n• Walang tracking o koleksiyon ng lokasyon</string>
<string name="open_location_settings">Buksan ang Location Settings</string>
<string name="check_again">Suriin muli</string>
<string name="location_services_unavailable">Hindi available ang Location Services</string>
<string name="location_unavailable_explanation">Hindi available ang location services sa device na ito. Hindi ito karaniwan dahil standard ito sa Android.\n\nKailangan ito para maayos ang Bluetooth scanning. Kung wala ito, hindi matutuklasan ang mga kalapit na user.</string>
<string name="checking_location_services">Sinusuri ang location services…</string>
<string name="bluetooth_required">Kailangan ang Bluetooth</string>
<string name="bluetooth_needs_for">Kailangan ng bitchat ang Bluetooth para sa:</string>
<string name="bluetooth_needs_bullets">• Tuklasin ang mga kalapit na user\n• Gumawa ng mesh na koneksyon\n• Magpadala at tumanggap ng mensahe\n• Gumana kahit walang internet o server</string>
<string name="enable_bluetooth">Ienable ang Bluetooth</string>
<string name="bluetooth_not_supported">Hindi suportado ang Bluetooth</string>
<string name="bluetooth_unsupported_explanation">Hindi sinusuportahan ng device na ito ang Bluetooth Low Energy (BLE) na kailangan para gumana ang bitchat.\n\nKailangan ang BLE para bumuo ng mesh at makipagugnayan sa kalapit na device kahit walang internet.</string>
<string name="checking_bluetooth_status">Sinusuri ang status ng Bluetooth…</string>
<string name="battery_optimization_detected_title">natukoy ang pagoptimize ng baterya</string>
<string name="battery_optimization_enabled_title">Nakaenable ang pagoptimize</string>
<string name="battery_optimization_explanation_short">kailangang tumakbo ang bitchat sa background para sa mesh; maaaring putulin ito ng pagoptimize.</string>
<string name="benefits_of_disabling">Mga benepisyo ng pagdisable</string>
<string name="battery_benefits_short">• maaasahang paghatid\n• panatilihin ang koneksyon\n• iwas putol</string>
<string name="disable_battery_optimization">Idisable ang pagoptimize</string>
<string name="battery_optimization_disabled_title">nadisable ang pagoptimize</string>
<string name="continue_btn">Magpatuloy</string>
<string name="initializing_mesh_network">Ineinitialize ang mesh network</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">Iseset up ang Bluetooth mesh…</string>
<string name="should_take_seconds">Ilang segundo lang ito</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">Hindi kumpleto ang setup</string>
<string name="try_again">Subukang muli</string>
<string name="privacy_protected">Protektado ang iyong privacy</string>
<string name="privacy_bullets">• walang tracking o koleksiyon\n• offline ang mesh chat sa Bluetooth\n• gumagamit ng internet ang geohash chat</string>
<string name="permissions_header">mga permiso</string>
<string name="grant_permissions">Payagan</string>
<string name="location_tracking_warning">HINDI sinusubaybayan ng bitchat ang lokasyon mo</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">TAO</string>
<string name="nobody_around">walang tao sa paligid…</string>
<string name="you_suffix"> (ikaw)</string>
<string name="pan_zoom_instruction">ipan at izoom para pumili ng geohash</string>
<string name="select">piliin</string>
<string name="type_a_message_placeholder">magtype ng mensahe…</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">banggit</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">Larawan</string>
<string name="media_type_file">File</string>
<!-- Mga status ng mensahe -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- Tulong na text sa abiso -->
<string name="notification_sent_image">📷 nagpadala ng larawan</string>
<string name="notification_sent_voice">🎤 nagpadala ng voice message</string>
<string name="notification_sent_file">📎 nagpadala ng file</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- Voice player a11y -->
<string name="cd_play_voice">Iplay</string>
<string name="cd_pause_voice">Ipause</string>
<!-- Mga paglalarawan ng permiso -->
<string name="perm_nearby_devices_desc">Kailangan upang makakita ng mga bitchat user sa Bluetooth</string>
<string name="perm_nearby_devices_system">Payagan ang bitchat na kumonekta sa kalapit na device</string>
<string name="perm_location_desc">Kailangan ng Android para sa pagtuklas ng user sa Bluetooth</string>
<string name="perm_location_system">Kailangan ito ng bitchat para magscan</string>
<string name="perm_notifications_desc">Tumanggap ng abiso sa mga pribadong mensahe</string>
<string name="perm_notifications_system">Payagan ang bitchat na magpadala ng abiso</string>
<string name="perm_battery_desc">Idisable ang pagoptimize upang tumakbo nang maaasahan at mapanatili ang mesh na koneksyon</string>
<string name="perm_battery_system">Payagan ang bitchat na tumakbo nang walang limitasyong baterya</string>
<!-- Mga uri ng permiso -->
<string name="perm_type_nearby_devices">Kalapit na device</string>
<string name="perm_type_precise_location">Eksaktong lokasyon</string>
<string name="perm_type_microphone">Mikropono</string>
<string name="perm_type_notifications">Mga abiso</string>
<string name="perm_type_battery_optimization">Pagoptimize ng baterya</string>
<string name="perm_type_other">Iba pa</string>
<!-- Dialog ng password -->
<string name="pwd_prompt_title">Ilagay ang password ng channel</string>
<string name="pwd_prompt_message">Ang channel na %1$s ay protektado. Ilagay ang password para sumali.</string>
<string name="pwd_label">Password</string>
<string name="join">Sumali</string>
<string name="cancel">Kanselahin</string>
<!-- Plurals -->
<plurals name="notification_and_more">
<item quantity="one">at %d pa</item>
<item quantity="other">at %d pa</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 tao</item>
<item quantity="other">%d tao</item>
</plurals>
</resources>
+379
View File
@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Raisons des autorisations -->
<string name="permission_bluetooth_rationale">Lautorisation Bluetooth est requise pour discuter en pair à pair sans internet.</string>
<string name="permission_location_rationale">Lautorisation de localisation est requise pour découvrir les appareils à proximité via Bluetooth.</string>
<string name="permission_notification_rationale">Lautorisation de notifications est requise pour talerter des nouveaux messages.</string>
<!-- Placeholders / UI de base -->
<string name="nickname_hint">pseudo</string>
<string name="message_hint">écrire un message…</string>
<string name="channel_password_hint">Mot de passe</string>
<string name="join_channel">Rejoindre le canal</string>
<string name="leave_channel">Quitter</string>
<string name="send_message">Envoyer</string>
<string name="show_commands">Afficher les commandes</string>
<string name="back">Retour</string>
<string name="people">Personnes</string>
<string name="channels">Canaux</string>
<string name="online_users">Utilisateurs en ligne</string>
<string name="no_one_connected">Personne connecté</string>
<string name="emergency_clear_hint">Tapoter 3 fois pour effacer toutes les données</string>
<string name="your_network">Réseau</string>
<!-- Optimisation de la batterie -->
<string name="battery_optimization_detected">Optimisation de la batterie détectée</string>
<string name="battery_optimization_disabled">Optimisation de la batterie désactivée</string>
<string name="battery_optimization_not_required">Optimisation de la batterie non requise</string>
<string name="battery_optimization_checking">Vérification de loptimisation de la batterie</string>
<string name="battery_optimization_why_disable">Pourquoi désactiver loptimisation de la batterie ?</string>
<string name="battery_optimization_explanation">bitchat sexécute en arrière-plan pour maintenir des connexions mesh avec les appareils à proximité. Loptimisation de la batterie peut interrompre ces connexions, entraînant des retards ou des pertes de messages.\n\nLa désactiver garantit une messagerie pair à pair fiable.</string>
<string name="battery_optimization_disable_button">Désactiver loptimisation</string>
<string name="battery_optimization_note">Remarque : tu peux modifier ce réglage plus tard dans Paramètres Android &gt; Apps &gt; bitchat &gt; Batterie</string>
<string name="battery_optimization_not_supported_explanation">Ton appareil na pas besoin de réglages doptimisation de batterie. bitchat fonctionnera normalement.</string>
<string name="battery_optimization_not_supported_message">Ton appareil na pas besoin de réglages doptimisation de batterie. bitchat fonctionnera normalement.</string>
<string name="battery_optimization_success_message">bitchat peut fonctionner de manière fiable en arrièreplan</string>
<string name="battery_optimization_benefits">• Livraison fiable des messages\n• Maintien de la connectivité mesh\n• Relais des messages en arrièreplan\n• Évite les coupures</string>
<string name="battery_optimization_check_again">Vérifier à nouveau</string>
<string name="battery_optimization_skip">Ignorer pour linstant</string>
<string name="battery_optimization_continue">Continuer</string>
<string name="retry">Réessayer</string>
<string name="skip">Ignorer</string>
<!-- Notifications -->
<string name="notification_summary_more">et %1$d de plus</string>
<string name="notification_messages_from_people">%1$d messages de %2$d personnes</string>
<string name="notification_more_conversations">et %1$d conversations de plus</string>
<string name="notification_active_peers_title">👥 bitchatters à proximité !</string>
<string name="notification_active_peers_one">1 personne à proximité</string>
<string name="notification_active_peers_many">%1$d personnes à proximité</string>
<string name="notification_new_messages">Nouveaux messages</string>
<string name="notification_new_location_messages">Nouveaux messages de lieu</string>
<string name="notification_mentions_in">Mentionné dans %1$s</string>
<string name="notification_mentions_in_more">Mentionné dans %1$s (+%2$d de plus)</string>
<string name="notification_mentions_in_plural">%1$d mentions dans %2$s</string>
<string name="notification_new_activity_in">Nouvelle activité dans %1$s</string>
<string name="notification_messages_in">Messages dans %1$s</string>
<string name="notification_joined_conversation">%1$s a rejoint la conversation</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d mentions</string>
<string name="notification_geohash_summary_title">bitchat discussions par lieu</string>
<string name="notification_geohash_summary_text">%1$d messages depuis %2$d lieux</string>
<string name="notification_mesh_mention_title_singular">Mentionné dans le chat Mesh</string>
<string name="notification_mesh_mention_title_plural">%1$d mentions dans le chat Mesh</string>
<string name="notification_more_locations">et %1$d lieux de plus</string>
<string name="notification_and_more">et %1$d de plus</string>
<!-- Favoris / accessibilité -->
<string name="cd_add_favorite">Ajouter aux favoris</string>
<string name="cd_remove_favorite">Retirer des favoris</string>
<string name="cd_add_bookmark">Ajouter un signet</string>
<!-- Entête de chat & accessibilité -->
<string name="chat_back">retour</string>
<string name="chat_channel_prefix">canal : %1$s</string>
<string name="chat_leave">quitter</string>
<string name="cd_nostr_reachable">Joignable via Nostr</string>
<string name="cd_unread_private_messages">Messages privés non lus</string>
<string name="cd_toggle_bookmark">Basculer le signet</string>
<string name="cd_teleported">Téléporté</string>
<string name="cd_tor_status">Statut Tor</string>
<string name="cd_connected_peers">Pairs connectés</string>
<string name="cd_geohash_participants">Participants geohash</string>
<string name="cd_ready_for_handshake">Prêt pour l’échange de clés</string>
<string name="cd_handshake_in_progress">Échange de clés en cours</string>
<string name="cd_encrypted">Chiffré de bout en bout</string>
<string name="cd_handshake_failed">Échec de l’échange</string>
<!-- Dialogue de fichier -->
<string name="file_viewer_title">📎 Fichier reçu</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Taille : %1$s</string>
<string name="file_viewer_type">🏷️ Type : %1$s</string>
<string name="file_viewer_open_save">📂 Ouvrir / Enregistrer</string>
<string name="close_with_emoji">❌ Fermer</string>
<string name="pick_image">Choisir une image</string>
<!-- Feuille À propos -->
<string name="about_tagline">messagerie mesh décentralisée avec chiffrement de bout en bout</string>
<string name="about_offline_mesh_title">Chat Mesh horsligne</string>
<string name="about_offline_mesh_desc">Communique directement via Bluetooth LE sans internet ni serveurs. Les messages sont relayés par les appareils proches pour étendre la portée.</string>
<string name="about_online_geohash_title">Canaux Geohash en ligne</string>
<string name="about_online_geohash_desc">Discute avec des personnes proches via des canaux basés sur geohash. Étends le mesh grâce à des relais internet publics.</string>
<string name="about_e2e_title">Chiffrement de bout en bout</string>
<string name="about_e2e_desc">Les messages privés sont chiffrés. Les messages de canal sont publics.</string>
<string name="about_appearance">apparence</string>
<string name="about_system">système</string>
<string name="about_light">clair</string>
<string name="about_dark">sombre</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">pow désactivé</string>
<string name="about_pow_on">pow activé</string>
<string name="about_pow_tip">ajoute un proof of work aux messages geohash pour dissuader le spam.</string>
<string name="about_pow_difficulty">difficulté : %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">la difficulté %1$d nécessite ~%2$s tentatives de hachage</string>
<string name="about_pow_desc_none">aucun proof of work requis</string>
<string name="about_pow_desc_very_low">très faible protection minimale</string>
<string name="about_pow_desc_low">faible protection basique</string>
<string name="about_pow_desc_medium">moyenne bonne protection</string>
<string name="about_pow_desc_high">élevée forte protection</string>
<string name="about_pow_desc_very_high">très élevée peut causer des délais</string>
<string name="about_pow_desc_extreme">extrême calcul important requis</string>
<string name="about_network">réseau</string>
<string name="about_tor_off">tor désactivé</string>
<string name="about_tor_on">tor activé</string>
<string name="about_tor_route">router internet via Tor pour plus de confidentialité.</string>
<string name="about_tor_status">statut Tor : %1$s, bootstrap %2$d%%</string>
<string name="about_last">Dernier : %1$s</string>
<string name="about_emergency_title">Suppression durgence des données</string>
<string name="about_emergency_tip">Astuce : tapote 3 fois le titre de lapp pour supprimer toutes les données (messages, clés, paramètres).</string>
<string name="about_debug_settings">Paramètres de debug</string>
<string name="about_footer">Open Source • Privacy First • Décentralisé</string>
<string name="close_plain">Fermer</string>
<string name="cancel_lower">annuler</string>
<!-- Descriptions génériques -->
<string name="cd_warning">Avertissement</string>
<string name="cd_location_services">Services de localisation</string>
<string name="cd_privacy">Confidentialité</string>
<string name="cd_error">Erreur</string>
<string name="cd_battery_optimization">Optimisation de la batterie</string>
<string name="cd_benefits">Avantages</string>
<string name="cd_checking_battery_optimization">Vérification de loptimisation de la batterie</string>
<string name="cd_not_supported_battery_optimization">Optimisation non prise en charge</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Message non lu</string>
<string name="cd_open_map">Ouvrir la carte</string>
<string name="cd_remove_bookmark">Retirer le signet</string>
<string name="cd_teleport">Téléporter</string>
<string name="cd_selected">Sélectionné</string>
<string name="cd_leave_channel">Quitter le canal</string>
<string name="cd_reachable_via_nostr">Joignable via Nostr</string>
<string name="cd_offline_favorite">Favori (horsligne)</string>
<string name="cd_decrease_precision">Diminuer la précision</string>
<string name="cd_increase_precision">Augmenter la précision</string>
<string name="cd_select_geohash">Sélectionner le geohash</string>
<string name="cd_scroll_to_bottom">Aller en bas</string>
<string name="cd_file">Fichier</string>
<string name="cd_image">Image</string>
<string name="cd_cancel">Annuler</string>
<string name="cd_link">Lien</string>
<string name="cd_pick_media">Choisir un média</string>
<string name="cd_record_voice">Enregistrer un message vocal</string>
<string name="cd_offline_mesh_chat">Chat Mesh horsligne</string>
<string name="cd_online_geohash_channels">Canaux Geohash en ligne</string>
<string name="cd_end_to_end_encryption">Chiffrement de bout en bout</string>
<!-- Images & fichiers -->
<string name="image_page_of">Image %1$d sur %2$d</string>
<string name="image_unavailable">Image indisponible</string>
<string name="image_saved_to_downloads">Image enregistrée dans "Téléchargements"</string>
<string name="image_save_failed">Échec de lenregistrement de limage</string>
<string name="pick_file">Choisir un fichier</string>
<string name="file_unavailable">[fichier indisponible]</string>
<string name="unknown">inconnu</string>
<!-- Feuille dactions utilisateur -->
<string name="choose_action_message_or_user">choisis une action pour ce message ou cet utilisateur</string>
<string name="choose_action_user">choisis une action pour cet utilisateur</string>
<string name="action_copy_message_title">copier le message</string>
<string name="action_copy_message_subtitle">copier ce message dans le pressepapiers</string>
<string name="action_slap_title">gifler %1$s</string>
<string name="action_slap_subtitle">envoyer une gifle amicale</string>
<string name="action_hug_title">prendre %1$s dans les bras</string>
<string name="action_hug_subtitle">envoyer une accolade amicale</string>
<string name="action_block_title">bloquer %1$s</string>
<string name="action_block_subtitle">bloquer tous les messages de cet utilisateur</string>
<!-- Feuille des canaux de lieu -->
<string name="location_channels_title">#canaux de lieu</string>
<string name="location_channels_desc">discute avec des personnes proches via des canaux geohash. seul un geohash approximatif est partagé, jamais un GPS exact. ne prends pas de capture d’écran et ne partage pas cet écran pour protéger ta vie privée.</string>
<string name="grant_location_permission">accorder la permission de localisation</string>
<string name="location_permission_denied">permission de localisation refusée. activela dans les paramètres pour utiliser les canaux de lieu.</string>
<string name="open_settings">Ouvrir les paramètres</string>
<string name="location_permission_granted">\u2713 permission de localisation accordée</string>
<string name="checking_permissions">vérification des permissions…</string>
<string name="finding_nearby_channels">recherche des canaux à proximité…</string>
<string name="bookmarked">ajouté aux favoris</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">geohash invalide</string>
<string name="teleport">téléporter</string>
<string name="disable_location_services">désactiver les services de localisation</string>
<string name="enable_location_services">activer les services de localisation</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">bloc</string>
<string name="location_level_neighborhood">quartier</string>
<string name="location_level_city">ville</string>
<string name="location_level_province">province</string>
<string name="location_level_region">région</string>
<!-- Debug / Diagnostics -->
<string name="debug_tools">outils de debug</string>
<string name="debug_tools_desc">outils développeur pour diagnostic et contrôle</string>
<string name="debug_verbose_logging">journalisation verbeuse</string>
<string name="debug_bluetooth_roles">rôles Bluetooth</string>
<string name="debug_gatt_server">serveur GATT</string>
<string name="debug_connections_fmt">connexions : %1$d / %2$d</string>
<string name="debug_max_server">max serveur</string>
<string name="debug_gatt_client">client GATT</string>
<string name="debug_max_client">max client</string>
<string name="debug_overall_connections_fmt">connexions : %1$d / %2$d</string>
<string name="debug_max_overall">max global</string>
<string name="debug_packet_relay">relais de paquets</string>
<string name="debug_since_start_fmt">depuis le début : %1$d</string>
<string name="debug_sync_settings">paramètres de synchro</string>
<string name="debug_max_packets_per_sync_fmt">paquets max par synchro : %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">taille max du filtre GCS : %1$d octets (1281024)</string>
<string name="debug_target_fpr_fmt">FPR cible : %1$.2f%%</string>
<string name="debug_connected_devices">appareils connectés</string>
<string name="debug_our_device_id_fmt">ID de notre appareil : %1$s</string>
<string name="debug_none">aucun</string>
<string name="debug_disconnect">déconnecter</string>
<string name="debug_recent_scan_results">résultats de scan récents</string>
<string name="debug_connect">connecter</string>
<string name="debug_debug_console">console de debug</string>
<string name="debug_clear">effacer</string>
<string name="debug_relays_window_fmt">dernières 10s : %1$d • 1m : %2$d • 15m : %3$d</string>
<string name="debug_derived_p_fmt">P dérivé : %1$s • nb max estimé : %2$s</string>
<string name="debug_direct_suffix"> • direct</string>
<string name="debug_question_mark">?</string>
<string name="debug_role_server">en tant que serveur (nous hébergeons)</string>
<string name="debug_role_client">en tant que client (nous nous connectons)</string>
<!-- Écrans donboarding -->
<string name="location_services_required">Services de localisation requis</string>
<string name="privacy_first">Confidentialité dabord</string>
<string name="location_explanation">bitchat ne suit PAS ta position.\n\nLes services de localisation sont requis pour le scan Bluetooth et pour la fonction de chat Geohash.</string>
<string name="location_needs_for">bitchat a besoin des services de localisation pour :</string>
<string name="location_needs_bullets">• Scan des appareils Bluetooth\n• Découvrir les utilisateurs à proximité sur le réseau mesh\n• Fonction de chat Geohash\n• Pas de suivi ni de collecte de position</string>
<string name="open_location_settings">Ouvrir les paramètres de localisation</string>
<string name="check_again">Vérifier à nouveau</string>
<string name="location_services_unavailable">Services de localisation indisponibles</string>
<string name="location_unavailable_explanation">Les services de localisation ne sont pas disponibles sur cet appareil. Cest inhabituel car ils sont standard sur Android.\n\nLapp en a besoin pour que le scan Bluetooth fonctionne correctement (exigence Android). Sans cela, lapp ne peut pas découvrir les utilisateurs à proximité.</string>
<string name="checking_location_services">Vérification des services de localisation…</string>
<string name="bluetooth_required">Bluetooth requis</string>
<string name="bluetooth_needs_for">bitchat a besoin de Bluetooth pour :</string>
<string name="bluetooth_needs_bullets">• Découvrir les utilisateurs à proximité\n• Créer des connexions de réseau mesh\n• Envoyer et recevoir des messages\n• Fonctionner sans internet ni serveurs</string>
<string name="enable_bluetooth">Activer Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth non pris en charge</string>
<string name="bluetooth_unsupported_explanation">Cet appareil ne prend pas en charge Bluetooth Low Energy (BLE), requis pour le fonctionnement de bitchat.\n\nbitchat a besoin de BLE pour créer des réseaux mesh et communiquer sans internet avec les appareils à proximité.</string>
<string name="checking_bluetooth_status">Vérification du statut Bluetooth…</string>
<string name="battery_optimization_detected_title">optimisation de la batterie détectée</string>
<string name="battery_optimization_enabled_title">Optimisation de la batterie activée</string>
<string name="battery_optimization_explanation_short">bitchat doit fonctionner en arrièreplan pour maintenir les connexions mesh. loptimisation de la batterie peut les interrompre.</string>
<string name="benefits_of_disabling">Avantages de la désactivation</string>
<string name="battery_benefits_short">• livraison fiable des messages\n• maintient la connectivité mesh\n• évite les coupures</string>
<string name="disable_battery_optimization">Désactiver loptimisation</string>
<string name="battery_optimization_disabled_title">optimisation de la batterie désactivée</string>
<string name="continue_btn">Continuer</string>
<string name="initializing_mesh_network">Initialisation du réseau mesh</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">Configuration du mesh Bluetooth…</string>
<string name="should_take_seconds">Cela ne devrait prendre que quelques secondes</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">Configuration incomplète</string>
<string name="try_again">Réessayer</string>
<string name="privacy_protected">Ta confidentialité est protégée</string>
<string name="privacy_bullets">• pas de suivi ni collecte de données\n• chats mesh Bluetooth entièrement horsligne\n• les chats geohash utilisent internet</string>
<string name="permissions_header">autorisations</string>
<string name="grant_permissions">Accorder les autorisations</string>
<string name="location_tracking_warning">bitchat ne suit PAS ta position</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">PERSONNES</string>
<string name="nobody_around">personne aux alentours…</string>
<string name="you_suffix"> (toi)</string>
<string name="pan_zoom_instruction">déplacer et zoomer pour choisir un geohash</string>
<string name="select">sélectionner</string>
<string name="type_a_message_placeholder">écrire un message…</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">mention</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">Image</string>
<string name="media_type_file">Fichier</string>
<!-- Statuts de message -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- Aide de texte de notification -->
<string name="notification_sent_image">📷 a envoyé une image</string>
<string name="notification_sent_voice">🎤 a envoyé un message vocal</string>
<string name="notification_sent_file">📎 a envoyé un fichier</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- Lecteur vocal accessibilité -->
<string name="cd_play_voice">Lire</string>
<string name="cd_pause_voice">Pause</string>
<!-- Descriptions des permissions -->
<string name="perm_nearby_devices_desc">Nécessaire pour découvrir des utilisateurs bitchat via Bluetooth</string>
<string name="perm_nearby_devices_system">Autoriser bitchat à se connecter aux appareils à proximité</string>
<string name="perm_location_desc">Requis par Android pour découvrir des utilisateurs bitchat via Bluetooth</string>
<string name="perm_location_system">bitchat en a besoin pour rechercher des appareils à proximité</string>
<string name="perm_notifications_desc">Recevoir des notifications de messages privés</string>
<string name="perm_notifications_system">Autoriser bitchat à tenvoyer des notifications</string>
<string name="perm_battery_desc">Désactiver loptimisation de la batterie pour assurer un fonctionnement fiable en arrièreplan et maintenir les connexions mesh</string>
<string name="perm_battery_system">Autoriser bitchat à fonctionner sans restrictions de batterie</string>
<!-- Types de permission -->
<string name="perm_type_nearby_devices">Appareils à proximité</string>
<string name="perm_type_precise_location">Localisation précise</string>
<string name="perm_type_microphone">Microphone</string>
<string name="perm_type_notifications">Notifications</string>
<string name="perm_type_battery_optimization">Optimisation de la batterie</string>
<string name="perm_type_other">Autre</string>
<!-- Dialogue de mot de passe -->
<string name="pwd_prompt_title">Entrer le mot de passe du canal</string>
<string name="pwd_prompt_message">Le canal %1$s est protégé par mot de passe. Entre le mot de passe pour rejoindre.</string>
<string name="pwd_label">Mot de passe</string>
<string name="join">Rejoindre</string>
<string name="cancel">Annuler</string>
<!-- Pluriels -->
<plurals name="notification_and_more">
<item quantity="one">et %d de plus</item>
<item quantity="other">et %d de plus</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 personne</item>
<item quantity="other">%d personnes</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d note</item>
<item quantity="other">#%1$s ± 1 • %2$d notes</item>
</plurals>
<string name="location_notes_description">ajoutez de courtes notes permanentes à cet endroit pour que d\'autres visiteurs les trouvent.</string>
<string name="location_notes_relays_unavailable">relais géo indisponibles ; notes en pause</string>
<string name="location_notes_no_relays_title">aucun relais géo à proximité</string>
<string name="location_notes_no_relays_desc">les notes dépendent des relais géo. vérifiez la connexion et réessayez.</string>
<string name="loading_location_notes">chargement des notes…</string>
<string name="location_notes_empty_title">aucune note pour le moment</string>
<string name="location_notes_empty_desc">soyez le premier à en ajouter pour cet endroit.</string>
<string name="dismiss">fermer</string>
<string name="location_notes_input_placeholder">ajoutez une note pour cet endroit</string>
</resources>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- TODO: Hebrew translations -->
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d הערה</item>
<item quantity="other">#%1$s ± 1 • %2$d הערות</item>
</plurals>
<string name="location_notes_description">הוסף הערות קצרות וקבועות למיקום זה כדי שמבקרים אחרים ימצאו אותן.</string>
<string name="location_notes_relays_unavailable">ממסרי מיקום אינם זמינים; ההערות הושהו</string>
<string name="location_notes_no_relays_title">אין ממסרי מיקום בקרבת מקום</string>
<string name="location_notes_no_relays_desc">ההערות תלויות בממסרי מיקום. בדוק חיבור ונסה שוב.</string>
<string name="loading_location_notes">טוען הערות…</string>
<string name="location_notes_empty_title">אין עדיין הערות</string>
<string name="location_notes_empty_desc">היה הראשון להוסיף הערה למקום זה.</string>
<string name="dismiss">סגור</string>
<string name="location_notes_input_placeholder">הוסף הערה למקום זה</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- अनुमति के कारण -->
<string name="permission_bluetooth_rationale">ब्लूटूथ अनुमति इंटरनेट के बिना सीधे दूसरों से चैट करने के लिए आवश्यक है।</string>
<string name="permission_location_rationale">स्थान अनुमति ब्लूटूथ के माध्यम से आस-पास के डिवाइस खोजने के लिए आवश्यक है।</string>
<string name="permission_notification_rationale">सूचनाओं की अनुमति नए संदेशों के बारे में बताने के लिए आवश्यक है।</string>
<!-- प्लेसहोल्डर / बुनियादी UI -->
<string name="nickname_hint">उपनाम</string>
<string name="message_hint">संदेश लिखें…</string>
<string name="channel_password_hint">पासवर्ड</string>
<string name="join_channel">चैनल में शामिल हों</string>
<string name="leave_channel">छोड़ें</string>
<string name="send_message">भेजें</string>
<string name="show_commands">कमांड दिखाएँ</string>
<string name="back">वापस</string>
<string name="people">लोग</string>
<string name="channels">चैनल</string>
<string name="online_users">ऑनलाइन उपयोगकर्ता</string>
<string name="no_one_connected">कोई कनेक्टेड नहीं</string>
<string name="emergency_clear_hint">सभी डेटा मिटाने के लिए तीन बार टैप करें</string>
<string name="your_network">आपका नेटवर्क</string>
<!-- बैटरी अनुकूलन -->
<string name="battery_optimization_detected">बैटरी अनुकूलन मिला</string>
<string name="battery_optimization_disabled">बैटरी अनुकूलन बंद है</string>
<string name="battery_optimization_not_required">बैटरी अनुकूलन आवश्यक नहीं</string>
<string name="battery_optimization_checking">बैटरी अनुकूलन जाँच रहे हैं</string>
<string name="battery_optimization_why_disable">बैटरी अनुकूलन क्यों बंद करें?</string>
<string name="battery_optimization_explanation">bitchat पृष्ठभूमि में चलती है ताकि पास के उपकरणों के साथ मेष कनेक्शन बनाए रखे। बैटरी अनुकूलन इन कनेक्शनों को बाधित कर सकता है, जिससे संदेश देर से पहुँचें या खो जाएँ।\n\nबैटरी अनुकूलन बंद करने से विश्वसनीय पीयर‑टू‑पीयर संचार सुनिश्चित होता है।</string>
<string name="battery_optimization_disable_button">बैटरी अनुकूलन बंद करें</string>
<string name="battery_optimization_note">नोट: आप इसे बाद में Android सेटिंग्स &gt; ऐप्स &gt; bitchat &gt; बैटरी में बदल सकते हैं।</string>
<string name="battery_optimization_not_supported_explanation">आपके डिवाइस को बैटरी अनुकूलन सेटिंग्स की आवश्यकता नहीं है। bitchat सामान्य रूप से चलेगी।</string>
<string name="battery_optimization_not_supported_message">आपके डिवाइस को बैटरी अनुकूलन सेटिंग्स की आवश्यकता नहीं है। bitchat सामान्य रूप से चलेगी।</string>
<string name="battery_optimization_success_message">bitchat पृष्ठभूमि में विश्वसनीय रूप से चल सकती है</string>
<string name="battery_optimization_benefits">• संदेशों की विश्वसनीय डिलीवरी\n• मेष कनेक्शन बनाए रखना\n• पृष्ठभूमि में संदेश फॉरवर्डिंग\n• डिसकनेक्शन से बचाव</string>
<string name="battery_optimization_check_again">फिर से जाँचें</string>
<string name="battery_optimization_skip">अभी छोड़ें</string>
<string name="battery_optimization_continue">जारी रखें</string>
<string name="retry">दोबारा प्रयास करें</string>
<string name="skip">छोड़ें</string>
<!-- सूचनाएँ -->
<string name="notification_summary_more">और %1$d</string>
<string name="notification_messages_from_people">%2$d लोगों से %1$d संदेश</string>
<string name="notification_more_conversations">और %1$d वार्तालाप</string>
<string name="notification_active_peers_title">👥 पास में उपयोगकर्ता!</string>
<string name="notification_active_peers_one">पास में 1 व्यक्ति</string>
<string name="notification_active_peers_many">पास में %1$d लोग</string>
<string name="notification_new_messages">नए संदेश</string>
<string name="notification_new_location_messages">नई स्थान संदेश</string>
<string name="notification_mentions_in">%1$s में उल्लेख</string>
<string name="notification_mentions_in_more">%1$s में उल्लेख (+%2$d)</string>
<string name="notification_mentions_in_plural">%2$s में %1$d उल्लेख</string>
<string name="notification_new_activity_in">%1$s में नई गतिविधि</string>
<string name="notification_messages_in">%1$s में संदेश</string>
<string name="notification_joined_conversation">%1$s बातचीत में शामिल हुआ/हुई</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d उल्लेख</string>
<string name="notification_geohash_summary_title">bitchat स्थान चैट</string>
<string name="notification_geohash_summary_text">%2$d स्थानों से %1$d संदेश</string>
<string name="notification_mesh_mention_title_singular">मेष चैट में उल्लेख</string>
<string name="notification_mesh_mention_title_plural">मेष चैट में %1$d उल्लेख</string>
<string name="notification_more_locations">और %1$d स्थान</string>
<string name="notification_and_more">और %1$d</string>
<!-- पसंद (एक्सेसिबिलिटी) -->
<string name="cd_add_favorite">पसंदीदा में जोड़ें</string>
<string name="cd_remove_favorite">पसंदीदा से हटाएँ</string>
<string name="cd_add_bookmark">बुकमार्क जोड़ें</string>
<!-- चैट हेडर & एक्सेसिबिलिटी -->
<string name="chat_back">वापस</string>
<string name="chat_channel_prefix">चैनल: %1$s</string>
<string name="chat_leave">छोड़ें</string>
<string name="cd_nostr_reachable">Nostr के माध्यम से उपलब्ध</string>
<string name="cd_unread_private_messages">अपठित निजी संदेश</string>
<string name="cd_toggle_bookmark">बुकमार्क टॉगल करें</string>
<string name="cd_teleported">टेलीपोर्ट हुआ</string>
<string name="cd_tor_status">Tor स्थिति</string>
<string name="cd_connected_peers">कनेक्टेड पीयर्स</string>
<string name="cd_geohash_participants">geohash प्रतिभागी</string>
<string name="cd_ready_for_handshake">हैंडशेक के लिए तैयार</string>
<string name="cd_handshake_in_progress">हैंडशेक जारी है</string>
<string name="cd_encrypted">एंड‑टू‑एंड एन्क्रिप्टेड</string>
<string name="cd_handshake_failed">हैंडशेक विफल</string>
<!-- फ़ाइल व्यूअर संवाद -->
<string name="file_viewer_title">📎 फ़ाइल प्राप्त</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 आकार: %1$s</string>
<string name="file_viewer_type">🏷️ प्रकार: %1$s</string>
<string name="file_viewer_open_save">📂 खोलें / सहेजें</string>
<string name="close_with_emoji">❌ बंद करें</string>
<string name="pick_image">छवि चुनें</string>
<!-- अबाउट शीट -->
<string name="about_tagline">विकेन्द्रीकृत मेष चैट • एंड‑टू‑एंड एन्क्रिप्शन</string>
<string name="about_offline_mesh_title">ऑफ़लाइन मेष चैट</string>
<string name="about_offline_mesh_desc">इंटरनेट या सर्वर के बिना Bluetooth LE के माध्यम से सीधे संवाद करें। संदेशों को पास के उपकरणों के माध्यम से रिले किया जाता है ताकि पहुँच बढ़े।</string>
<string name="about_online_geohash_title">ऑनलाइन geohash चैनल</string>
<string name="about_online_geohash_desc">geohash आधारित चैनलों के माध्यम से अपने आस‑पास के लोगों से जुड़ें। सार्वजनिक इंटरनेट रिले के माध्यम से मेष का विस्तार करें।</string>
<string name="about_e2e_title">एंड‑टू‑एंड एन्क्रिप्शन</string>
<string name="about_e2e_desc">निजी संदेश एन्क्रिप्टेड हैं। चैनल संदेश सार्वजनिक हैं।</string>
<string name="about_appearance">रूप</string>
<string name="about_system">सिस्टम</string>
<string name="about_light">लाइट</string>
<string name="about_dark">डार्क</string>
<string name="about_pow">प्रूफ़ ऑफ़ वर्क</string>
<string name="about_pow_off">PoW बंद</string>
<string name="about_pow_on">PoW चालू</string>
<string name="about_pow_tip">स्पैम को कठिन बनाने के लिए geohash संदेशों में Proof of Work जोड़ें।</string>
<string name="about_pow_difficulty">कठिनाई: %1$d बिट (~%2$s)</string>
<string name="about_pow_difficulty_attempts">कठिनाई %1$d के लिए ~%2$s हैश प्रयास</string>
<string name="about_pow_desc_none">Proof of Work आवश्यक नहीं</string>
<string name="about_pow_desc_very_low">बहुत कम – न्यूनतम स्पैम सुरक्षा</string>
<string name="about_pow_desc_low">कम – बुनियादी स्पैम सुरक्षा</string>
<string name="about_pow_desc_medium">मध्यम – अच्छी स्पैम सुरक्षा</string>
<string name="about_pow_desc_high">उच्च – मजबूत स्पैम सुरक्षा</string>
<string name="about_pow_desc_very_high">बहुत उच्च – विलंब हो सकता है</string>
<string name="about_pow_desc_extreme">अत्यधिक – काफ़ी गणनात्मक संसाधन चाहिए</string>
<string name="about_network">नेटवर्क</string>
<string name="about_tor_off">Tor बंद</string>
<string name="about_tor_on">Tor चालू</string>
<string name="about_tor_route">अधिक गोपनीयता के लिए इंटरनेट ट्रैफ़िक को Tor के माध्यम से रूट करें।</string>
<string name="about_tor_status">Tor स्थिति: %1$s, बूटस्ट्रैप %2$d%%</string>
<string name="about_last">अंतिम: %1$s</string>
<string name="about_emergency_title">आपातकालीन डेटा मिटाना</string>
<string name="about_emergency_tip">संकेत: सभी सहेजे डेटा – संदेश, कुंजियाँ और सेटिंग्स सहित – मिटाने के लिए ऐप शीर्षक पर तीन बार टैप करें।</string>
<string name="about_debug_settings">डिबग सेटिंग्स</string>
<string name="about_footer">ओपन सोर्स • गोपनीयता पहले • विकेन्द्रीकृत</string>
<string name="close_plain">बंद करें</string>
<string name="cancel_lower">रद्द करें</string>
<!-- सामान्य कंटेंट विवरण -->
<string name="cd_warning">चेतावनी</string>
<string name="cd_location_services">स्थान सेवाएँ</string>
<string name="cd_privacy">गोपनीयता</string>
<string name="cd_error">त्रुटि</string>
<string name="cd_battery_optimization">बैटरी अनुकूलन</string>
<string name="cd_benefits">लाभ</string>
<string name="cd_checking_battery_optimization">बैटरी अनुकूलन जाँच रहे हैं</string>
<string name="cd_not_supported_battery_optimization">बैटरी अनुकूलन समर्थित नहीं</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">अपठित संदेश</string>
<string name="cd_open_map">मानचित्र खोलें</string>
<string name="cd_remove_bookmark">बुकमार्क हटाएँ</string>
<string name="cd_teleport">टेलीपोर्ट</string>
<string name="cd_selected">चयनित</string>
<string name="cd_leave_channel">चैनल छोड़ें</string>
<string name="cd_reachable_via_nostr">Nostr के माध्यम से उपलब्ध</string>
<string name="cd_offline_favorite">पसंदीदा (ऑफ़लाइन)</string>
<string name="cd_decrease_precision">सटीकता घटाएँ</string>
<string name="cd_increase_precision">सटीकता बढ़ाएँ</string>
<string name="cd_select_geohash">geohash चुनें</string>
<string name="cd_scroll_to_bottom">नीचे स्क्रॉल करें</string>
<string name="cd_file">फ़ाइल</string>
<string name="cd_image">छवि</string>
<string name="cd_cancel">रद्द करें</string>
<string name="cd_link">लिंक</string>
<string name="cd_pick_media">मीडिया चुनें</string>
<string name="cd_pick_file">फ़ाइल चुनें</string>
<string name="cd_save_current_image">वर्तमान छवि सहेजें</string>
<string name="cd_close">बंद करें</string>
<string name="cd_image_index_of">छवि %1$d / %2$d</string>
<string name="cd_privacy_protected">गोपनीयता सुरक्षित</string>
<string name="cd_record_voice">वॉइस नोट रिकॉर्ड करें</string>
<string name="cd_offline_mesh_chat">ऑफ़लाइन मेष चैट</string>
<string name="cd_online_geohash_channels">ऑनलाइन geohash चैनल</string>
<string name="cd_end_to_end_encryption">एंड‑टू‑एंड एन्क्रिप्शन</string>
<!-- छवियाँ और फ़ाइलें -->
<string name="image_page_of">छवि %1$d / %2$d</string>
<string name="image_unavailable">छवि उपलब्ध नहीं</string>
<string name="image_saved_to_downloads">छवि "Downloads" में सहेजी गई</string>
<string name="image_save_failed">छवि सहेजी नहीं जा सकी</string>
<string name="toast_image_saved">छवि "Downloads" में सहेजी गई</string>
<string name="toast_failed_to_save_image">छवि सहेजी नहीं जा सकी</string>
<string name="pick_file">फ़ाइल चुनें</string>
<string name="file_unavailable">[फ़ाइल उपलब्ध नहीं]</string>
<string name="unknown">अज्ञात</string>
<!-- उपयोगकर्ता क्रिया शीट -->
<string name="choose_action_message_or_user">इस संदेश या उपयोगकर्ता के लिए क्रिया चुनें</string>
<string name="choose_action_user">इस उपयोगकर्ता के लिए क्रिया चुनें</string>
<string name="action_copy_message_title">संदेश कॉपी करें</string>
<string name="action_copy_message_subtitle">इस संदेश को क्लिपबोर्ड में कॉपी करें</string>
<string name="action_slap_title">%1$s को थप्पड़</string>
<string name="action_slap_subtitle">मज़ाकिया थप्पड़ भेजें</string>
<string name="action_hug_title">%1$s को गले लगाएँ</string>
<string name="action_hug_subtitle">दोस्ताना आलिंगन भेजें</string>
<string name="action_block_title">%1$s को ब्लॉक करें</string>
<string name="action_block_subtitle">इस उपयोगकर्ता के सभी संदेश ब्लॉक करें</string>
<!-- geohash चैनल शीट -->
<string name="location_channels_title">#स्थान चैनल</string>
<string name="location_channels_desc">geohash चैनलों के माध्यम से अपने पास के लोगों के साथ चैट करें। केवल एक मोटा geohash साझा किया जाता है, कभी भी सटीक GPS डेटा नहीं। अपनी गोपनीयता के लिए, स्क्रीनशॉट न लें और इस स्क्रीन को साझा न करें।</string>
<string name="grant_location_permission">स्थान अनुमति दें</string>
<string name="location_permission_denied">स्थान अनुमति अस्वीकार कर दी गई। स्थान चैनल उपयोग करने के लिए सेटिंग्स में सक्षम करें।</string>
<string name="open_settings">सेटिंग्स खोलें</string>
<string name="location_permission_granted">\u2713 स्थान अनुमति दी गई</string>
<string name="checking_permissions">अनुमतियाँ जाँच रहे हैं…</string>
<string name="finding_nearby_channels">पास के चैनल ढूँढ़ रहे हैं…</string>
<string name="bookmarked">बुकमार्क</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">अमान्य geohash</string>
<string name="teleport">टेलीपोर्ट</string>
<string name="disable_location_services">स्थान सेवाएँ बंद करें</string>
<string name="enable_location_services">स्थान सेवाएँ चालू करें</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">ब्लॉक</string>
<string name="location_level_neighborhood">पड़ोस</string>
<string name="location_level_city">शहर</string>
<string name="location_level_province">प्रांत</string>
<string name="location_level_region">क्षेत्र</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- डिबग / निदान -->
<string name="debug_tools">डिबग उपकरण</string>
<string name="debug_tools_desc">निदान और नियंत्रण के लिए डेवलपर टूल</string>
<string name="debug_verbose_logging">विस्तृत लॉगिंग</string>
<string name="debug_verbose_hint">पीयर जुड़ना/छोड़ना, कनेक्शन दिशा, पैकेट रिले और रिले को लॉग करता है</string>
<string name="debug_bluetooth_roles">Bluetooth भूमिकाएँ</string>
<string name="debug_gatt_server">GATT सर्वर</string>
<string name="debug_connections_fmt">कनेक्शन: %1$d / %2$d</string>
<string name="debug_max_server">अधिकतम सर्वर</string>
<string name="debug_gatt_client">GATT क्लाइंट</string>
<string name="debug_max_client">अधिकतम क्लाइंट</string>
<string name="debug_overall_connections_fmt">कनेक्शन: %1$d / %2$d</string>
<string name="debug_max_overall">कुल अधिकतम</string>
<string name="debug_packet_relay">पैकेट रिले</string>
<string name="debug_since_start_fmt">आरंभ से: %1$d</string>
<string name="debug_roles_hint">भूमिकाएँ ऑन/ऑफ करें और बंद करने पर सभी कनेक्शन बंद करें</string>
<string name="debug_sync_settings">सिंक सेटिंग्स</string>
<string name="debug_max_packets_per_sync_fmt">प्रति सिंक अधिकतम पैकेट: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">अधिकतम GCS फ़िल्टर आकार: %1$d बाइट (1281024)</string>
<string name="debug_target_fpr_fmt">लक्ष्य FPR: %1$.2f%%</string>
<string name="debug_connected_devices">कनेक्टेड डिवाइस</string>
<string name="debug_our_device_id_fmt">हमारा डिवाइस ID: %1$s</string>
<string name="debug_none">कोई नहीं</string>
<string name="debug_disconnect">डिसकनेक्ट</string>
<string name="debug_recent_scan_results">हाल में स्कैन किए डिवाइस</string>
<string name="debug_connect">कनेक्ट</string>
<string name="debug_debug_console">डिबग कंसोल</string>
<string name="debug_clear">साफ़ करें</string>
<string name="debug_relays_window_fmt">पिछले 10 से.: %1$d • 1 मि.: %2$d • 15 मि.: %3$d</string>
<string name="debug_derived_p_fmt">व्युत्पन्न P: %1$s • अनुमानित अधिकतम आइटम: %2$s</string>
<string name="debug_direct_suffix"> • डायरेक्ट</string>
<string name="debug_role_server">सर्वर के रूप में (हम होस्ट करते हैं)</string>
<string name="debug_role_client">क्लाइंट के रूप में (हम कनेक्ट करते हैं)</string>
<!-- ऑनबोर्डिंग स्क्रीन -->
<string name="location_services_required">स्थान सेवाएँ आवश्यक</string>
<string name="privacy_first">गोपनीयता पहले</string>
<string name="location_explanation">bitchat आपकी लोकेशन ट्रैक नहीं करती।\n\nBluetooth स्कैनिंग और geohash चैट फीचर के लिए स्थान सेवाएँ आवश्यक हैं।</string>
<string name="location_needs_for">bitchat को इन कारणों से स्थान सेवाएँ चाहिए:</string>
<string name="location_needs_bullets">• Bluetooth डिवाइस स्कैनिंग\n• मेष नेटवर्क में पास के उपयोगकर्ताओं की खोज\n• geohash चैट फीचर\n• कोई ट्रैकिंग या लोकेशन संग्रह नहीं</string>
<string name="open_location_settings">स्थान सेटिंग्स खोलें</string>
<string name="check_again">फिर से जाँचें</string>
<string name="location_services_unavailable">स्थान सेवाएँ उपलब्ध नहीं</string>
<string name="location_unavailable_explanation">इस डिवाइस पर स्थान सेवाएँ उपलब्ध नहीं हैं। यह असामान्य है क्योंकि Android डिवाइसों पर वे सामान्यतः होती हैं।\n\nBluetooth स्कैनिंग (Android आवश्यकता) के ठीक से काम करने के लिए स्थान सेवाएँ जरूरी हैं। इसके बिना ऐप पास के उपयोगकर्ताओं को नहीं ढूँढ़ सकती।</string>
<string name="checking_location_services">स्थान सेवाएँ जाँची जा रही हैं…</string>
<string name="bluetooth_required">Bluetooth आवश्यक</string>
<string name="bluetooth_needs_for">bitchat को Bluetooth की आवश्यकता:</string>
<string name="bluetooth_needs_bullets">• पास के उपयोगकर्ताओं की खोज\n• मेष कनेक्शन बनाना\n• संदेश भेजना और प्राप्त करना\n• इंटरनेट या सर्वर के बिना काम करना</string>
<string name="enable_bluetooth">Bluetooth चालू करें</string>
<string name="bluetooth_not_supported">Bluetooth समर्थित नहीं</string>
<string name="bluetooth_unsupported_explanation">यह डिवाइस Bluetooth Low Energy (BLE) को सपोर्ट नहीं करता, जो bitchat के लिए आवश्यक है।\n\nइंटरनेट के बिना पास के डिवाइसों के साथ मेष नेटवर्क बनाने और संवाद करने के लिए BLE आवश्यक है।</string>
<string name="checking_bluetooth_status">Bluetooth स्थिति जाँच रहे हैं…</string>
<string name="battery_optimization_detected_title">बैटरी अनुकूलन मिला</string>
<string name="battery_optimization_enabled_title">बैटरी अनुकूलन चालू है</string>
<string name="battery_optimization_explanation_short">मेष कनेक्शन बनाए रखने के लिए bitchat को पृष्ठभूमि में चलना होता है। बैटरी अनुकूलन इन कनेक्शनों को बाधित कर सकता है।</string>
<string name="benefits_of_disabling">बंद करने के लाभ</string>
<string name="battery_benefits_short">• विश्वसनीय डिलीवरी\n• मेष कनेक्टिविटी बनाए रखें\n• डिसकनेक्शन रोकें</string>
<string name="disable_battery_optimization">बैटरी अनुकूलन बंद करें</string>
<string name="battery_optimization_disabled_title">बैटरी अनुकूलन बंद</string>
<string name="continue_btn">जारी रखें</string>
<string name="initializing_mesh_network">मेष नेटवर्क प्रारंभ कर रहे हैं</string>
<string name="setting_up_bluetooth">Bluetooth मेष नेटवर्क सेट कर रहे हैं…</string>
<string name="should_take_seconds">इसमें केवल कुछ सेकंड लगेंगे</string>
<string name="setup_not_complete">सेटअप पूरा नहीं हुआ</string>
<string name="try_again">फिर से प्रयास करें</string>
<string name="privacy_protected">आपकी गोपनीयता सुरक्षित है</string>
<string name="privacy_bullets">• कोई ट्रैकिंग या डेटा संग्रह नहीं\n• Bluetooth मेष चैट पूरी तरह ऑफ़लाइन\n• geohash चैट इंटरनेट का उपयोग करती है</string>
<string name="permissions_header">अनुमतियाँ</string>
<string name="grant_permissions">अनुमतियाँ दें</string>
<string name="location_tracking_warning">bitchat आपकी लोकेशन ट्रैक नहीं करती</string>
<string name="geohash_people_header">लोग</string>
<string name="nobody_around">आस‑पास कोई नहीं…</string>
<string name="you_suffix"> (आप)</string>
<string name="pan_zoom_instruction">geohash चुनने के लिए पैन/ज़ूम करें</string>
<string name="select">चयन करें</string>
<string name="type_a_message_placeholder">संदेश लिखें…</string>
<string name="mention">उल्लेख</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">छवि</string>
<string name="media_type_file">फ़ाइल</string>
<!-- अधिसूचना पाठ सहायक -->
<string name="notification_sent_image">📷 छवि भेजी</string>
<string name="notification_sent_voice">🎤 वॉइस नोट भेजा</string>
<string name="notification_sent_file">📎 फ़ाइल भेजी</string>
<!-- वॉइस प्लेयर एक्सेसिबिलिटी -->
<string name="cd_play_voice">चलाएँ</string>
<string name="cd_pause_voice">रोकें</string>
<string name="cd_mining_pow">PoW माइनिंग</string>
<string name="cd_pow_enabled">PoW सक्षम</string>
<string name="cd_proof_of_work">प्रूफ़ ऑफ़ वर्क</string>
<string name="pow_mining_ellipsis">माइनिंग…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- अनुमति विवरण -->
<string name="perm_nearby_devices_desc">ब्लूटूथ के माध्यम से bitchat उपयोगकर्ताओं की खोज के लिए आवश्यक</string>
<string name="perm_nearby_devices_system">bitchat को पास के उपकरणों से कनेक्ट करने दें</string>
<string name="perm_location_desc">Android द्वारा आवश्यक: ब्लूटूथ के माध्यम से पास के bitchat उपयोगकर्ताओं की खोज</string>
<string name="perm_location_system">पास के उपकरण स्कैन करने के लिए bitchat को यह चाहिए</string>
<string name="perm_notifications_desc">निजी संदेश मिलने पर सूचनाएँ प्राप्त करें</string>
<string name="perm_notifications_system">bitchat को आपको सूचनाएँ भेजने दें</string>
<string name="perm_battery_desc">बैटरी अनुकूलन बंद करें ताकि bitchat पृष्ठभूमि में विश्वसनीय रूप से चल सके और मेष कनेक्शन बनाए रख सके</string>
<string name="perm_battery_system">bitchat को बैटरी प्रतिबंधों के बिना चलने दें</string>
<!-- अनुमति प्रकार -->
<string name="perm_type_nearby_devices">पास के उपकरण</string>
<string name="perm_type_precise_location">सटीक स्थान</string>
<string name="perm_type_microphone">माइक्रोफ़ोन</string>
<string name="perm_type_notifications">सूचनाएँ</string>
<string name="perm_type_battery_optimization">बैटरी अनुकूलन</string>
<string name="perm_type_other">अन्य</string>
<!-- पासवर्ड संवाद -->
<string name="pwd_prompt_title">चैनल पासवर्ड दर्ज करें</string>
<string name="pwd_prompt_message">चैनल %1$s पासवर्ड द्वारा सुरक्षित है। शामिल होने के लिए पासवर्ड दर्ज करें।</string>
<string name="pwd_label">पासवर्ड</string>
<string name="join">शामिल हों</string>
<string name="cancel">रद्द करें</string>
<!-- बहुवचन -->
<plurals name="notification_and_more">
<item quantity="one">और %d</item>
<item quantity="other">और %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 व्यक्ति</item>
<item quantity="other">%d लोग</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d नोट</item>
<item quantity="other">#%1$s ± 1 • %2$d नोट्स</item>
</plurals>
<string name="location_notes_description">अन्य आगंतुकों के लिए इस स्थान पर छोटी स्थायी नोट्स जोड़ें।</string>
<string name="location_notes_relays_unavailable">जियो रिले उपलब्ध नहीं; नोट्स विरामित</string>
<string name="location_notes_no_relays_title">आसपास कोई जियो रिले नहीं</string>
<string name="location_notes_no_relays_desc">नोट्स जियो रिले पर निर्भर हैं। कनेक्शन जांचें और फिर से प्रयास करें।</string>
<string name="loading_location_notes">नोट्स लोड हो रहे हैं…</string>
<string name="location_notes_empty_title">अभी कोई नोट नहीं</string>
<string name="location_notes_empty_desc">इस स्थान के लिए पहला नोट जोड़ें।</string>
<string name="dismiss">बंद करें</string>
<string name="location_notes_input_placeholder">इस स्थान के लिए एक नोट जोड़ें</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Alasan izin -->
<string name="permission_bluetooth_rationale">Izin Bluetooth diperlukan untuk chatting langsung dengan orang lain tanpa Internet.</string>
<string name="permission_location_rationale">Izin lokasi diperlukan untuk menemukan perangkat terdekat melalui Bluetooth.</string>
<string name="permission_notification_rationale">Izin notifikasi diperlukan untuk memberitahu Anda tentang pesan baru.</string>
<!-- Placeholder / UI dasar -->
<string name="nickname_hint">Nama panggilan</string>
<string name="message_hint">Ketik pesan…</string>
<string name="channel_password_hint">Kata sandi</string>
<string name="join_channel">Bergabung ke channel</string>
<string name="leave_channel">Keluar</string>
<string name="send_message">Kirim</string>
<string name="show_commands">Tampilkan perintah</string>
<string name="back">Kembali</string>
<string name="people">Orang</string>
<string name="channels">Channel</string>
<string name="online_users">Pengguna online</string>
<string name="no_one_connected">Tidak ada yang terhubung</string>
<string name="emergency_clear_hint">Ketuk tiga kali untuk menghapus semua data</string>
<string name="your_network">Jaringan</string>
<!-- Optimalisasi baterai -->
<string name="battery_optimization_detected">Optimalisasi baterai terdeteksi</string>
<string name="battery_optimization_disabled">Optimalisasi baterai dinonaktifkan</string>
<string name="battery_optimization_not_required">Optimalisasi baterai tidak diperlukan</string>
<string name="battery_optimization_checking">Memeriksa optimalisasi baterai</string>
<string name="battery_optimization_why_disable">Mengapa menonaktifkan optimalisasi baterai?</string>
<string name="battery_optimization_explanation">bitchat berjalan di latar belakang untuk mempertahankan koneksi mesh dengan perangkat terdekat. Optimalisasi baterai dapat mengganggu koneksi ini, menyebabkan pesan tertunda atau hilang.\n\nMenonaktifkan optimalisasi baterai memastikan komunikasi peer-to-peer yang andal.</string>
<string name="battery_optimization_disable_button">Nonaktifkan optimalisasi baterai</string>
<string name="battery_optimization_note">Catatan: Anda dapat mengubahnya nanti di Pengaturan Android &gt; Aplikasi &gt; bitchat &gt; Baterai.</string>
<string name="battery_optimization_not_supported_explanation">Perangkat Anda tidak memerlukan pengaturan optimalisasi baterai. bitchat akan berjalan normal.</string>
<string name="battery_optimization_not_supported_message">Perangkat Anda tidak memerlukan pengaturan optimalisasi baterai. bitchat akan berjalan normal.</string>
<string name="battery_optimization_success_message">bitchat dapat berjalan andal di latar belakang</string>
<string name="battery_optimization_benefits">• Pengiriman pesan yang andal\n• Mempertahankan koneksi mesh\n• Relay pesan latar belakang\n• Mencegah putusnya koneksi</string>
<string name="battery_optimization_check_again">Periksa lagi</string>
<string name="battery_optimization_skip">Lewati sekarang</string>
<string name="battery_optimization_continue">Lanjut</string>
<string name="retry">Coba lagi</string>
<string name="skip">Lewati</string>
<!-- Notifikasi -->
<string name="notification_summary_more">dan %1$d lagi</string>
<string name="notification_messages_from_people">%1$d pesan dari %2$d orang</string>
<string name="notification_more_conversations">dan %1$d percakapan lagi</string>
<string name="notification_active_peers_title">👥 bitchatter terdekat!</string>
<string name="notification_active_peers_one">1 orang terdekat</string>
<string name="notification_active_peers_many">%1$d orang terdekat</string>
<string name="notification_new_messages">Pesan baru</string>
<string name="notification_new_location_messages">Pesan lokasi baru</string>
<string name="notification_mentions_in">Disebut di %1$s</string>
<string name="notification_mentions_in_more">Disebut di %1$s (+%2$d lagi)</string>
<string name="notification_mentions_in_plural">%1$d penyebutan di %2$s</string>
<string name="notification_new_activity_in">Aktivitas baru di %1$s</string>
<string name="notification_messages_in">Pesan di %1$s</string>
<string name="notification_joined_conversation">%1$s bergabung dengan percakapan</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d penyebutan</string>
<string name="notification_geohash_summary_title">bitchat Chat lokasi</string>
<string name="notification_geohash_summary_text">%1$d pesan dari %2$d lokasi</string>
<string name="notification_mesh_mention_title_singular">Disebut di Mesh Chat</string>
<string name="notification_mesh_mention_title_plural">%1$d penyebutan di Mesh Chat</string>
<string name="notification_more_locations">dan %1$d lokasi lagi</string>
<string name="notification_and_more">dan %1$d lagi</string>
<!-- Aksesibilitas favorit -->
<string name="cd_add_favorite">Tambah ke favorit</string>
<string name="cd_remove_favorite">Hapus dari favorit</string>
<string name="cd_add_bookmark">Tambah bookmark</string>
<!-- Header chat & aksesibilitas -->
<string name="chat_back">kembali</string>
<string name="chat_channel_prefix">Channel: %1$s</string>
<string name="chat_leave">keluar</string>
<string name="cd_nostr_reachable">Dapat dijangkau melalui Nostr</string>
<string name="cd_unread_private_messages">Pesan pribadi yang belum dibaca</string>
<string name="cd_toggle_bookmark">Alihkan bookmark</string>
<string name="cd_teleported">Diteleportasi</string>
<string name="cd_tor_status">Status Tor</string>
<string name="cd_connected_peers">Peer yang terhubung</string>
<string name="cd_geohash_participants">Peserta geohash</string>
<string name="cd_ready_for_handshake">Siap untuk handshake</string>
<string name="cd_handshake_in_progress">Handshake sedang berlangsung</string>
<string name="cd_encrypted">Terenkripsi end-to-end</string>
<string name="cd_handshake_failed">Handshake gagal</string>
<!-- Dialog penampil file -->
<string name="file_viewer_title">📎 File diterima</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Ukuran: %1$s</string>
<string name="file_viewer_type">🏷️ Jenis: %1$s</string>
<string name="file_viewer_open_save">📂 Buka / Simpan</string>
<string name="close_with_emoji">❌ Tutup</string>
<string name="pick_image">Pilih gambar</string>
<!-- Sheet tentang -->
<string name="about_tagline">chat mesh terdesentralisasi dengan enkripsi end-to-end</string>
<string name="about_offline_mesh_title">Chat Mesh Offline</string>
<string name="about_offline_mesh_desc">Berkomunikasi langsung melalui Bluetooth LE tanpa Internet atau server. Pesan diteruskan melalui perangkat terdekat untuk memperluas jangkauan.</string>
<string name="about_online_geohash_title">Channel Geohash Online</string>
<string name="about_online_geohash_desc">Terhubung dengan orang-orang di area Anda melalui channel berbasis geohash. Perluas mesh melalui relay Internet publik.</string>
<string name="about_e2e_title">Enkripsi end-to-end</string>
<string name="about_e2e_desc">Pesan pribadi dienkripsi. Pesan channel bersifat publik.</string>
<string name="about_appearance">Tampilan</string>
<string name="about_system">Sistem</string>
<string name="about_light">Terang</string>
<string name="about_dark">Gelap</string>
<string name="about_pow">Proof of Work</string>
<string name="about_pow_off">PoW mati</string>
<string name="about_pow_on">PoW hidup</string>
<string name="about_pow_tip">Tambahkan proof of work ke pesan geohash untuk mempersulit spam.</string>
<string name="about_pow_difficulty">Kesulitan: %1$d bit (~%2$s)</string>
<string name="about_pow_difficulty_attempts">Kesulitan %1$d memerlukan ~%2$s percobaan hash</string>
<string name="about_pow_desc_none">tidak ada proof of work yang diperlukan</string>
<string name="about_pow_desc_very_low">sangat rendah perlindungan spam minimal</string>
<string name="about_pow_desc_low">rendah perlindungan spam dasar</string>
<string name="about_pow_desc_medium">sedang perlindungan spam yang baik</string>
<string name="about_pow_desc_high">tinggi perlindungan spam yang kuat</string>
<string name="about_pow_desc_very_high">sangat tinggi dapat menyebabkan keterlambatan</string>
<string name="about_pow_desc_extreme">ekstrem memerlukan daya komputasi yang signifikan</string>
<string name="about_network">Jaringan</string>
<string name="about_tor_off">Tor mati</string>
<string name="about_tor_on">Tor hidup</string>
<string name="about_tor_route">Rutekan lalu lintas Internet melalui Tor untuk privasi ekstra.</string>
<string name="about_tor_status">Status Tor: %1$s, Bootstrap %2$d%%</string>
<string name="about_last">Terakhir: %1$s</string>
<string name="about_emergency_title">Hapus data darurat</string>
<string name="about_emergency_tip">Tips: Ketuk tiga kali pada judul aplikasi untuk menghapus semua data tersimpan termasuk pesan, kunci, dan pengaturan.</string>
<string name="about_debug_settings">Pengaturan debug</string>
<string name="about_footer">Sumber Terbuka • Privasi Pertama • Terdesentralisasi</string>
<string name="close_plain">Tutup</string>
<string name="cancel_lower">batal</string>
<!-- Deskripsi konten umum -->
<string name="cd_warning">Peringatan</string>
<string name="cd_location_services">Layanan lokasi</string>
<string name="cd_privacy">Privasi</string>
<string name="cd_error">Kesalahan</string>
<string name="cd_battery_optimization">Optimalisasi baterai</string>
<string name="cd_benefits">Manfaat</string>
<string name="cd_checking_battery_optimization">Memeriksa optimalisasi baterai</string>
<string name="cd_not_supported_battery_optimization">Optimalisasi baterai tidak didukung</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Pesan yang belum dibaca</string>
<string name="cd_open_map">Buka peta</string>
<string name="cd_remove_bookmark">Hapus bookmark</string>
<string name="cd_teleport">Teleportasi</string>
<string name="cd_selected">Dipilih</string>
<string name="cd_leave_channel">Keluar dari channel</string>
<string name="cd_reachable_via_nostr">Dapat dijangkau melalui Nostr</string>
<string name="cd_offline_favorite">Favorit (offline)</string>
<string name="cd_decrease_precision">Kurangi presisi</string>
<string name="cd_increase_precision">Tingkatkan presisi</string>
<string name="cd_select_geohash">Pilih geohash</string>
<string name="cd_scroll_to_bottom">Gulir ke bawah</string>
<string name="cd_file">File</string>
<string name="cd_image">Gambar</string>
<string name="cd_cancel">Batal</string>
<string name="cd_link">Tautan</string>
<string name="cd_pick_media">Pilih media</string>
<string name="cd_pick_file">Pilih file</string>
<string name="cd_save_current_image">Simpan gambar saat ini</string>
<string name="cd_close">Tutup</string>
<string name="cd_image_index_of">Gambar %1$d dari %2$d</string>
<string name="cd_privacy_protected">Privasi terlindungi</string>
<string name="cd_record_voice">Rekam pesan suara</string>
<string name="cd_offline_mesh_chat">Chat Mesh Offline</string>
<string name="cd_online_geohash_channels">Channel Geohash Online</string>
<string name="cd_end_to_end_encryption">Enkripsi end-to-end</string>
<!-- Gambar & file -->
<string name="image_page_of">Gambar %1$d dari %2$d</string>
<string name="image_unavailable">Gambar tidak tersedia</string>
<string name="image_saved_to_downloads">Gambar disimpan ke \"Downloads\"</string>
<string name="image_save_failed">Gagal menyimpan gambar</string>
<string name="toast_image_saved">Gambar disimpan ke \"Downloads\"</string>
<string name="toast_failed_to_save_image">Gagal menyimpan gambar</string>
<string name="pick_file">Pilih file</string>
<string name="file_unavailable">[File tidak tersedia]</string>
<string name="unknown">tidak diketahui</string>
<!-- Sheet aksi pengguna -->
<string name="choose_action_message_or_user">Pilih aksi untuk pesan atau pengguna ini</string>
<string name="choose_action_user">Pilih aksi untuk pengguna ini</string>
<string name="action_copy_message_title">Salin pesan</string>
<string name="action_copy_message_subtitle">Salin pesan ini ke clipboard</string>
<string name="action_slap_title">Tampar %1$s</string>
<string name="action_slap_subtitle">Kirim tamparan main-main</string>
<string name="action_hug_title">Peluk %1$s</string>
<string name="action_hug_subtitle">Kirim pelukan yang ramah</string>
<string name="action_block_title">Blokir %1$s</string>
<string name="action_block_subtitle">Blokir semua pesan dari pengguna ini</string>
<!-- Sheet channel geohash -->
<string name="location_channels_title">#Channel lokasi</string>
<string name="location_channels_desc">Chat dengan orang-orang di dekat Anda melalui channel geohash. Hanya geohash kasar yang dibagikan, bukan data GPS yang tepat. Harap jangan tangkap layar atau bagikan tampilan ini untuk privasi.</string>
<string name="grant_location_permission">Berikan izin lokasi</string>
<string name="location_permission_denied">Izin lokasi ditolak. Aktifkan di Pengaturan untuk menggunakan channel lokasi.</string>
<string name="open_settings">Buka Pengaturan</string>
<string name="location_permission_granted">\u2713 Izin lokasi diberikan</string>
<string name="checking_permissions">Memeriksa izin …</string>
<string name="finding_nearby_channels">Mencari channel terdekat …</string>
<string name="bookmarked">Dibookmark</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">Geohash tidak valid</string>
<string name="teleport">teleportasi</string>
<string name="disable_location_services">Nonaktifkan layanan lokasi</string>
<string name="enable_location_services">Aktifkan layanan lokasi</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">Blok</string>
<string name="location_level_neighborhood">Lingkungan</string>
<string name="location_level_city">Kota</string>
<string name="location_level_province">Provinsi</string>
<string name="location_level_region">Wilayah</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnostik -->
<string name="debug_tools">Alat debug</string>
<string name="debug_tools_desc">Alat pengembang untuk diagnostik dan kontrol</string>
<string name="debug_verbose_logging">logging verbose</string>
<string name="debug_verbose_hint">Log bergabung/keluar peer, arah koneksi, penerusan paket dan relay</string>
<string name="debug_bluetooth_roles">Peran Bluetooth</string>
<string name="debug_gatt_server">GATT Server</string>
<string name="debug_connections_fmt">Koneksi: %1$d / %2$d</string>
<string name="debug_max_server">server maks</string>
<string name="debug_gatt_client">GATT Client</string>
<string name="debug_max_client">client maks</string>
<string name="debug_overall_connections_fmt">Koneksi: %1$d / %2$d</string>
<string name="debug_max_overall">maks keseluruhan</string>
<string name="debug_packet_relay">Packet Relay</string>
<string name="debug_since_start_fmt">sejak mulai: %1$d</string>
<string name="debug_roles_hint">Aktifkan/nonaktifkan peran dan tutup semua koneksi saat menonaktifkan</string>
<string name="debug_sync_settings">Pengaturan sinkronisasi</string>
<string name="debug_max_packets_per_sync_fmt">paket maks per sinkronisasi: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">ukuran filter GCS maks: %1$d Byte (1281024)</string>
<string name="debug_target_fpr_fmt">FPR target: %1$.2f%%</string>
<string name="debug_connected_devices">perangkat terhubung</string>
<string name="debug_our_device_id_fmt">ID perangkat kami: %1$s</string>
<string name="debug_none">tidak ada</string>
<string name="debug_disconnect">putuskan koneksi</string>
<string name="debug_recent_scan_results">perangkat yang baru dipindai</string>
<string name="debug_connect">hubungkan</string>
<string name="debug_debug_console">Konsol debug</string>
<string name="debug_clear">hapus</string>
<string name="debug_relays_window_fmt">10 detik terakhir: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P turunan: %1$s • elemen maks perkiraan: %2$s</string>
<string name="debug_direct_suffix"> • langsung</string>
<string name="debug_role_server">sebagai server (kami host)</string>
<string name="debug_role_client">sebagai client (kami hubungkan)</string>
<!-- Layar onboarding -->
<string name="location_services_required">Layanan lokasi diperlukan</string>
<string name="privacy_first">Privasi pertama</string>
<string name="location_explanation">bitchat TIDAK melacak lokasi Anda.\n\nLayanan lokasi diperlukan untuk pemindaian Bluetooth dan fitur geohash chat.</string>
<string name="location_needs_for">bitchat memerlukan layanan lokasi untuk:</string>
<string name="location_needs_bullets">• Pemindaian perangkat Bluetooth\n• Menemukan pengguna terdekat di jaringan mesh\n• Fitur geohash chat\n• Tidak ada pelacakan atau pengumpulan lokasi</string>
<string name="open_location_settings">Buka pengaturan lokasi</string>
<string name="check_again">Periksa lagi</string>
<string name="location_services_unavailable">Layanan lokasi tidak tersedia</string>
<string name="location_unavailable_explanation">Layanan lokasi tidak tersedia di perangkat ini. Ini tidak biasa karena layanan lokasi standar di perangkat Android.\n\nbitchat memerlukan layanan lokasi agar pemindaian Bluetooth berfungsi dengan benar (persyaratan Android). Tanpanya, aplikasi tidak dapat menemukan pengguna terdekat.</string>
<string name="checking_location_services">Memeriksa layanan lokasi …</string>
<string name="bluetooth_required">Bluetooth diperlukan</string>
<string name="bluetooth_needs_for">bitchat memerlukan Bluetooth untuk:</string>
<string name="bluetooth_needs_bullets">• Menemukan pengguna terdekat\n• Membuat koneksi jaringan mesh\n• Mengirim dan menerima pesan\n• Berfungsi tanpa Internet atau server</string>
<string name="enable_bluetooth">Aktifkan Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth tidak didukung</string>
<string name="bluetooth_unsupported_explanation">Perangkat ini tidak mendukung Bluetooth Low Energy (BLE), yang diperlukan agar bitchat berfungsi.\n\nbitchat memerlukan BLE untuk membuat jaringan mesh dan berkomunikasi dengan perangkat terdekat tanpa Internet.</string>
<string name="checking_bluetooth_status">Memeriksa status Bluetooth …</string>
<string name="battery_optimization_detected_title">Optimalisasi baterai terdeteksi</string>
<string name="battery_optimization_enabled_title">Optimalisasi baterai diaktifkan</string>
<string name="battery_optimization_explanation_short">bitchat harus berjalan di latar belakang untuk mempertahankan koneksi mesh. Optimalisasi baterai dapat mengganggu koneksi ini.</string>
<string name="benefits_of_disabling">Manfaat menonaktifkan</string>
<string name="battery_benefits_short">• pengiriman pesan yang andal\n• mempertahankan koneksi mesh\n• mencegah putusnya koneksi</string>
<string name="disable_battery_optimization">Nonaktifkan optimalisasi baterai</string>
<string name="battery_optimization_disabled_title">Optimalisasi baterai dinonaktifkan</string>
<string name="continue_btn">Lanjut</string>
<string name="initializing_mesh_network">Menginisialisasi jaringan mesh</string>
<string name="setting_up_bluetooth">Menyiapkan jaringan Bluetooth mesh …</string>
<string name="should_take_seconds">Ini seharusnya hanya memakan waktu beberapa detik</string>
<string name="setup_not_complete">Penyiapan tidak lengkap</string>
<string name="try_again">Coba lagi</string>
<string name="privacy_protected">Privasi Anda terlindungi</string>
<string name="privacy_bullets">• tidak ada pelacakan atau pengumpulan data\n• Bluetooth mesh chat sepenuhnya offline\n• Geohash chat menggunakan Internet</string>
<string name="permissions_header">Izin</string>
<string name="grant_permissions">Berikan izin</string>
<string name="location_tracking_warning">bitchat TIDAK melacak lokasi Anda</string>
<string name="geohash_people_header">ORANG</string>
<string name="nobody_around">tidak ada orang di sekitar …</string>
<string name="you_suffix"> (Anda)</string>
<string name="pan_zoom_instruction">geser dan zoom untuk memilih geohash</string>
<string name="select">pilih</string>
<string name="type_a_message_placeholder">Ketik pesan …</string>
<string name="mention">sebut</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Gambar</string>
<string name="media_type_file">File</string>
<!-- Pembantu teks notifikasi -->
<string name="notification_sent_image">📷 mengirim gambar</string>
<string name="notification_sent_voice">🎤 mengirim pesan suara</string>
<string name="notification_sent_file">📎 mengirim file</string>
<!-- Aksesibilitas pemutar suara -->
<string name="cd_play_voice">Putar</string>
<string name="cd_pause_voice">Jeda</string>
<string name="cd_mining_pow">Mining PoW</string>
<string name="cd_pow_enabled">PoW diaktifkan</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">Mining …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Deskripsi izin -->
<string name="perm_nearby_devices_desc">Diperlukan untuk menemukan pengguna bitchat melalui Bluetooth</string>
<string name="perm_nearby_devices_system">Izinkan bitchat terhubung dengan perangkat terdekat</string>
<string name="perm_location_desc">Diperlukan oleh Android untuk menemukan pengguna bitchat terdekat melalui Bluetooth</string>
<string name="perm_location_system">bitchat memerlukan ini untuk memindai perangkat terdekat</string>
<string name="perm_notifications_desc">Terima notifikasi saat Anda menerima pesan pribadi</string>
<string name="perm_notifications_system">Izinkan bitchat mengirim notifikasi kepada Anda</string>
<string name="perm_battery_desc">Nonaktifkan optimalisasi baterai untuk memastikan bitchat berjalan andal di latar belakang dan mempertahankan koneksi jaringan mesh</string>
<string name="perm_battery_system">Izinkan bitchat berjalan tanpa pembatasan baterai</string>
<!-- Jenis izin -->
<string name="perm_type_nearby_devices">Perangkat terdekat</string>
<string name="perm_type_precise_location">Lokasi yang tepat</string>
<string name="perm_type_microphone">Mikrofon</string>
<string name="perm_type_notifications">Notifikasi</string>
<string name="perm_type_battery_optimization">Optimalisasi baterai</string>
<string name="perm_type_other">Lainnya</string>
<!-- Dialog kata sandi -->
<string name="pwd_prompt_title">Masukkan kata sandi channel</string>
<string name="pwd_prompt_message">Channel %1$s dilindungi kata sandi. Masukkan kata sandi untuk bergabung.</string>
<string name="pwd_label">Kata sandi</string>
<string name="join">Bergabung</string>
<string name="cancel">Batal</string>
<!-- Jamak -->
<plurals name="notification_and_more">
<item quantity="one">dan %d lagi</item>
<item quantity="other">dan %d lagi</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 orang</item>
<item quantity="other">%d orang</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d catatan</item>
<item quantity="other">#%1$s ± 1 • %2$d catatan</item>
</plurals>
<string name="location_notes_description">tambahkan catatan singkat permanen ke lokasi ini agar pengunjung lain dapat menemukannya.</string>
<string name="location_notes_relays_unavailable">relay geo tidak tersedia; catatan dijeda</string>
<string name="location_notes_no_relays_title">tidak ada relay geo di sekitar</string>
<string name="location_notes_no_relays_desc">catatan bergantung pada relay geo. periksa koneksi lalu coba lagi.</string>
<string name="loading_location_notes">memuat catatan…</string>
<string name="location_notes_empty_title">belum ada catatan</string>
<string name="location_notes_empty_desc">jadilah yang pertama menambahkan catatan untuk tempat ini.</string>
<string name="dismiss">tutup</string>
<string name="location_notes_input_placeholder">tambahkan catatan untuk tempat ini</string>
</resources>
+399
View File
@@ -0,0 +1,399 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Spiegazioni dei permessi -->
<string name="permission_bluetooth_rationale">Il permesso Bluetooth è necessario per la messaggistica peer-to-peer senza internet.</string>
<string name="permission_location_rationale">Il permesso di localizzazione è necessario per scoprire i dispositivi vicini tramite Bluetooth.</string>
<string name="permission_notification_rationale">Il permesso di notifica è necessario per avvisarti di nuovi messaggi.</string>
<!-- Suggerimenti / UI di base -->
<string name="nickname_hint">nickname</string>
<string name="message_hint">scrivi un messaggio…</string>
<string name="channel_password_hint">Password</string>
<string name="join_channel">Entra nel canale</string>
<string name="leave_channel">Esci</string>
<string name="send_message">Invia</string>
<string name="show_commands">Mostra comandi</string>
<string name="back">Indietro</string>
<string name="people">Persone</string>
<string name="channels">Canali</string>
<string name="online_users">Utenti online</string>
<string name="no_one_connected">Nessuno connesso</string>
<string name="emergency_clear_hint">Tocca tre volte per cancellare tutti i dati</string>
<string name="your_network">Rete</string>
<!-- Ottimizzazione batteria -->
<string name="battery_optimization_detected">Ottimizzazione batteria rilevata</string>
<string name="battery_optimization_disabled">Ottimizzazione batteria disattivata</string>
<string name="battery_optimization_not_required">Ottimizzazione batteria non richiesta</string>
<string name="battery_optimization_checking">Controllo ottimizzazione batteria</string>
<string name="battery_optimization_why_disable">Perché disattivare l\'ottimizzazione della batteria?</string>
<string name="battery_optimization_explanation">bitchat viene eseguito in background per mantenere le connessioni di rete mesh con i dispositivi vicini. L\'ottimizzazione della batteria può interrompere queste connessioni, causando ritardi o perdita di messaggi.\n\nDisattivare l\'ottimizzazione della batteria garantisce una messaggistica peer-to-peer affidabile.</string>
<string name="battery_optimization_disable_button">Disattiva ottimizzazione batteria</string>
<string name="battery_optimization_note">Nota: puoi modificare questa impostazione in seguito in Impostazioni Android &gt; App &gt; bitchat &gt; Batteria</string>
<string name="battery_optimization_not_supported_explanation">Il tuo dispositivo non richiede impostazioni di ottimizzazione della batteria. bitchat funzionerà normalmente.</string>
<string name="battery_optimization_not_supported_message">Il tuo dispositivo non richiede impostazioni di ottimizzazione della batteria. bitchat funzionerà normalmente.</string>
<string name="battery_optimization_success_message">bitchat può funzionare in modo affidabile in background</string>
<string name="battery_optimization_benefits">• Garantisce la consegna affidabile dei messaggi\n• Mantiene la connettività della rete mesh\n• Consente l\'inoltro dei messaggi in background\n• Previene le interruzioni della connessione</string>
<string name="battery_optimization_check_again">Controlla di nuovo</string>
<string name="battery_optimization_skip">Salta per ora</string>
<string name="battery_optimization_continue">Continua</string>
<string name="retry">Riprova</string>
<string name="skip">Salta</string>
<!-- Notifiche -->
<string name="notification_summary_more">e altri %1$d</string>
<string name="notification_messages_from_people">%1$d messaggi da %2$d persone</string>
<string name="notification_more_conversations">e altre %1$d conversazioni</string>
<string name="notification_active_peers_title">👥 bitchatter nelle vicinanze!</string>
<string name="notification_active_peers_one">1 persona nei dintorni</string>
<string name="notification_active_peers_many">%1$d persone nei dintorni</string>
<string name="notification_new_messages">Nuovi messaggi</string>
<string name="notification_new_location_messages">Nuovi messaggi di posizione</string>
<string name="notification_mentions_in">Menzionato in %1$s</string>
<string name="notification_mentions_in_more">Menzionato in %1$s (+%2$d altri)</string>
<string name="notification_mentions_in_plural">%1$d menzioni in %2$s</string>
<string name="notification_new_activity_in">Nuova attività in %1$s</string>
<string name="notification_messages_in">Messaggi in %1$s</string>
<string name="notification_joined_conversation">%1$s si è unito alla conversazione</string>
<string name="notification_geohash_summary_title_mentions">bitchat - %1$d menzioni</string>
<string name="notification_geohash_summary_title">bitchat - chat di posizione</string>
<string name="notification_geohash_summary_text">%1$d messaggi da %2$d posizioni</string>
<string name="notification_mesh_mention_title_singular">Menzionato nella chat mesh</string>
<string name="notification_mesh_mention_title_plural">%1$d menzioni nella chat mesh</string>
<string name="notification_more_locations">e altre %1$d posizioni</string>
<string name="notification_and_more">e altri %1$d</string>
<!-- Accessibilità favoriti -->
<string name="cd_add_favorite">Aggiungi ai preferiti</string>
<string name="cd_remove_favorite">Rimuovi dai preferiti</string>
<string name="cd_add_bookmark">Aggiungi segnalibro</string>
<!-- Intestazione chat e accessibilità -->
<string name="chat_back">indietro</string>
<string name="chat_channel_prefix">canale: %1$s</string>
<string name="chat_leave">esci</string>
<string name="cd_nostr_reachable">Raggiungibile via Nostr</string>
<string name="cd_unread_private_messages">Messaggi privati non letti</string>
<string name="cd_toggle_bookmark">Attiva/disattiva segnalibro</string>
<string name="cd_teleported">Teletrasportato</string>
<string name="cd_tor_status">Stato Tor</string>
<string name="cd_connected_peers">Peer connessi</string>
<string name="cd_geohash_participants">Partecipanti geohash</string>
<string name="cd_ready_for_handshake">Pronto per l\'handshake</string>
<string name="cd_handshake_in_progress">Handshake in corso</string>
<string name="cd_encrypted">Crittografia end-to-end</string>
<string name="cd_handshake_failed">Handshake fallito</string>
<!-- Finestra di visualizzazione file -->
<string name="file_viewer_title">📎 File ricevuto</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Dimensione: %1$s</string>
<string name="file_viewer_type">🏷️ Tipo: %1$s</string>
<string name="file_viewer_open_save">📂 Apri / Salva</string>
<string name="close_with_emoji">❌ Chiudi</string>
<string name="pick_image">Scegli immagine</string>
<!-- Schermata informazioni -->
<string name="about_tagline">messaggistica mesh decentralizzata con crittografia end-to-end</string>
<string name="about_offline_mesh_title">Chat mesh offline</string>
<string name="about_offline_mesh_desc">Comunica direttamente tramite Bluetooth LE senza internet o server. I messaggi vengono inoltrati attraverso i dispositivi vicini per estendere la portata.</string>
<string name="about_online_geohash_title">Canali geohash online</string>
<string name="about_online_geohash_desc">Connettiti con persone nella tua area usando canali basati su geohash. Estendi la rete mesh usando relay internet pubblici.</string>
<string name="about_e2e_title">Crittografia end-to-end</string>
<string name="about_e2e_desc">I messaggi privati sono crittografati. I messaggi dei canali sono pubblici.</string>
<string name="about_appearance">aspetto</string>
<string name="about_system">sistema</string>
<string name="about_light">chiaro</string>
<string name="about_dark">scuro</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">PoW off</string>
<string name="about_pow_on">PoW on</string>
<string name="about_pow_tip">aggiungi proof of work ai messaggi geohash per scoraggiare lo spam.</string>
<string name="about_pow_difficulty">difficoltà: %1$d bit (~%2$s)</string>
<string name="about_pow_difficulty_attempts">difficoltà %1$d richiede ~%2$s tentativi di hash</string>
<string name="about_pow_desc_none">nessun proof of work richiesto</string>
<string name="about_pow_desc_very_low">molto bassa - protezione spam minima</string>
<string name="about_pow_desc_low">bassa - protezione spam base</string>
<string name="about_pow_desc_medium">media - buona protezione spam</string>
<string name="about_pow_desc_high">alta - forte protezione spam</string>
<string name="about_pow_desc_very_high">molto alta - può causare ritardi</string>
<string name="about_pow_desc_extreme">estrema - richiede calcoli significativi</string>
<string name="about_network">rete</string>
<string name="about_tor_off">Tor off</string>
<string name="about_tor_on">Tor on</string>
<string name="about_tor_route">instrada internet su Tor per una maggiore privacy.</string>
<string name="about_tor_status">Stato Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Ultimo: %1$s</string>
<string name="about_emergency_title">Eliminazione dati di emergenza</string>
<string name="about_emergency_tip">Suggerimento: fai triplo clic sul titolo dell\'app per eliminare in emergenza tutti i dati memorizzati, inclusi messaggi, chiavi e impostazioni.</string>
<string name="about_debug_settings">Impostazioni di debug</string>
<string name="about_footer">Open Source • Privacy First • Decentralizzato</string>
<string name="close_plain">Chiudi</string>
<string name="cancel_lower">annulla</string>
<!-- Descrizioni contenuto generiche -->
<string name="cd_warning">Avviso</string>
<string name="cd_location_services">Servizi di localizzazione</string>
<string name="cd_privacy">Privacy</string>
<string name="cd_error">Errore</string>
<string name="cd_battery_optimization">Ottimizzazione batteria</string>
<string name="cd_benefits">Vantaggi</string>
<string name="cd_checking_battery_optimization">Controllo ottimizzazione batteria</string>
<string name="cd_not_supported_battery_optimization">Ottimizzazione batteria non supportata</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Messaggio non letto</string>
<string name="cd_open_map">Apri mappa</string>
<string name="cd_remove_bookmark">Rimuovi segnalibro</string>
<string name="cd_teleport">Teletrasporta</string>
<string name="cd_selected">Selezionato</string>
<string name="cd_leave_channel">Esci dal canale</string>
<string name="cd_reachable_via_nostr">Raggiungibile via Nostr</string>
<string name="cd_offline_favorite">Preferito offline</string>
<string name="cd_decrease_precision">Diminuisci precisione</string>
<string name="cd_increase_precision">Aumenta precisione</string>
<string name="cd_select_geohash">Seleziona geohash</string>
<string name="cd_scroll_to_bottom">Scorri in fondo</string>
<string name="cd_file">File</string>
<string name="cd_image">Immagine</string>
<string name="cd_cancel">Annulla</string>
<string name="cd_link">Link</string>
<string name="cd_pick_media">Scegli media</string>
<string name="cd_pick_file">Scegli file</string>
<string name="cd_save_current_image">Salva immagine corrente</string>
<string name="cd_close">Chiudi</string>
<string name="cd_image_index_of">Immagine %1$d di %2$d</string>
<string name="cd_privacy_protected">Privacy protetta</string>
<string name="cd_record_voice">Registra nota vocale</string>
<string name="cd_offline_mesh_chat">Chat mesh offline</string>
<string name="cd_online_geohash_channels">Canali geohash online</string>
<string name="cd_end_to_end_encryption">Crittografia end-to-end</string>
<!-- Immagini e file -->
<string name="image_page_of">Immagine %1$d di %2$d</string>
<string name="image_unavailable">Immagine non disponibile</string>
<string name="image_saved_to_downloads">Immagine salvata in Download</string>
<string name="image_save_failed">Impossibile salvare l\'immagine</string>
<string name="toast_image_saved">Immagine salvata in Download</string>
<string name="toast_failed_to_save_image">Impossibile salvare l\'immagine</string>
<string name="pick_file">Scegli file</string>
<string name="file_unavailable">[file non disponibile]</string>
<string name="unknown">sconosciuto</string>
<!-- Azioni utente schermata -->
<string name="choose_action_message_or_user">scegli un\'azione per questo messaggio o utente</string>
<string name="choose_action_user">scegli un\'azione per questo utente</string>
<string name="action_copy_message_title">copia messaggio</string>
<string name="action_copy_message_subtitle">copia questo messaggio negli appunti</string>
<string name="action_slap_title">schiaffeggia %1$s</string>
<string name="action_slap_subtitle">invia uno schiaffo giocoso</string>
<string name="action_hug_title">abbraccia %1$s</string>
<string name="action_hug_subtitle">invia un abbraccio amichevole</string>
<string name="action_block_title">blocca %1$s</string>
<string name="action_block_subtitle">blocca tutti i messaggi da questo utente</string>
<!-- Schermata canali di posizione -->
<string name="location_channels_title">#canali di posizione</string>
<string name="location_channels_desc">chatta con persone vicino a te usando i canali geohash. viene condiviso solo un geohash approssimativo, mai la posizione GPS esatta. non fare screenshot o condividere questa schermata per proteggere la tua privacy.</string>
<string name="grant_location_permission">concedi permesso di localizzazione</string>
<string name="location_permission_denied">permesso di localizzazione negato. abilita nelle impostazioni per usare i canali di posizione.</string>
<string name="open_settings">Apri impostazioni</string>
<string name="location_permission_granted">\u2713 permesso di localizzazione concesso</string>
<string name="checking_permissions">controllo permessi…</string>
<string name="finding_nearby_channels">ricerca canali vicini…</string>
<string name="bookmarked">segnalibro</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">geohash non valido</string>
<string name="teleport">teletrasporta</string>
<string name="disable_location_services">disattiva servizi di localizzazione</string>
<string name="enable_location_services">attiva servizi di localizzazione</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">blocco</string>
<string name="location_level_neighborhood">quartiere</string>
<string name="location_level_city">città</string>
<string name="location_level_province">provincia</string>
<string name="location_level_region">regione</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnostica -->
<string name="debug_tools">strumenti di debug</string>
<string name="debug_tools_desc">utilità per sviluppatori per diagnostica e controllo</string>
<string name="debug_verbose_logging">logging dettagliato</string>
<string name="debug_verbose_hint">registra entrate/uscite peer, direzione connessione, instradamento pacchetti e relay</string>
<string name="debug_bluetooth_roles">ruoli Bluetooth</string>
<string name="debug_gatt_server">server GATT</string>
<string name="debug_connections_fmt">connessioni: %1$d / %2$d</string>
<string name="debug_max_server">max server</string>
<string name="debug_gatt_client">client GATT</string>
<string name="debug_max_client">max client</string>
<string name="debug_overall_connections_fmt">connessioni: %1$d / %2$d</string>
<string name="debug_max_overall">max totali</string>
<string name="debug_packet_relay">relay pacchetti</string>
<string name="debug_since_start_fmt">dall\'avvio: %1$d</string>
<string name="debug_roles_hint">attiva/disattiva ruoli e chiudi tutte le connessioni quando disabilitato</string>
<string name="debug_sync_settings">impostazioni sincronizzazione</string>
<string name="debug_max_packets_per_sync_fmt">max pacchetti per sync: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">dimensione max filtro GCS: %1$d byte (1281024)</string>
<string name="debug_target_fpr_fmt">FPR obiettivo: %1$.2f%%</string>
<string name="debug_connected_devices">dispositivi connessi</string>
<string name="debug_our_device_id_fmt">ID del nostro dispositivo: %1$s</string>
<string name="debug_none">nessuno</string>
<string name="debug_disconnect">disconnetti</string>
<string name="debug_recent_scan_results">risultati scansione recenti</string>
<string name="debug_connect">connetti</string>
<string name="debug_debug_console">console di debug</string>
<string name="debug_clear">cancella</string>
<string name="debug_relays_window_fmt">ultimi 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P derivato: %1$s • max elementi stimati: %2$s</string>
<string name="debug_direct_suffix"> • diretto</string>
<string name="debug_role_server">come server (noi ospitiamo)</string>
<string name="debug_role_client">come client (noi connettiamo)</string>
<!-- Schermate onboarding -->
<string name="location_services_required">Servizi di localizzazione richiesti</string>
<string name="privacy_first">Privacy prima di tutto</string>
<string name="location_explanation">bitchat NON traccia la tua posizione.\n\nI servizi di localizzazione sono necessari per la scansione Bluetooth e per la funzionalità di chat geohash.</string>
<string name="location_needs_for">bitchat ha bisogno dei servizi di localizzazione per:</string>
<string name="location_needs_bullets">• Scansione dispositivi Bluetooth\n• Scoprire utenti vicini nella rete mesh\n• Funzionalità chat geohash\n• Nessun tracciamento o raccolta di posizione</string>
<string name="open_location_settings">Apri impostazioni di localizzazione</string>
<string name="check_again">Controlla di nuovo</string>
<string name="location_services_unavailable">Servizi di localizzazione non disponibili</string>
<string name="location_unavailable_explanation">I servizi di localizzazione non sono disponibili su questo dispositivo. Ciò è insolito poiché i servizi di localizzazione sono standard sui dispositivi Android.\n\nbitchat ha bisogno dei servizi di localizzazione per far funzionare correttamente la scansione Bluetooth (requisito Android). Senza questo, l\'app non può scoprire gli utenti vicini.</string>
<string name="checking_location_services">Controllo servizi di localizzazione…</string>
<string name="bluetooth_required">Bluetooth richiesto</string>
<string name="bluetooth_needs_for">bitchat ha bisogno del Bluetooth per:</string>
<string name="bluetooth_needs_bullets">• Scoprire utenti vicini\n• Creare connessioni di rete mesh\n• Inviare e ricevere messaggi\n• Funzionare senza internet o server</string>
<string name="enable_bluetooth">Attiva Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth non supportato</string>
<string name="bluetooth_unsupported_explanation">Questo dispositivo non supporta Bluetooth Low Energy (BLE), che è necessario per il funzionamento di bitchat.\n\nbitchat ha bisogno di BLE per creare reti mesh e comunicare con dispositivi vicini senza internet.</string>
<string name="checking_bluetooth_status">Controllo stato Bluetooth…</string>
<string name="battery_optimization_detected_title">ottimizzazione batteria rilevata</string>
<string name="battery_optimization_enabled_title">Ottimizzazione batteria abilitata</string>
<string name="battery_optimization_explanation_short">bitchat deve essere eseguito in background per mantenere le connessioni mesh. l\'ottimizzazione della batteria può interrompere queste connessioni.</string>
<string name="benefits_of_disabling">Vantaggi della disattivazione</string>
<string name="battery_benefits_short">• consegna messaggi affidabile\n• mantiene la connettività mesh\n• previene le interruzioni della connessione</string>
<string name="disable_battery_optimization">Disattiva ottimizzazione batteria</string>
<string name="battery_optimization_disabled_title">ottimizzazione batteria disattivata</string>
<string name="continue_btn">Continua</string>
<string name="initializing_mesh_network">Inizializzazione rete mesh</string>
<string name="setting_up_bluetooth">Configurazione rete mesh Bluetooth…</string>
<string name="should_take_seconds">Dovrebbe richiedere solo pochi secondi</string>
<string name="setup_not_complete">Configurazione non completata</string>
<string name="try_again">Riprova</string>
<string name="privacy_protected">La tua privacy è protetta</string>
<string name="privacy_bullets">• nessun tracciamento o raccolta dati\n• le chat mesh Bluetooth sono completamente offline\n• le chat geohash usano internet</string>
<string name="permissions_header">permessi</string>
<string name="grant_permissions">Concedi permessi</string>
<string name="location_tracking_warning">bitchat NON traccia la tua posizione</string>
<string name="geohash_people_header">PERSONE</string>
<string name="nobody_around">nessuno nei dintorni…</string>
<string name="you_suffix"> (tu)</string>
<string name="pan_zoom_instruction">scorri e ingrandisci per selezionare un geohash</string>
<string name="select">seleziona</string>
<string name="type_a_message_placeholder">scrivi un messaggio…</string>
<string name="mention">menzione</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Immagine</string>
<string name="media_type_file">File</string>
<!-- Helper testo notifiche -->
<string name="notification_sent_image">📷 ha inviato un\'immagine</string>
<string name="notification_sent_voice">🎤 ha inviato un messaggio vocale</string>
<string name="notification_sent_file">📎 ha inviato un file</string>
<!-- Accessibilità lettore vocale -->
<string name="cd_play_voice">Riproduci</string>
<string name="cd_pause_voice">Pausa</string>
<string name="cd_mining_pow">Mining PoW</string>
<string name="cd_pow_enabled">PoW abilitato</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">mining…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Descrizioni permessi -->
<string name="perm_nearby_devices_desc">Necessario per scoprire utenti bitchat tramite Bluetooth</string>
<string name="perm_nearby_devices_system">Consenti a bitchat di connettersi a dispositivi vicini</string>
<string name="perm_location_desc">Richiesto da Android per scoprire utenti bitchat vicini tramite Bluetooth</string>
<string name="perm_location_system">bitchat ha bisogno di questo per cercare dispositivi vicini</string>
<string name="perm_notifications_desc">Ricevi notifiche quando ricevi messaggi privati</string>
<string name="perm_notifications_system">Consenti a bitchat di inviarti notifiche</string>
<string name="perm_battery_desc">Disattiva l\'ottimizzazione della batteria per garantire che bitchat funzioni in modo affidabile in background e mantenga le connessioni di rete mesh</string>
<string name="perm_battery_system">Consenti a bitchat di funzionare senza restrizioni della batteria</string>
<!-- Tipi di permessi -->
<string name="perm_type_nearby_devices">Dispositivi vicini</string>
<string name="perm_type_precise_location">Posizione precisa</string>
<string name="perm_type_microphone">Microfono</string>
<string name="perm_type_notifications">Notifiche</string>
<string name="perm_type_battery_optimization">Ottimizzazione batteria</string>
<string name="perm_type_other">Altro</string>
<!-- Dialogo richiesta password -->
<string name="pwd_prompt_title">Inserisci password del canale</string>
<string name="pwd_prompt_message">Il canale %1$s è protetto da password. Inserisci la password per entrare.</string>
<string name="pwd_label">Password</string>
<string name="join">Entra</string>
<string name="cancel">Annulla</string>
<!-- Simboli e stringhe speciali -->
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="at_nickname">@%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="dot">.</string>
<string name="warning_emoji">⚠️</string>
<!-- Icone stato messaggio -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- Helper file notifiche -->
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- Debug aggiuntivo -->
<string name="debug_question_mark">?</string>
<!-- Plurali -->
<plurals name="notification_and_more">
<item quantity="one">e %d altro</item>
<item quantity="other">e altri %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 persona</item>
<item quantity="other">%d persone</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d nota</item>
<item quantity="other">#%1$s ± 1 • %2$d note</item>
</plurals>
<string name="location_notes_description">aggiungi brevi note permanenti a questo luogo per altri visitatori.</string>
<string name="location_notes_relays_unavailable">relay geolocalizzati non disponibili; note in pausa</string>
<string name="location_notes_no_relays_title">nessun relay geolocalizzato nelle vicinanze</string>
<string name="location_notes_no_relays_desc">le note dipendono dai relay geo. controlla la connessione e riprova.</string>
<string name="loading_location_notes">caricamento note…</string>
<string name="location_notes_empty_title">nessuna nota ancora</string>
<string name="location_notes_empty_desc">sii il primo ad aggiungerne una per questo posto.</string>
<string name="dismiss">chiudi</string>
<string name="location_notes_input_placeholder">aggiungi una nota per questo luogo</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- 権限の説明 -->
<string name="permission_bluetooth_rationale">Bluetooth の許可は、インターネットなしで他の人と直接チャットするために必要です。</string>
<string name="permission_location_rationale">位置情報の許可は、Bluetooth で近くのデバイスを見つけるために必要です。</string>
<string name="permission_notification_rationale">通知の許可は、新しいメッセージをお知らせするために必要です。</string>
<!-- プレースホルダー / 基本 UI -->
<string name="nickname_hint">ニックネーム</string>
<string name="message_hint">メッセージを入力…</string>
<string name="channel_password_hint">パスワード</string>
<string name="join_channel">チャンネルに参加</string>
<string name="leave_channel">退出</string>
<string name="send_message">送信</string>
<string name="show_commands">コマンドを表示</string>
<string name="back">戻る</string>
<string name="people"></string>
<string name="channels">チャンネル</string>
<string name="online_users">オンラインユーザー</string>
<string name="no_one_connected">接続中のユーザーはいません</string>
<string name="emergency_clear_hint">3 回タップで全データを消去</string>
<string name="your_network">あなたのネットワーク</string>
<!-- バッテリー最適化 -->
<string name="battery_optimization_detected">バッテリー最適化を検出</string>
<string name="battery_optimization_disabled">バッテリー最適化は無効です</string>
<string name="battery_optimization_not_required">バッテリー最適化は不要です</string>
<string name="battery_optimization_checking">バッテリー最適化を確認中</string>
<string name="battery_optimization_why_disable">なぜバッテリー最適化を無効にするのか</string>
<string name="battery_optimization_explanation">bitchat はバックグラウンドで動作して、近くのデバイスとのメッシュ接続を維持します。バッテリー最適化はこれらの接続を中断し、メッセージの遅延や欠落を引き起こす可能性があります。\n\nバッテリー最適化を無効にすると、信頼できるピアツーピア通信が可能になります。</string>
<string name="battery_optimization_disable_button">バッテリー最適化を無効にする</string>
<string name="battery_optimization_note">注: 後で Android の設定 &gt; アプリ &gt; bitchat &gt; バッテリー で変更できます。</string>
<string name="battery_optimization_not_supported_explanation">この端末ではバッテリー最適化の設定は不要です。bitchat は通常通り動作します。</string>
<string name="battery_optimization_not_supported_message">この端末ではバッテリー最適化の設定は不要です。bitchat は通常通り動作します。</string>
<string name="battery_optimization_success_message">bitchat はバックグラウンドで信頼して動作できます</string>
<string name="battery_optimization_benefits">• メッセージの確実な配信\n• メッシュ接続の維持\n• バックグラウンド転送\n• 切断の防止</string>
<string name="battery_optimization_check_again">再確認</string>
<string name="battery_optimization_skip">今はスキップ</string>
<string name="battery_optimization_continue">続行</string>
<string name="retry">再試行</string>
<string name="skip">スキップ</string>
<!-- 通知 -->
<string name="notification_summary_more">ほか %1$d 件</string>
<string name="notification_messages_from_people">%2$d 人からの %1$d 件のメッセージ</string>
<string name="notification_more_conversations">ほか %1$d 会話</string>
<string name="notification_active_peers_title">👥 近くに bitchatter </string>
<string name="notification_active_peers_one">近くに 1 人</string>
<string name="notification_active_peers_many">近くに %1$d 人</string>
<string name="notification_new_messages">新着メッセージ</string>
<string name="notification_new_location_messages">新しい位置情報メッセージ</string>
<string name="notification_mentions_in">%1$s でのメンション</string>
<string name="notification_mentions_in_more">%1$s でのメンション (+%2$d)</string>
<string name="notification_mentions_in_plural">%2$s で %1$d 件のメンション</string>
<string name="notification_new_activity_in">%1$s の新しいアクティビティ</string>
<string name="notification_messages_in">%1$s のメッセージ</string>
<string name="notification_joined_conversation">%1$s が会話に参加しました</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d 件のメンション</string>
<string name="notification_geohash_summary_title">bitchat – ロケーションチャット</string>
<string name="notification_geohash_summary_text">%2$d 箇所からの %1$d 件のメッセージ</string>
<string name="notification_mesh_mention_title_singular">メッシュチャットでメンション</string>
<string name="notification_mesh_mention_title_plural">メッシュチャットで %1$d 件のメンション</string>
<string name="notification_more_locations">ほか %1$d 箇所</string>
<string name="notification_and_more">ほか %1$d</string>
<!-- お気に入り アクセシビリティ -->
<string name="cd_add_favorite">お気に入りに追加</string>
<string name="cd_remove_favorite">お気に入りから削除</string>
<string name="cd_add_bookmark">ブックマークに追加</string>
<!-- チャットヘッダー & アクセシビリティ -->
<string name="chat_back">戻る</string>
<string name="chat_channel_prefix">チャンネル: %1$s</string>
<string name="chat_leave">退出</string>
<string name="cd_nostr_reachable">Nostr 経由で到達可能</string>
<string name="cd_unread_private_messages">未読のプライベートメッセージ</string>
<string name="cd_toggle_bookmark">ブックマークを切り替え</string>
<string name="cd_teleported">テレポート済み</string>
<string name="cd_tor_status">Tor ステータス</string>
<string name="cd_connected_peers">接続中のピア</string>
<string name="cd_geohash_participants">Geohash 参加者</string>
<string name="cd_ready_for_handshake">ハンドシェイク準備完了</string>
<string name="cd_handshake_in_progress">ハンドシェイク中</string>
<string name="cd_encrypted">エンドツーエンド暗号化</string>
<string name="cd_handshake_failed">ハンドシェイク失敗</string>
<!-- ファイルビューア ダイアログ -->
<string name="file_viewer_title">📎 ファイルを受信</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 サイズ: %1$s</string>
<string name="file_viewer_type">🏷️ 種類: %1$s</string>
<string name="file_viewer_open_save">📂 開く / 保存</string>
<string name="close_with_emoji">❌ 閉じる</string>
<string name="pick_image">画像を選択</string>
<!-- 概要シート -->
<string name="about_tagline">分散型メッシュチャット・エンドツーエンド暗号化</string>
<string name="about_offline_mesh_title">オフライン・メッシュチャット</string>
<string name="about_offline_mesh_desc">インターネットやサーバーなしで、Bluetooth LE 経由で直接通信します。近隣のデバイスを経由してメッセージを中継し、到達範囲を広げます。</string>
<string name="about_online_geohash_title">オンライン Geohash チャンネル</string>
<string name="about_online_geohash_desc">Geohash ベースのチャンネルで近くの人々とつながります。公開インターネットのリレーを介してメッシュを拡張します。</string>
<string name="about_e2e_title">エンドツーエンド暗号化</string>
<string name="about_e2e_desc">プライベートメッセージは暗号化されます。チャンネルメッセージは公開です。</string>
<string name="about_appearance">表示</string>
<string name="about_system">システム</string>
<string name="about_light">ライト</string>
<string name="about_dark">ダーク</string>
<string name="about_pow">Proof of Work</string>
<string name="about_pow_off">PoW オフ</string>
<string name="about_pow_on">PoW オン</string>
<string name="about_pow_tip">スパム対策として Geohash メッセージに Proof of Work を追加します。</string>
<string name="about_pow_difficulty">難易度: %1$d ビット (~%2$s)</string>
<string name="about_pow_difficulty_attempts">難易度 %1$d は約 %2$s 回のハッシュ試行が必要</string>
<string name="about_pow_desc_none">Proof of Work は不要</string>
<string name="about_pow_desc_very_low">非常に低い 最小限のスパム対策</string>
<string name="about_pow_desc_low">低い 基本的なスパム対策</string>
<string name="about_pow_desc_medium"> 良好なスパム対策</string>
<string name="about_pow_desc_high">高い 強力なスパム対策</string>
<string name="about_pow_desc_very_high">非常に高い 遅延が発生する可能性</string>
<string name="about_pow_desc_extreme">極めて高い 相当な計算資源が必要</string>
<string name="about_network">ネットワーク</string>
<string name="about_tor_off">Tor オフ</string>
<string name="about_tor_on">Tor オン</string>
<string name="about_tor_route">プライバシー向上のため、インターネット通信を Tor 経由にします。</string>
<string name="about_tor_status">Tor ステータス: %1$s、ブートストラップ %2$d%%</string>
<string name="about_last">最終: %1$s</string>
<string name="about_emergency_title">緊急データ消去</string>
<string name="about_emergency_tip">ヒント: アプリタイトルを 3 回タップすると、メッセージ・鍵・設定を含む保存データをすべて消去します。</string>
<string name="about_debug_settings">デバッグ設定</string>
<string name="about_footer">オープンソース • プライバシーファースト • 分散型</string>
<string name="close_plain">閉じる</string>
<string name="cancel_lower">キャンセル</string>
<!-- 一般のコンテンツ記述 -->
<string name="cd_warning">警告</string>
<string name="cd_location_services">位置情報サービス</string>
<string name="cd_privacy">プライバシー</string>
<string name="cd_error">エラー</string>
<string name="cd_battery_optimization">バッテリー最適化</string>
<string name="cd_benefits">利点</string>
<string name="cd_checking_battery_optimization">バッテリー最適化を確認中</string>
<string name="cd_not_supported_battery_optimization">バッテリー最適化は非対応</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">未読メッセージ</string>
<string name="cd_open_map">地図を開く</string>
<string name="cd_remove_bookmark">ブックマークを削除</string>
<string name="cd_teleport">テレポート</string>
<string name="cd_selected">選択済み</string>
<string name="cd_leave_channel">チャンネルから退出</string>
<string name="cd_reachable_via_nostr">Nostr 経由で到達可能</string>
<string name="cd_offline_favorite">お気に入り (オフライン)</string>
<string name="cd_decrease_precision">精度を下げる</string>
<string name="cd_increase_precision">精度を上げる</string>
<string name="cd_select_geohash">Geohash を選択</string>
<string name="cd_scroll_to_bottom">一番下へスクロール</string>
<string name="cd_file">ファイル</string>
<string name="cd_image">画像</string>
<string name="cd_cancel">キャンセル</string>
<string name="cd_link">リンク</string>
<string name="cd_pick_media">メディアを選択</string>
<string name="cd_pick_file">ファイルを選択</string>
<string name="cd_save_current_image">現在の画像を保存</string>
<string name="cd_close">閉じる</string>
<string name="cd_image_index_of">画像 %1$d / %2$d</string>
<string name="cd_privacy_protected">プライバシー保護</string>
<string name="cd_record_voice">ボイスメモを録音</string>
<string name="cd_offline_mesh_chat">オフライン・メッシュチャット</string>
<string name="cd_online_geohash_channels">オンライン Geohash チャンネル</string>
<string name="cd_end_to_end_encryption">エンドツーエンド暗号化</string>
<!-- 画像 & ファイル -->
<string name="image_page_of">画像 %1$d / %2$d</string>
<string name="image_unavailable">画像は利用できません</string>
<string name="image_saved_to_downloads">画像を「ダウンロード」に保存しました</string>
<string name="image_save_failed">画像を保存できませんでした</string>
<string name="toast_image_saved">画像を「ダウンロード」に保存しました</string>
<string name="toast_failed_to_save_image">画像を保存できませんでした</string>
<string name="pick_file">ファイルを選択</string>
<string name="file_unavailable">[ファイルは利用できません]</string>
<string name="unknown">不明</string>
<!-- ユーザーアクション シート -->
<string name="choose_action_message_or_user">このメッセージまたはユーザーの操作を選択</string>
<string name="choose_action_user">このユーザーの操作を選択</string>
<string name="action_copy_message_title">メッセージをコピー</string>
<string name="action_copy_message_subtitle">このメッセージをクリップボードにコピー</string>
<string name="action_slap_title">%1$s を平手打ち</string>
<string name="action_slap_subtitle">冗談の平手打ちを送る</string>
<string name="action_hug_title">%1$s をハグ</string>
<string name="action_hug_subtitle">フレンドリーなハグを送る</string>
<string name="action_block_title">%1$s をブロック</string>
<string name="action_block_subtitle">このユーザーからのすべてのメッセージをブロック</string>
<!-- Geohash チャンネル シート -->
<string name="location_channels_title">#ロケーション・チャンネル</string>
<string name="location_channels_desc">Geohash チャンネルで近くの人とチャットしましょう。共有されるのは大まかな geohash のみで、正確な GPS データは共有されません。プライバシー保護のため、この画面のスクリーンショットや共有は行わないでください。</string>
<string name="grant_location_permission">位置情報の許可を与える</string>
<string name="location_permission_denied">位置情報の許可が拒否されました。ロケーション・チャンネルを使用するには設定で有効にしてください。</string>
<string name="open_settings">設定を開く</string>
<string name="location_permission_granted">\u2713 位置情報の許可が付与されました</string>
<string name="checking_permissions">権限を確認中…</string>
<string name="finding_nearby_channels">近くのチャンネルを検索中…</string>
<string name="bookmarked">ブックマーク</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">無効な geohash</string>
<string name="teleport">テレポート</string>
<string name="disable_location_services">位置情報サービスを無効にする</string>
<string name="enable_location_services">位置情報サービスを有効にする</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">ブロック</string>
<string name="location_level_neighborhood">近隣</string>
<string name="location_level_city"></string>
<string name="location_level_province">州 / 県</string>
<string name="location_level_region">地域</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- デバッグ / 診断 -->
<string name="debug_tools">デバッグツール</string>
<string name="debug_tools_desc">診断と制御のための開発者ツール</string>
<string name="debug_verbose_logging">詳細ログ</string>
<string name="debug_verbose_hint">ピアの参加/離脱、接続方向、パケット転送、リレーを記録</string>
<string name="debug_bluetooth_roles">Bluetooth ロール</string>
<string name="debug_gatt_server">GATT サーバー</string>
<string name="debug_connections_fmt">接続: %1$d / %2$d</string>
<string name="debug_max_server">最大サーバー</string>
<string name="debug_gatt_client">GATT クライアント</string>
<string name="debug_max_client">最大クライアント</string>
<string name="debug_overall_connections_fmt">接続: %1$d / %2$d</string>
<string name="debug_max_overall">合計最大</string>
<string name="debug_packet_relay">パケットリレー</string>
<string name="debug_since_start_fmt">開始以降: %1$d</string>
<string name="debug_roles_hint">ロールのオン/オフを切り替え、オフ時にすべての接続を閉じる</string>
<string name="debug_sync_settings">同期設定</string>
<string name="debug_max_packets_per_sync_fmt">同期あたりの最大パケット: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">GCS フィルター最大サイズ: %1$d バイト (1281024)</string>
<string name="debug_target_fpr_fmt">目標 FPR: %1$.2f%%</string>
<string name="debug_connected_devices">接続済みデバイス</string>
<string name="debug_our_device_id_fmt">自分のデバイス ID: %1$s</string>
<string name="debug_none">なし</string>
<string name="debug_disconnect">切断</string>
<string name="debug_recent_scan_results">最近スキャンしたデバイス</string>
<string name="debug_connect">接続</string>
<string name="debug_debug_console">デバッグコンソール</string>
<string name="debug_clear">クリア</string>
<string name="debug_relays_window_fmt">直近 10 秒: %1$d • 1 分: %2$d • 15 分: %3$d</string>
<string name="debug_derived_p_fmt">導出 P: %1$s • 推定最大アイテム: %2$s</string>
<string name="debug_direct_suffix"> • 直接</string>
<string name="debug_role_server">サーバーとして (自分がホスト)</string>
<string name="debug_role_client">クライアントとして (自分が接続)</string>
<!-- オンボーディング画面 -->
<string name="location_services_required">位置情報サービスが必要です</string>
<string name="privacy_first">プライバシー第一</string>
<string name="location_explanation">bitchat はあなたの位置情報を追跡しません。\n\n位置情報サービスは、Bluetooth スキャンと geohash チャット機能に必要です。</string>
<string name="location_needs_for">bitchat が位置情報サービスを必要とする理由:</string>
<string name="location_needs_bullets">• Bluetooth デバイスのスキャン\n• メッシュネットワークで近くのユーザーを発見\n• geohash チャット機能\n• 位置情報の追跡や収集は行いません</string>
<string name="open_location_settings">位置情報の設定を開く</string>
<string name="check_again">再確認</string>
<string name="location_services_unavailable">位置情報サービスが利用できません</string>
<string name="location_unavailable_explanation">この端末では位置情報サービスが利用できません。Android 端末では通常標準機能のため、これは珍しい状況です。\n\nBluetooth スキャン (Android の要件) を正しく動作させるために位置情報サービスが必要です。これがないと、近くのユーザーを検出できません。</string>
<string name="checking_location_services">位置情報サービスを確認中…</string>
<string name="bluetooth_required">Bluetooth が必要です</string>
<string name="bluetooth_needs_for">bitchat が Bluetooth を必要とする理由:</string>
<string name="bluetooth_needs_bullets">• 近くのユーザーを発見\n• メッシュネットワーク接続を作成\n• メッセージの送受信\n• インターネットやサーバーなしで動作</string>
<string name="enable_bluetooth">Bluetooth を有効にする</string>
<string name="bluetooth_not_supported">Bluetooth はサポートされていません</string>
<string name="bluetooth_unsupported_explanation">この端末は Bluetooth Low Energy (BLE) をサポートしていません。bitchat の動作に必要です。\n\nBLE は、インターネットなしで近くのデバイスとメッシュネットワークを作るために必要です。</string>
<string name="checking_bluetooth_status">Bluetooth ステータスを確認中…</string>
<string name="battery_optimization_detected_title">バッテリー最適化を検出</string>
<string name="battery_optimization_enabled_title">バッテリー最適化が有効</string>
<string name="battery_optimization_explanation_short">メッシュ接続を維持するため、bitchat はバックグラウンドで動作する必要があります。バッテリー最適化は接続を中断する可能性があります。</string>
<string name="benefits_of_disabling">無効化の利点</string>
<string name="battery_benefits_short">• 信頼できるメッセージ配信\n• メッシュ接続の維持\n• 切断の防止</string>
<string name="disable_battery_optimization">バッテリー最適化を無効化</string>
<string name="battery_optimization_disabled_title">バッテリー最適化は無効</string>
<string name="continue_btn">続行</string>
<string name="initializing_mesh_network">メッシュネットワークを初期化中</string>
<string name="setting_up_bluetooth">Bluetooth メッシュネットワークを設定中…</string>
<string name="should_take_seconds">数秒で完了するはずです</string>
<string name="setup_not_complete">設定が完了していません</string>
<string name="try_again">再試行</string>
<string name="privacy_protected">あなたのプライバシーは保護されています</string>
<string name="privacy_bullets">• 追跡やデータ収集はありません\n• Bluetooth メッシュチャットは完全にオフライン\n• geohash チャットはインターネットを使用</string>
<string name="permissions_header">権限</string>
<string name="grant_permissions">権限を付与</string>
<string name="location_tracking_warning">bitchat はあなたの位置情報を追跡しません</string>
<string name="geohash_people_header">人々</string>
<string name="nobody_around">誰もいません…</string>
<string name="you_suffix"> (あなた)</string>
<string name="pan_zoom_instruction">パン/ズームして geohash を選択</string>
<string name="select">選択</string>
<string name="type_a_message_placeholder">メッセージを入力…</string>
<string name="mention">メンション</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">画像</string>
<string name="media_type_file">ファイル</string>
<!-- 通知テキストヘルパー -->
<string name="notification_sent_image">📷 画像を送信しました</string>
<string name="notification_sent_voice">🎤 ボイスメモを送信しました</string>
<string name="notification_sent_file">📎 ファイルを送信しました</string>
<!-- ボイスプレイヤー アクセシビリティ -->
<string name="cd_play_voice">再生</string>
<string name="cd_pause_voice">一時停止</string>
<string name="cd_mining_pow">PoW をマイニング中</string>
<string name="cd_pow_enabled">PoW 有効</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">マイニング中…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- 権限の説明 -->
<string name="perm_nearby_devices_desc">Bluetooth で bitchat ユーザーを検出するために必要です</string>
<string name="perm_nearby_devices_system">bitchat が近くのデバイスに接続することを許可</string>
<string name="perm_location_desc">Android の要件: Bluetooth 経由で近くの bitchat ユーザーを検出</string>
<string name="perm_location_system">bitchat が近くのデバイスをスキャンするために必要です</string>
<string name="perm_notifications_desc">プライベートメッセージを受信したときに通知を受け取る</string>
<string name="perm_notifications_system">bitchat から通知を送信することを許可</string>
<string name="perm_battery_desc">bitchat がバックグラウンドで安定して動作し、メッシュ接続を維持できるように、バッテリー最適化を無効にします</string>
<string name="perm_battery_system">bitchat がバッテリー制限なしで動作することを許可</string>
<!-- 権限タイプ -->
<string name="perm_type_nearby_devices">近くのデバイス</string>
<string name="perm_type_precise_location">正確な位置情報</string>
<string name="perm_type_microphone">マイク</string>
<string name="perm_type_notifications">通知</string>
<string name="perm_type_battery_optimization">バッテリー最適化</string>
<string name="perm_type_other">その他</string>
<!-- パスワード ダイアログ -->
<string name="pwd_prompt_title">チャンネルのパスワードを入力</string>
<string name="pwd_prompt_message">チャンネル %1$s はパスワードで保護されています。参加するにはパスワードを入力してください。</string>
<string name="pwd_label">パスワード</string>
<string name="join">参加</string>
<string name="cancel">キャンセル</string>
<!-- 複数形 -->
<plurals name="notification_and_more">
<item quantity="one">ほか %d</item>
<item quantity="other">ほか %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 人</item>
<item quantity="other">%d 人</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d 件のメモ</item>
<item quantity="other">#%1$s ± 1 • %2$d 件のメモ</item>
</plurals>
<string name="location_notes_description">他の訪問者が見つけられるよう、この場所に短いメモを追加しましょう。</string>
<string name="location_notes_relays_unavailable">ジオリレーが利用できません。メモを一時停止中</string>
<string name="location_notes_no_relays_title">近くにジオリレーがありません</string>
<string name="location_notes_no_relays_desc">メモはジオリレーに依存します。接続を確認して再試行してください。</string>
<string name="loading_location_notes">メモを読み込み中…</string>
<string name="location_notes_empty_title">まだメモはありません</string>
<string name="location_notes_empty_desc">この場所の最初のメモを追加しましょう。</string>
<string name="dismiss">閉じる</string>
<string name="location_notes_input_placeholder">この場所へのメモを追加</string>
</resources>
+352
View File
@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- ნებართვების ახსნა -->
<string name="permission_bluetooth_rationale">Bluetooth-ის ნებართვა საჭიროა, რომ ინტერნეტის გარეშე პირდაპირ ისაუბროთ სხვებთან.</string>
<string name="permission_location_rationale">მდებარეობის ნებართვა საჭიროა ახლომდებარე მოწყობილობების Bluetooth-ით საპოვნელად.</string>
<string name="permission_notification_rationale">შეტყობინებების ნებართვა საჭიროა ახალი შეტყობინებების შეგახსენებლად.</string>
<!-- Placeholder-ები / საბაზისო UI -->
<string name="nickname_hint">მეტსახელი</string>
<string name="message_hint">შეიყვანეთ შეტყობინება…</string>
<string name="channel_password_hint">პაროლი</string>
<string name="join_channel">არხში შეუერთება</string>
<string name="leave_channel">გამოსვლა</string>
<string name="send_message">გაგზავნა</string>
<string name="show_commands">ბრძანებების ჩვენება</string>
<string name="back">უკან</string>
<string name="people">ხალხი</string>
<string name="channels">არხები</string>
<string name="online_users">ონლაინ მომხმარებლები</string>
<string name="no_one_connected">არავინ არის დაკავშირებული</string>
<string name="emergency_clear_hint">სამჯერ დააჭირეთ ყველა მონაცემის წასაშლელად</string>
<string name="your_network">თქვენი ქსელი</string>
<!-- ბატარეის ოპტიმიზაცია -->
<string name="battery_optimization_detected">ბატარეის ოპტიმიზაცია აღმოჩნდა</string>
<string name="battery_optimization_disabled">ბატარეის ოპტიმიზაცია გამორთულია</string>
<string name="battery_optimization_not_required">ბატარეის ოპტიმიზაცია არ არის საჭირო</string>
<string name="battery_optimization_checking">ბატარეის ოპტიმიზაციის შემოწმება</string>
<string name="battery_optimization_why_disable">რატომ უნდა გამოირთოს ბატარეის ოპტიმიზაცია?</string>
<string name="battery_optimization_explanation">bitchat მუშაობს ფონში, რათა ახლომდებარე მოწყობილობებთან mesh-კავშირები შეინარჩუნოს. ბატარეის ოპტიმიზაციამ შეიძლება დააწყვეტინოს ეს კავშირები, რის გამოც შეტყობინებები დაგვიანდეს ან დაიკარგოს.\n\nბატარეის ოპტიმიზაციის გამორთვა უზრუნველყოფს სანდო peer-to-peer კომუნიკაციას.</string>
<string name="battery_optimization_disable_button">ბატარეის ოპტიმიზაციის გამორთვა</string>
<string name="battery_optimization_note">შენიშვნა: შეგიძლიათ შეცვალოთ მოგვიანებით Android-ის პარამეტრებში &gt; აპები &gt; bitchat &gt; ბატარეა.</string>
<string name="battery_optimization_not_supported_explanation">თქვენს მოწყობილობას ბატარეის ოპტიმიზაცია არ სჭირდება. bitchat ჩვეულებრივ იმუშავებს.</string>
<string name="battery_optimization_not_supported_message">თქვენს მოწყობილობას ბატარეის ოპტიმიზაცია არ სჭირდება. bitchat ჩვეულებრივ იმუშავებს.</string>
<string name="battery_optimization_success_message">bitchat შეძლებს სანდოდ იმუშაოს ფონში</string>
<string name="battery_optimization_benefits">• შეტყობინებების სანდო მიწოდება\n• mesh-კავშირის შენარჩუნება\n• ფონური გადაგზავნა\n• გათიშვების თავიდან აცილება</string>
<string name="battery_optimization_check_again">თავიდან შემოწმება</string>
<string name="battery_optimization_skip">ახლა გამოტოვება</string>
<string name="battery_optimization_continue">გაგრძელება</string>
<string name="retry">კვლავ ცდა</string>
<string name="skip">გამოტოვება</string>
<!-- შეტყობინებები -->
<string name="notification_summary_more">და კიდევ %1$d</string>
<string name="notification_messages_from_people">%2$d ადამიანიდან %1$d შეტყობინება</string>
<string name="notification_more_conversations">და კიდევ %1$d საუბარი</string>
<string name="notification_active_peers_title">👥 bitchatter-ები ახლოს!</string>
<string name="notification_active_peers_one">1 ადამიანი ახლოს</string>
<string name="notification_active_peers_many">ახლოს %1$d ადამიანი</string>
<string name="notification_new_messages">ახალი შეტყობინებები</string>
<string name="notification_new_location_messages">მდებარეობის ახალი შეტყობინებები</string>
<string name="notification_mentions_in">ხსენება %1$s-ში</string>
<string name="notification_mentions_in_more">ხსენება %1$s-ში (+%2$d)</string>
<string name="notification_mentions_in_plural">%2$s-ში %1$d ხსენება</string>
<string name="notification_new_activity_in">ახალი აქტივობა %1$s-ში</string>
<string name="notification_messages_in">შეტყობინებები %1$s-ში</string>
<string name="notification_joined_conversation">%1$s შეუერთდა საუბარს</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d ხსენება</string>
<string name="notification_geohash_summary_title">bitchat – მდებარეობის ჩათები</string>
<string name="notification_geohash_summary_text">%2$d ადგილიდან %1$d შეტყობინება</string>
<string name="notification_mesh_mention_title_singular">mesh-ჩათში ხსენება</string>
<string name="notification_mesh_mention_title_plural">mesh-ჩათში %1$d ხსენება</string>
<string name="notification_more_locations">და კიდევ %1$d ადგილი</string>
<string name="notification_and_more">და კიდევ %1$d</string>
<!-- რჩეულების ხელმისაწვდომობა -->
<string name="cd_add_favorite">რჩეულებში დამატება</string>
<string name="cd_remove_favorite">რჩეულებიდან წაშლა</string>
<string name="cd_add_bookmark">სანიშნეს დამატება</string>
<!-- ჩათის სათაური & ხელმისაწვდომობა -->
<string name="chat_back">უკან</string>
<string name="chat_channel_prefix">არხი: %1$s</string>
<string name="chat_leave">გასვლა</string>
<string name="cd_nostr_reachable">მისაწვდომია Nostr-ით</string>
<string name="cd_unread_private_messages">წაუკითხავი პირადი შეტყობინებები</string>
<string name="cd_toggle_bookmark">სანიშნეს გადართვა</string>
<string name="cd_teleported">ტელეპორტირებული</string>
<string name="cd_tor_status">Tor-ის სტატუსი</string>
<string name="cd_connected_peers">დაკავშირებული პირები</string>
<string name="cd_geohash_participants">geohash მონაწილეები</string>
<string name="cd_ready_for_handshake">მზადაა ხელის ჩამოსართმევად</string>
<string name="cd_handshake_in_progress">მიმდინარეობს ხელის ჩამორთმევა</string>
<string name="cd_encrypted">ბოლო-მდე დაშიფვრა</string>
<string name="cd_handshake_failed">ხელის ჩამორთმევა წარუმატებლად დასრულდა</string>
<!-- ფაილის დამთვალიერებელი დიალოგი -->
<string name="file_viewer_title">📎 ფაილი მიღებულია</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 ზომა: %1$s</string>
<string name="file_viewer_type">🏷️ ტიპი: %1$s</string>
<string name="file_viewer_open_save">📂 გახსნა / შენახვა</string>
<string name="close_with_emoji">❌ დახურვა</string>
<string name="pick_image">სურათის არჩევა</string>
<!-- შიტი "შესახებ" -->
<string name="about_tagline">დეცენტრალიზებული mesh-ჩათი ბოლო-მდე დაშიფვრით</string>
<string name="about_offline_mesh_title">ოფლაინ mesh-ჩათი</string>
<string name="about_offline_mesh_desc">ესაუბრეთ პირდაპირ Bluetooth LE-ის საშუალებით ინტერნეტის ან სერვერების გარეშე. შეტყობინებები გადაიგზავნება ახლომდებარე მოწყობილობებზე, რათა გაიზარდოს დაფარვა.</string>
<string name="about_online_geohash_title">ონლაინ geohash არხები</string>
<string name="about_online_geohash_desc">დაუკავშირდით ახლომდებარე ხალხს geohash-ზე დაფუძნებული არხებით. გააფართოვეთ mesh საჯარო ინტერნეტ რილეებით.</string>
<string name="about_e2e_title">ბოლო-მდე დაშიფვრა</string>
<string name="about_e2e_desc">პირადი შეტყობინებები დაშიფრულია. არხის შეტყობინებები საჯაროა.</string>
<string name="about_appearance">გარეგნობა</string>
<string name="about_system">სისტემა</string>
<string name="about_light">ღია</string>
<string name="about_dark">მუქი</string>
<string name="about_pow">Proof of Work</string>
<string name="about_pow_off">PoW გამორთულია</string>
<string name="about_pow_on">PoW ჩართულია</string>
<string name="about_pow_tip">დაამატეთ Proof of Work geohash შეტყობინებებს სპამის შესამცირებლად.</string>
<string name="about_pow_difficulty">სირთულე: %1$d ბიტი (~%2$s)</string>
<string name="about_pow_difficulty_attempts">სირთულე %1$d მოითხოვს ~%2$s ჰეშის მცდელობას</string>
<string name="about_pow_desc_none">Proof of Work საჭირო არ არის</string>
<string name="about_pow_desc_very_low">ძალიან დაბალი – მინიმალური სპამის დაცვა</string>
<string name="about_pow_desc_low">დაბალი – საბაზისო დაცვა</string>
<string name="about_pow_desc_medium">საშუალო – კარგი დაცვა</string>
<string name="about_pow_desc_high">მაღალი – ძლიერი დაცვა</string>
<string name="about_pow_desc_very_high">ძალიან მაღალი – შეიძლება გამოიწვიოს დაყოვნება</string>
<string name="about_pow_desc_extreme">ექსტრემალური – საჭიროებს დიდ გამოთვლით რესურსს</string>
<string name="about_network">ქსელი</string>
<string name="about_tor_off">Tor გამორთულია</string>
<string name="about_tor_on">Tor ჩართულია</string>
<string name="about_tor_route">ინტერნეტ ტრაფიკის Tor-ით მარშრუტიზაცია პერსონალურობისთვის.</string>
<string name="about_tor_status">Tor სტატუსი: %1$s, ჩატვირთვა %2$d%%</string>
<string name="about_last">ბოლო: %1$s</string>
<string name="about_emergency_title">სასწრაფო მონაცემების წაშლა</string>
<string name="about_emergency_tip">რჩევა: დააჭირეთ აპის სათაურს სამჯერ ყველა შენახული მონაცემის – შეტყობინებების, გასაღებებისა და პარამეტრების – წასაშლელად.</string>
<string name="about_debug_settings">დebug პარამეტრები</string>
<string name="about_footer">ღია კოდი • კონფიდენციალობა პირველია • დეცენტრალიზებული</string>
<string name="close_plain">დახურვა</string>
<string name="cancel_lower">გაუქმება</string>
<!-- ზოგადი კონტენტის აღწერები -->
<string name="cd_warning">გაფრთხილება</string>
<string name="cd_location_services">მდებარეობის სერვისები</string>
<string name="cd_privacy">კონფიდენციალობა</string>
<string name="cd_error">შეცდომა</string>
<string name="cd_battery_optimization">ბატარეის ოპტიმიზაცია</string>
<string name="cd_benefits">სარგებელი</string>
<string name="cd_checking_battery_optimization">ბატარეის ოპტიმიზაციის შემოწმება</string>
<string name="cd_not_supported_battery_optimization">ბატარეის ოპტიმიზაცია მხარდაჭერილი არ არის</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">წაუკითხავი შეტყობინება</string>
<string name="cd_open_map">რუკის გახსნა</string>
<string name="cd_remove_bookmark">სანიშნეს წაშლა</string>
<string name="cd_teleport">ტელეპორტი</string>
<string name="cd_selected">მონიშნული</string>
<string name="cd_leave_channel">არხიდან გამოსვლა</string>
<string name="cd_reachable_via_nostr">მისაწვდომია Nostr-ით</string>
<string name="cd_offline_favorite">რჩეული (ოფლაინ)</string>
<string name="cd_decrease_precision">სიზუსტის შემცირება</string>
<string name="cd_increase_precision">სიზუსტის გაზრდა</string>
<string name="cd_select_geohash">აირჩიეთ geohash</string>
<string name="cd_scroll_to_bottom">ქვემოთ გადახვევა</string>
<string name="cd_file">ფაილი</string>
<string name="cd_image">სურათი</string>
<string name="cd_cancel">გაუქმება</string>
<string name="cd_link">ბმული</string>
<string name="cd_pick_media">მედიის არჩევა</string>
<string name="cd_pick_file">ფაილის არჩევა</string>
<string name="cd_save_current_image">მიმდინარე სურათის შენახვა</string>
<string name="cd_close">დახურვა</string>
<string name="cd_image_index_of">სურათი %1$d %2$d-დან</string>
<string name="cd_privacy_protected">კონფიდენციალობა დაცულია</string>
<string name="cd_record_voice">ხმოვანი ჩანაწერის ჩაწერა</string>
<string name="cd_offline_mesh_chat">ოფლაინ mesh-ჩათი</string>
<string name="cd_online_geohash_channels">ონლაინ geohash არხები</string>
<string name="cd_end_to_end_encryption">ბოლო-მდე დაშიფვრა</string>
<!-- სურათები & ფაილები -->
<string name="image_page_of">სურათი %1$d %2$d-დან</string>
<string name="image_unavailable">სურათი მიუწვდომელია</string>
<string name="image_saved_to_downloads">სურათი შენახულია "ჩამოტვირთვებში"</string>
<string name="image_save_failed">სურათის შენახვა ვერ მოხერხდა</string>
<string name="toast_image_saved">სურათი შენახულია "ჩამოტვირთვებში"</string>
<string name="toast_failed_to_save_image">სურათის შენახვა ვერ მოხერხდა</string>
<string name="pick_file">ფაილის არჩევა</string>
<string name="file_unavailable">[ფაილი მიუწვდომელია]</string>
<string name="unknown">უცნობი</string>
<!-- მომხმარებლის ქმედებების შიტი -->
<string name="choose_action_message_or_user">აირჩიეთ ქმედება ამ შეტყობინებისთვის ან მომხმარებლისთვის</string>
<string name="choose_action_user">აირჩიეთ ქმედება ამ მომხმარებლისთვის</string>
<string name="action_copy_message_title">შეტყობინების კოპირება</string>
<string name="action_copy_message_subtitle">ამ შეტყობინების კოპირება ბუფერში</string>
<string name="action_slap_title">%1$s-ის ლ®აპით დარტყმა</string>
<string name="action_slap_subtitle">გაგზავნეთ ხუმრობით ლ®აპი</string>
<string name="action_hug_title">%1$s-ის ჩახუტება</string>
<string name="action_hug_subtitle">გაგზავნეთ მეგობრული ჩახუტება</string>
<string name="action_block_title">%1$s-ის დაბლოკვა</string>
<string name="action_block_subtitle">ამ მომხმარებლის ყველა შეტყობინების დაბლოკვა</string>
<!-- geohash არხების შიტი -->
<string name="location_channels_title">#მდებარეობის არხები</string>
<string name="location_channels_desc">ესაუბრეთ თქვენს ახლოს მყოფ ადამიანებს geohash არხებით. იზიარება მხოლოდApprox geohash, არასოდეს ზუსტი GPS მონაცემები. თქვენი კონფიდენციალურობის დასაცავად ნუ გადაიღებთ სკრინშოტებს და ნუ გააზიარებთ ამ ეკრანს.</string>
<string name="grant_location_permission">მდებარეობის ნებართვის მინიჭება</string>
<string name="location_permission_denied">მდებარეობის ნებართვა უარყოფილია. ჩართეთ პარამეტრებში მდებარეობის არხების გამოსაყენებლად.</string>
<string name="open_settings">პარამეტრების გახსნა</string>
<string name="location_permission_granted">\u2713 მდებარეობის ნებართვა მინიჭებულია</string>
<string name="checking_permissions">ნებართვების შემოწმება…</string>
<string name="finding_nearby_channels">ახლომდებარე არხების ძიება…</string>
<string name="bookmarked">სანიშნეები</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">არასწორი geohash</string>
<string name="teleport">ტელეპორტი</string>
<string name="disable_location_services">მდებარეობის სერვისების გამორთვა</string>
<string name="enable_location_services">მდებარეობის სერვისების ჩართვა</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">კვარტალი</string>
<string name="location_level_neighborhood">ახლომდებარე რაიონი</string>
<string name="location_level_city">ქალაქი</string>
<string name="location_level_province">პროვინცია</string>
<string name="location_level_region">რეგიონი</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- დებაგი / დიაგნოსტიკა -->
<string name="debug_tools">დაბაგირების ხელსაწყოები</string>
<string name="debug_tools_desc">დეველოპერის ხელსაწყოები დიაგნოზისთვის და კონტროლისთვის</string>
<string name="debug_verbose_logging">გაფართოებული ლოგირება</string>
<string name="debug_verbose_hint">იწერება პირების ჩართვა/გამორთვა, კავშირის მიმართულება, პაკეტების გადაცემა და რილეები</string>
<string name="debug_bluetooth_roles">Bluetooth როლები</string>
<string name="debug_gatt_server">GATT სერვერი</string>
<string name="debug_connections_fmt">კავშირები: %1$d / %2$d</string>
<string name="debug_max_server">მაქს. სერვერი</string>
<string name="debug_gatt_client">GATT კლიენტი</string>
<string name="debug_max_client">მაქს. კლიენტი</string>
<string name="debug_overall_connections_fmt">კავშირები: %1$d / %2$d</string>
<string name="debug_max_overall">მაქს. სულ</string>
<string name="debug_packet_relay">პაკეტების რელე</string>
<string name="debug_since_start_fmt">გაშვებიდან: %1$d</string>
<string name="debug_roles_hint">როლების გადართვა და გამორთვისას ყველა კავშირის დახურვა</string>
<string name="debug_sync_settings">სინქრონიზაციის პარამეტრები</string>
<string name="debug_max_packets_per_sync_fmt">მაქს. პაკეტი სინქრონიზაციაზე: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">მაქს. GCS ფილტრის ზომა: %1$d ბაიტი (1281024)</string>
<string name="debug_target_fpr_fmt">სამიზნე FPR: %1$.2f%%</string>
<string name="debug_connected_devices">დაკავშირებული მოწყობილობები</string>
<string name="debug_our_device_id_fmt">ჩვენი მოწყობილობის ID: %1$s</string>
<string name="debug_none">არცერთი</string>
<string name="debug_disconnect">გათიშვა</string>
<string name="debug_recent_scan_results">ბოლო სკანირებული მოწყობილობები</string>
<string name="debug_connect">დაკავშირება</string>
<string name="debug_debug_console">დაბაგ კონსოლი</string>
<string name="debug_clear">გასუფთავება</string>
<string name="debug_relays_window_fmt">ბოლო 10 წმ: %1$d • 1 წთ: %2$d • 15 წთ: %3$d</string>
<string name="debug_derived_p_fmt">განმუხტული P: %1$s • სავარაუდო მაქს. ელემენტები: %2$s</string>
<string name="debug_direct_suffix"> • პირდაპირ</string>
<string name="debug_role_server">სერვერის როლში (ჩვენ ვმასპინძლობთ)</string>
<string name="debug_role_client">კლიენტის როლში (ჩვენ ვუკავშირდებით)</string>
<!-- ონბორდინგის ეკრანები -->
<string name="location_services_required">მდებარეობის სერვისებია საჭირო</string>
<string name="privacy_first">კონფიდენციალობა პირველია</string>
<string name="location_explanation">bitchat არ აკონტროლებს თქვენს მდებარეობას.\n\nმდებარეობის სერვისები საჭიროა Bluetooth სკანირებისა და geohash ჩათის ფუნქციისთვის.</string>
<string name="location_needs_for">bitchat-ს სჭირდება მდებარეობის სერვისები შემდეგისთვის:</string>
<string name="location_needs_bullets">• Bluetooth მოწყობილობების სკანირება\n• mesh ქსელში ახლომდებარე მომხმარებლების აღმოჩენა\n• geohash ჩათის ფუნქცია\n• არც ტრეკინგი, არც მდებარეობის შეგროვება</string>
<string name="open_location_settings">მდებარეობის პარამეტრების გახსნა</string>
<string name="check_again">თავიდან შემოწმება</string>
<string name="location_services_unavailable">მდებარეობის სერვისები მიუწვდომელია</string>
<string name="location_unavailable_explanation">ამ მოწყობილობაზე მდებარეობის სერვისები მიუწვდომელია. ეს უჩვეულოა, რადგან Android მოწყობილობებზე ისინი სტანდარტულია.\n\nBluetooth სკანირებისთვის (Android-ის მოთხოვნა) საჭიროა მდებარეობის სერვისები. ამის გარეშე აპს არ შეუძლია ახლომდებარე მომხმარებლების აღმოჩენა.</string>
<string name="checking_location_services">მდებარეობის სერვისების შემოწმება…</string>
<string name="bluetooth_required">Bluetooth საჭიროა</string>
<string name="bluetooth_needs_for">bitchat-ს სჭირდება Bluetooth შემდეგისთვის:</string>
<string name="bluetooth_needs_bullets">• ახლომდებარე მომხმარებლების აღმოჩენა\n• mesh ქსელის კავშირების შექმნა\n• შეტყობინებების გაგზავნა/მიღება\n• მუშაობა ინტერნეტის ან სერვერების გარეშე</string>
<string name="enable_bluetooth">Bluetooth-ის ჩართვა</string>
<string name="bluetooth_not_supported">Bluetooth არ მხარდაჭერილია</string>
<string name="bluetooth_unsupported_explanation">ამ მოწყობილობას არ უჭერს მხარს Bluetooth Low Energy (BLE), რომელიც საჭიროა bitchat-ისთვის.\n\nBLE საჭიროა mesh ქსელების შესაქმნელად და ახლომდებარე მოწყობილობებთან ინტერნეტის გარეშე კომუნიკაციისთვის.</string>
<string name="checking_bluetooth_status">Bluetooth სტატუსის შემოწმება…</string>
<string name="battery_optimization_detected_title">ბატარეის ოპტიმიზაცია აღმოჩნდა</string>
<string name="battery_optimization_enabled_title">ბატარეის ოპტიმიზაცია ჩართულია</string>
<string name="battery_optimization_explanation_short">mesh კავშირების შესანარჩუნებლად bitchat უნდა იმუშავოს ფონში. ბატარეის ოპტიმიზაციამ შეიძლება დაარღვიოს ეს კავშირები.</string>
<string name="benefits_of_disabling">გამორთვის სარგებელი</string>
<string name="battery_benefits_short">• სანდო მიწოდება\n• mesh კავშირის შენარჩუნება\n• გათიშვების თავიდან აცილება</string>
<string name="disable_battery_optimization">ბატარეის ოპტიმიზაციის გამორთვა</string>
<string name="battery_optimization_disabled_title">ბატარეის ოპტიმიზაცია გამორთულია</string>
<string name="continue_btn">გაგრძელება</string>
<string name="initializing_mesh_network">mesh ქსელის ინიციალიზაცია</string>
<string name="setting_up_bluetooth">Bluetooth mesh ქსელის მოწყობა…</string>
<string name="should_take_seconds">ეს რამდენიმე წამს უნდა გაგრძელდეს</string>
<string name="setup_not_complete">მოწყობა დაუსრულებელია</string>
<string name="try_again">კვლავ ცდა</string>
<string name="privacy_protected">თქვენი კონფიდენციალობა დაცულია</string>
<string name="privacy_bullets">• ტრეკინგი ან მონაცემთა შეგროვება არა\n• Bluetooth mesh-ჩათები სრულად ოფლაინ\n• geohash ჩათი იყენებს ინტერნეტს</string>
<string name="permissions_header">ნებართვები</string>
<string name="grant_permissions">ნებართვების მინიჭება</string>
<string name="location_tracking_warning">bitchat არ აკონტროლებს თქვენს მდებარეობას</string>
<string name="geohash_people_header">ხალხი</string>
<string name="nobody_around">არავინ არის ახლოს…</string>
<string name="you_suffix"> (თქვენ)</string>
<string name="pan_zoom_instruction">პანორამირება/ზუმი geohash-ის ასარჩევად</string>
<string name="select">არჩევა</string>
<string name="type_a_message_placeholder">შეიყვანეთ შეტყობინება…</string>
<string name="mention">ხსენება</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">სურათი</string>
<string name="media_type_file">ფაილი</string>
<!-- შეტყობინებების ტექსტის დამხმარეები -->
<string name="notification_sent_image">📷 გაგზავნა სურათი</string>
<string name="notification_sent_voice">🎤 გაგზავნა ხმოვანი შენიშვნა</string>
<string name="notification_sent_file">📎 გაგზავნა ფაილი</string>
<!-- ხმოვანი დამკვრელის ხელმისაწვდომობა -->
<string name="cd_play_voice">დაკვრა</string>
<string name="cd_pause_voice">პაუზა</string>
<string name="cd_mining_pow">PoW მაინინგი</string>
<string name="cd_pow_enabled">PoW ჩართულია</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">მაინინგი…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- ნებართვების აღწერები -->
<string name="perm_nearby_devices_desc">საჭიროა bitchat მომხმარებლების Bluetooth-ით აღმოსაჩენად</string>
<string name="perm_nearby_devices_system">დაუშვით bitchat-ს დაუკავშირდეს ახლომდებარე მოწყობილობებს</string>
<string name="perm_location_desc">Android მოითხოვს ახლომდებარე bitchat მომხმარებლების Bluetooth-ით აღმოსაჩენად</string>
<string name="perm_location_system">ეს საჭიროა ახლომდებარე მოწყობილობების დასასკანად</string>
<string name="perm_notifications_desc">საინფორმაციო შეტყობინებების მიღება პირადი მესიჯებისას</string>
<string name="perm_notifications_system">დაუშვით bitchat-ს გამოგიგზავნოთ შეტყობინებები</string>
<string name="perm_battery_desc">გამორთეთ ბატარეის ოპტიმიზაცია, რომ bitchat სანდოდ იმუშაოს ფონში და შეინარჩუნოს mesh-კავშირები</string>
<string name="perm_battery_system">დაუშვით bitchat-ს იმუშაოს ბატარეის შეზღუდვების გარეშე</string>
<!-- ნებართვების ტიპები -->
<string name="perm_type_nearby_devices">ახლომდებარე მოწყობილობები</string>
<string name="perm_type_precise_location">ზუსტი მდებარეობა</string>
<string name="perm_type_microphone">მიკროფონი</string>
<string name="perm_type_notifications">შეტყობინებები</string>
<string name="perm_type_battery_optimization">ბატარეის ოპტიმიზაცია</string>
<string name="perm_type_other">სხვა</string>
<!-- პაროლის დიალოგი -->
<string name="pwd_prompt_title">შეიყვანეთ არხის პაროლი</string>
<string name="pwd_prompt_message">არხი %1$s დაცულია პაროლით. შეიყვანეთ პაროლი შესაერთებლად.</string>
<string name="pwd_label">პაროლი</string>
<string name="join">შეუერთდი</string>
<string name="cancel">გაუქმება</string>
<!-- მრავლობითი რიცხვები -->
<plurals name="notification_and_more">
<item quantity="one">და კიდევ %d</item>
<item quantity="other">და კიდევ %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 ადამიანი</item>
<item quantity="other">%d ადამიანი</item>
</plurals>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- 권한 안내 -->
<string name="permission_bluetooth_rationale">인터넷 없이 다른 사람과 직접 채팅하려면 블루투스 권한이 필요합니다.</string>
<string name="permission_location_rationale">블루투스로 주변 기기를 찾으려면 위치 권한이 필요합니다.</string>
<string name="permission_notification_rationale">새 메시지를 알려면 알림 권한이 필요합니다.</string>
<!-- 플레이스홀더 / 기본 UI -->
<string name="nickname_hint">닉네임</string>
<string name="message_hint">메시지 입력…</string>
<string name="channel_password_hint">비밀번호</string>
<string name="join_channel">채널 참가</string>
<string name="leave_channel">나가기</string>
<string name="send_message">보내기</string>
<string name="show_commands">명령 보기</string>
<string name="back">뒤로</string>
<string name="people">사람들</string>
<string name="channels">채널</string>
<string name="online_users">온라인 사용자</string>
<string name="no_one_connected">연결된 사람이 없음</string>
<string name="emergency_clear_hint">모든 데이터를 지우려면 세 번 탭하세요</string>
<string name="your_network">네트워크</string>
<!-- 배터리 최적화 -->
<string name="battery_optimization_detected">배터리 최적화 감지됨</string>
<string name="battery_optimization_disabled">배터리 최적화 비활성화됨</string>
<string name="battery_optimization_not_required">배터리 최적화 필요 없음</string>
<string name="battery_optimization_checking">배터리 최적화 확인 중</string>
<string name="battery_optimization_why_disable">왜 배터리 최적화를 끄나요?</string>
<string name="battery_optimization_explanation">bitchat은 근처 기기와의 메쉬 연결을 유지하기 위해 백그라운드에서 동작합니다. 배터리 최적화는 이러한 연결을 중단시켜 메시지가 지연되거나 손실될 수 있습니다.\n\n배터리 최적화를 끄면 신뢰할 수 있는 P2P 통신이 보장됩니다.</string>
<string name="battery_optimization_disable_button">배터리 최적화 끄기</string>
<string name="battery_optimization_note">참고: 이후 Android 설정 &gt;&gt; bitchat &gt; 배터리에서 변경할 수 있습니다.</string>
<string name="battery_optimization_not_supported_explanation">이 기기는 배터리 최적화 설정이 필요하지 않습니다. bitchat은 정상적으로 동작합니다.</string>
<string name="battery_optimization_not_supported_message">이 기기는 배터리 최적화 설정이 필요하지 않습니다. bitchat은 정상적으로 동작합니다.</string>
<string name="battery_optimization_success_message">bitchat이 백그라운드에서 안정적으로 실행됩니다</string>
<string name="battery_optimization_benefits">• 신뢰할 수 있는 메시지 전달\n• 메쉬 연결 유지\n• 백그라운드 메시지 릴레이\n• 연결 끊김 방지</string>
<string name="battery_optimization_check_again">다시 확인</string>
<string name="battery_optimization_skip">지금 건너뛰기</string>
<string name="battery_optimization_continue">계속</string>
<string name="retry">다시 시도</string>
<string name="skip">건너뛰기</string>
<!-- 알림 -->
<string name="notification_summary_more">그리고 %1$d개 더</string>
<string name="notification_messages_from_people">%2$d명에게서 %1$d개의 메시지</string>
<string name="notification_more_conversations">그리고 %1$d개의 대화 더</string>
<string name="notification_active_peers_title">👥 근처 bitchatter!</string>
<string name="notification_active_peers_one">근처 1명</string>
<string name="notification_active_peers_many">근처 %1$d명</string>
<string name="notification_new_messages">새 메시지</string>
<string name="notification_new_location_messages">새 위치 메시지</string>
<string name="notification_mentions_in">%1$s에서 언급됨</string>
<string name="notification_mentions_in_more">%1$s에서 언급됨 (+%2$d)</string>
<string name="notification_mentions_in_plural">%2$s에서 %1$d회 언급</string>
<string name="notification_new_activity_in">%1$s의 새 활동</string>
<string name="notification_messages_in">%1$s의 메시지</string>
<string name="notification_joined_conversation">%1$s님이 대화에 참여했습니다</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d회 언급</string>
<string name="notification_geohash_summary_title">bitchat 위치 채팅</string>
<string name="notification_geohash_summary_text">%2$d개의 장소에서 온 %1$d개의 메시지</string>
<string name="notification_mesh_mention_title_singular">메쉬 채팅에서 언급됨</string>
<string name="notification_mesh_mention_title_plural">메쉬 채팅에서 %1$d회 언급</string>
<string name="notification_more_locations">그리고 %1$d개의 장소 더</string>
<string name="notification_and_more">그리고 %1$d개 더</string>
<!-- 즐겨찾기 접근성 -->
<string name="cd_add_favorite">즐겨찾기에 추가</string>
<string name="cd_remove_favorite">즐겨찾기에서 제거</string>
<string name="cd_add_bookmark">북마크 추가</string>
<!-- 채팅 헤더 & 접근성 -->
<string name="chat_back">뒤로</string>
<string name="chat_channel_prefix">채널: %1$s</string>
<string name="chat_leave">나가기</string>
<string name="cd_nostr_reachable">Nostr로 연결 가능</string>
<string name="cd_unread_private_messages">읽지 않은 개인 메시지</string>
<string name="cd_toggle_bookmark">북마크 전환</string>
<string name="cd_teleported">텔레포트됨</string>
<string name="cd_tor_status">Tor 상태</string>
<string name="cd_connected_peers">연결된 피어</string>
<string name="cd_geohash_participants">geohash 참여자</string>
<string name="cd_ready_for_handshake">핸드셰이크 준비됨</string>
<string name="cd_handshake_in_progress">핸드셰이크 진행 중</string>
<string name="cd_encrypted">종단간 암호화</string>
<string name="cd_handshake_failed">핸드셰이크 실패</string>
<!-- 파일 뷰어 대화상자 -->
<string name="file_viewer_title">📎 파일 수신</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 크기: %1$s</string>
<string name="file_viewer_type">🏷️ 유형: %1$s</string>
<string name="file_viewer_open_save">📂 열기 / 저장</string>
<string name="close_with_emoji">❌ 닫기</string>
<string name="pick_image">이미지 선택</string>
<!-- 정보 시트 -->
<string name="about_tagline">종단간 암호화를 갖춘 탈중앙 메쉬 채팅</string>
<string name="about_offline_mesh_title">오프라인 메쉬 채팅</string>
<string name="about_offline_mesh_desc">인터넷이나 서버 없이 Bluetooth LE로 직접 소통합니다. 범위를 확장하기 위해 근처 기기를 통해 메시지가 중계됩니다.</string>
<string name="about_online_geohash_title">온라인 geohash 채널</string>
<string name="about_online_geohash_desc">geohash 기반 채널을 통해 주변 사람들과 연결하세요. 공용 인터넷 릴레이로 메쉬를 확장합니다.</string>
<string name="about_e2e_title">종단간 암호화</string>
<string name="about_e2e_desc">개인 메시지는 암호화됩니다. 채널 메시지는 공개입니다.</string>
<string name="about_appearance">모양</string>
<string name="about_system">시스템</string>
<string name="about_light">라이트</string>
<string name="about_dark">다크</string>
<string name="about_pow">작업증명</string>
<string name="about_pow_off">PoW 끔</string>
<string name="about_pow_on">PoW 켬</string>
<string name="about_pow_tip">스팸을 어렵게 만들기 위해 geohash 메시지에 작업증명을 추가하세요.</string>
<string name="about_pow_difficulty">난이도: %1$d 비트 (~%2$s)</string>
<string name="about_pow_difficulty_attempts">난이도 %1$d는 ~%2$s 해시 시도가 필요합니다</string>
<string name="about_pow_desc_none">작업증명 필요 없음</string>
<string name="about_pow_desc_very_low">매우 낮음 최소 스팸 보호</string>
<string name="about_pow_desc_low">낮음 기본 스팸 보호</string>
<string name="about_pow_desc_medium">중간 좋은 스팸 보호</string>
<string name="about_pow_desc_high">높음 강한 스팸 보호</string>
<string name="about_pow_desc_very_high">매우 높음 – 지연이 발생할 수 있음</string>
<string name="about_pow_desc_extreme">매우 극단 – 상당한 연산 능력 필요</string>
<string name="about_network">네트워크</string>
<string name="about_tor_off">Tor 끔</string>
<string name="about_tor_on">Tor 켬</string>
<string name="about_tor_route">개인정보 보호를 위해 인터넷 트래픽을 Tor를 통해 라우팅합니다.</string>
<string name="about_tor_status">Tor 상태: %1$s, 부트스트랩 %2$d%%</string>
<string name="about_last">마지막: %1$s</string>
<string name="about_emergency_title">긴급 데이터 삭제</string>
<string name="about_emergency_tip">팁: 저장된 모든 데이터(메시지, 키, 설정 포함)를 삭제하려면 앱 제목을 세 번 탭하세요.</string>
<string name="about_debug_settings">디버그 설정</string>
<string name="about_footer">오픈 소스 • 프라이버시 우선 • 탈중앙</string>
<string name="close_plain">닫기</string>
<string name="cancel_lower">취소</string>
<!-- 일반 콘텐츠 설명 -->
<string name="cd_warning">경고</string>
<string name="cd_location_services">위치 서비스</string>
<string name="cd_privacy">개인정보</string>
<string name="cd_error">오류</string>
<string name="cd_battery_optimization">배터리 최적화</string>
<string name="cd_benefits">이점</string>
<string name="cd_checking_battery_optimization">배터리 최적화 확인 중</string>
<string name="cd_not_supported_battery_optimization">배터리 최적화 미지원</string>
<string name="cd_bluetooth">블루투스</string>
<string name="cd_unread_message">읽지 않은 메시지</string>
<string name="cd_open_map">지도 열기</string>
<string name="cd_remove_bookmark">북마크 제거</string>
<string name="cd_teleport">텔레포트</string>
<string name="cd_selected">선택됨</string>
<string name="cd_leave_channel">채널 나가기</string>
<string name="cd_reachable_via_nostr">Nostr로 연결 가능</string>
<string name="cd_offline_favorite">즐겨찾기 (오프라인)</string>
<string name="cd_decrease_precision">정밀도 낮추기</string>
<string name="cd_increase_precision">정밀도 높이기</string>
<string name="cd_select_geohash">geohash 선택</string>
<string name="cd_scroll_to_bottom">아래로 스크롤</string>
<string name="cd_file">파일</string>
<string name="cd_image">이미지</string>
<string name="cd_cancel">취소</string>
<string name="cd_link">링크</string>
<string name="cd_pick_media">미디어 선택</string>
<string name="cd_pick_file">파일 선택</string>
<string name="cd_save_current_image">현재 이미지 저장</string>
<string name="cd_close">닫기</string>
<string name="cd_image_index_of">이미지 %1$d / %2$d</string>
<string name="cd_privacy_protected">개인정보 보호됨</string>
<string name="cd_record_voice">음성 메시지 녹음</string>
<string name="cd_offline_mesh_chat">오프라인 메쉬 채팅</string>
<string name="cd_online_geohash_channels">온라인 geohash 채널</string>
<string name="cd_end_to_end_encryption">종단간 암호화</string>
<!-- 이미지 & 파일 -->
<string name="image_page_of">이미지 %1$d / %2$d</string>
<string name="image_unavailable">이미지를 사용할 수 없음</string>
<string name="image_saved_to_downloads">이미지가 \"Downloads\"에 저장됨</string>
<string name="image_save_failed">이미지를 저장하지 못했습니다</string>
<string name="toast_image_saved">이미지가 \"Downloads\"에 저장됨</string>
<string name="toast_failed_to_save_image">이미지를 저장하지 못했습니다</string>
<string name="pick_file">파일 선택</string>
<string name="file_unavailable">[파일을 사용할 수 없음]</string>
<string name="unknown">알 수 없음</string>
<!-- 사용자 작업 시트 -->
<string name="choose_action_message_or_user">이 메시지 또는 사용자에 대한 동작 선택</string>
<string name="choose_action_user">이 사용자에 대한 동작 선택</string>
<string name="action_copy_message_title">메시지 복사</string>
<string name="action_copy_message_subtitle">이 메시지를 클립보드에 복사</string>
<string name="action_slap_title">%1$s를 때리기</string>
<string name="action_slap_subtitle">장난스러운 따귀 보내기</string>
<string name="action_hug_title">%1$s를 안기</string>
<string name="action_hug_subtitle">친근한 포옹 보내기</string>
<string name="action_block_title">%1$s 차단</string>
<string name="action_block_subtitle">이 사용자의 모든 메시지 차단</string>
<!-- geohash 채널 시트 -->
<string name="location_channels_title">#위치 채널</string>
<string name="location_channels_desc">geohash 채널을 통해 주변 사람들과 채팅하세요. 정확한 GPS 데이터가 아닌 대략적인 geohash만 공유됩니다. 개인 정보 보호를 위해 이 화면을 스크린샷하거나 공유하지 마세요.</string>
<string name="grant_location_permission">위치 권한 허용</string>
<string name="location_permission_denied">위치 권한이 거부되었습니다. 위치 채널을 사용하려면 설정에서 활성화하세요.</string>
<string name="open_settings">설정 열기</string>
<string name="location_permission_granted">\u2713 위치 권한 허용됨</string>
<string name="checking_permissions">권한 확인 중 …</string>
<string name="finding_nearby_channels">주변 채널 찾는 중 …</string>
<string name="bookmarked">북마크됨</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">유효하지 않은 geohash</string>
<string name="teleport">텔레포트</string>
<string name="disable_location_services">위치 서비스 비활성화</string>
<string name="enable_location_services">위치 서비스 활성화</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">블록</string>
<string name="location_level_neighborhood">이웃</string>
<string name="location_level_city">도시</string>
<string name="location_level_province">주/도</string>
<string name="location_level_region">지역</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- 디버그 / 진단 -->
<string name="debug_tools">디버그 도구</string>
<string name="debug_tools_desc">진단 및 제어를 위한 개발자 도구</string>
<string name="debug_verbose_logging">상세 로깅</string>
<string name="debug_verbose_hint">피어 참여/이탈, 연결 방향, 패킷 전달 및 릴레이를 기록합니다</string>
<string name="debug_bluetooth_roles">블루투스 역할</string>
<string name="debug_gatt_server">GATT 서버</string>
<string name="debug_connections_fmt">연결: %1$d / %2$d</string>
<string name="debug_max_server">최대 서버</string>
<string name="debug_gatt_client">GATT 클라이언트</string>
<string name="debug_max_client">최대 클라이언트</string>
<string name="debug_overall_connections_fmt">연결: %1$d / %2$d</string>
<string name="debug_max_overall">총 최대</string>
<string name="debug_packet_relay">패킷 릴레이</string>
<string name="debug_since_start_fmt">시작 이후: %1$d</string>
<string name="debug_roles_hint">역할을 켜고/끄고 비활성화 시 모든 연결 닫기</string>
<string name="debug_sync_settings">동기화 설정</string>
<string name="debug_max_packets_per_sync_fmt">동기화당 최대 패킷: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">최대 GCS 필터 크기: %1$d Byte (1281024)</string>
<string name="debug_target_fpr_fmt">목표 FPR: %1$.2f%%</string>
<string name="debug_connected_devices">연결된 장치</string>
<string name="debug_our_device_id_fmt">우리 장치 ID: %1$s</string>
<string name="debug_none">없음</string>
<string name="debug_disconnect">연결 해제</string>
<string name="debug_recent_scan_results">최근 스캔된 장치</string>
<string name="debug_connect">연결</string>
<string name="debug_debug_console">디버그 콘솔</string>
<string name="debug_clear">지우기</string>
<string name="debug_relays_window_fmt">마지막 10초: %1$d • 1분: %2$d • 15분: %3$d</string>
<string name="debug_derived_p_fmt">유도 P: %1$s • 예상 최대 요소: %2$s</string>
<string name="debug_direct_suffix"> • 직접</string>
<string name="debug_role_server">서버로서 (우리가 호스트)</string>
<string name="debug_role_client">클라이언트로서 (우리가 연결)</string>
<!-- 온보딩 화면 -->
<string name="location_services_required">위치 서비스 필요</string>
<string name="privacy_first">개인정보 우선</string>
<string name="location_explanation">bitchat은 사용자의 위치를 추적하지 않습니다.\n\n블루투스 스캔 및 geohash 채팅 기능에 위치 서비스가 필요합니다.</string>
<string name="location_needs_for">bitchat은 다음을 위해 위치 서비스가 필요합니다:</string>
<string name="location_needs_bullets">• 블루투스 기기 스캔\n• 메쉬 네트워크에서 근처 사용자 발견\n• geohash 채팅 기능\n• 추적 또는 위치 수집 없음</string>
<string name="open_location_settings">위치 설정 열기</string>
<string name="check_again">다시 확인</string>
<string name="location_services_unavailable">위치 서비스를 사용할 수 없음</string>
<string name="location_unavailable_explanation">이 기기에서는 위치 서비스를 사용할 수 없습니다. Android 기기에서 위치 서비스는 표준이므로 이는 드문 경우입니다.\n\n블루투스 스캔이 제대로 작동하려면 bitchat에 위치 서비스가 필요합니다(Android 요구 사항). 그렇지 않으면 앱이 주변 사용자를 찾지 못합니다.</string>
<string name="checking_location_services">위치 서비스 확인 중 …</string>
<string name="bluetooth_required">블루투스 필요</string>
<string name="bluetooth_needs_for">bitchat은 다음을 위해 블루투스가 필요합니다:</string>
<string name="bluetooth_needs_bullets">• 근처 사용자 찾기\n• 메쉬 네트워크 연결 생성\n• 메시지 보내고 받기\n• 인터넷이나 서버 없이 작동</string>
<string name="enable_bluetooth">블루투스 켜기</string>
<string name="bluetooth_not_supported">블루투스 미지원</string>
<string name="bluetooth_unsupported_explanation">이 기기는 bitchat이 동작하는 데 필요한 Bluetooth Low Energy (BLE)를 지원하지 않습니다.\n\nbitchat은 인터넷 없이 근처 장치와 통신하고 메쉬 네트워크를 생성하기 위해 BLE가 필요합니다.</string>
<string name="checking_bluetooth_status">블루투스 상태 확인 중 …</string>
<string name="battery_optimization_detected_title">배터리 최적화 감지됨</string>
<string name="battery_optimization_enabled_title">배터리 최적화 활성화됨</string>
<string name="battery_optimization_explanation_short">메쉬 연결을 유지하려면 bitchat이 백그라운드에서 실행되어야 합니다. 배터리 최적화는 이러한 연결을 방해할 수 있습니다.</string>
<string name="benefits_of_disabling">비활성화의 이점</string>
<string name="battery_benefits_short">• 신뢰할 수 있는 메시지 전달\n• 메쉬 연결 유지\n• 연결 끊김 방지</string>
<string name="disable_battery_optimization">배터리 최적화 끄기</string>
<string name="battery_optimization_disabled_title">배터리 최적화 비활성화됨</string>
<string name="continue_btn">계속</string>
<string name="initializing_mesh_network">메쉬 네트워크 초기화 중</string>
<string name="setting_up_bluetooth">블루투스 메쉬 네트워크 설정 중 …</string>
<string name="should_take_seconds">몇 초 정도 소요됩니다</string>
<string name="setup_not_complete">설정이 완료되지 않았습니다</string>
<string name="try_again">다시 시도</string>
<string name="privacy_protected">개인정보가 보호됩니다</string>
<string name="privacy_bullets">• 추적 또는 데이터 수집 없음\n• 블루투스 메쉬 채팅은 완전 오프라인\n• geohash 채팅은 인터넷 사용</string>
<string name="permissions_header">권한</string>
<string name="grant_permissions">권한 허용</string>
<string name="location_tracking_warning">bitchat은 사용자의 위치를 추적하지 않습니다</string>
<string name="geohash_people_header">사람들</string>
<string name="nobody_around">주변에 아무도 없음 …</string>
<string name="you_suffix"> (나)</string>
<string name="pan_zoom_instruction">geohash를 선택하려면 이동하고 확대/축소하세요</string>
<string name="select">선택</string>
<string name="type_a_message_placeholder">메시지 입력 …</string>
<string name="mention">멘션</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">이미지</string>
<string name="media_type_file">파일</string>
<!-- 알림 텍스트 도우미 -->
<string name="notification_sent_image">📷 이미지 보냄</string>
<string name="notification_sent_voice">🎤 음성 메시지 보냄</string>
<string name="notification_sent_file">📎 파일 보냄</string>
<!-- 음성 플레이어 접근성 -->
<string name="cd_play_voice">재생</string>
<string name="cd_pause_voice">일시정지</string>
<string name="cd_mining_pow">PoW 채굴</string>
<string name="cd_pow_enabled">PoW 사용</string>
<string name="cd_proof_of_work">작업증명</string>
<string name="pow_mining_ellipsis">채굴 중 …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- 권한 설명 -->
<string name="perm_nearby_devices_desc">블루투스를 통해 bitchat 사용자를 발견하는 데 필요</string>
<string name="perm_nearby_devices_system">근처 기기와 연결하도록 bitchat을 허용</string>
<string name="perm_location_desc">블루투스를 통해 근처 bitchat 사용자를 찾기 위해 Android에 필요</string>
<string name="perm_location_system">근처 기기를 스캔하려면 bitchat에 필요</string>
<string name="perm_notifications_desc">개인 메시지를 받으면 알림 받기</string>
<string name="perm_notifications_system">bitchat이 알림을 보내도록 허용</string>
<string name="perm_battery_desc">bitchat이 백그라운드에서 안정적으로 실행되고 메쉬 연결을 유지하도록 배터리 최적화를 끄세요</string>
<string name="perm_battery_system">배터리 제한 없이 실행하도록 bitchat을 허용</string>
<!-- 권한 유형 -->
<string name="perm_type_nearby_devices">근처 기기</string>
<string name="perm_type_precise_location">정확한 위치</string>
<string name="perm_type_microphone">마이크</string>
<string name="perm_type_notifications">알림</string>
<string name="perm_type_battery_optimization">배터리 최적화</string>
<string name="perm_type_other">기타</string>
<!-- 비밀번호 대화상자 -->
<string name="pwd_prompt_title">채널 비밀번호 입력</string>
<string name="pwd_prompt_message">채널 %1$s은 비밀번호로 보호됩니다. 참여하려면 비밀번호를 입력하세요.</string>
<string name="pwd_label">비밀번호</string>
<string name="join">참가</string>
<string name="cancel">취소</string>
<!-- 복수형 -->
<plurals name="notification_and_more">
<item quantity="one">그리고 %d개 더</item>
<item quantity="other">그리고 %d개 더</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1명</item>
<item quantity="other">%d명</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d개의 노트</item>
<item quantity="other">#%1$s ± 1 • %2$d개의 노트</item>
</plurals>
<string name="location_notes_description">다른 방문자들이 볼 수 있도록 이 위치에 짧은 영구 노트를 추가하세요.</string>
<string name="location_notes_relays_unavailable">지오 릴레이를 사용할 수 없음; 노트 일시 중지됨</string>
<string name="location_notes_no_relays_title">주변에 지오 릴레이가 없음</string>
<string name="location_notes_no_relays_desc">노트는 지오 릴레이에 의존합니다. 연결을 확인하고 다시 시도하세요.</string>
<string name="loading_location_notes">노트 불러오는 중…</string>
<string name="location_notes_empty_title">아직 노트가 없습니다</string>
<string name="location_notes_empty_desc">이 장소에 첫 번째 노트를 추가해 보세요.</string>
<string name="dismiss">닫기</string>
<string name="location_notes_input_placeholder">이 장소에 노트 추가</string>
</resources>
+379
View File
@@ -0,0 +1,379 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Fanazavana momba ny alalana -->
<string name="permission_bluetooth_rationale">Ilaina ny alalana Bluetooth mba hifandraisan-davitra tsy misy Internet.</string>
<string name="permission_location_rationale">Ilaina ny alalana momba ny toerana mba hahitana fitaovana akaiky amin\'ny alalan\'ny Bluetooth.</string>
<string name="permission_notification_rationale">Ilaina ny alalana fampandrenesana mba hampandre anao rehefa misy hafatra vaovao.</string>
<!-- Soso-kevitra / UI fototra -->
<string name="nickname_hint">anarana kely</string>
<string name="message_hint">soraty hafatra…</string>
<string name="channel_password_hint">Teny miafina</string>
<string name="join_channel">Hiditra amin\'ny fantsona</string>
<string name="leave_channel">Hiala</string>
<string name="send_message">Handefa</string>
<string name="show_commands">Haneho baiko</string>
<string name="back">Hiverina</string>
<string name="people">Olona</string>
<string name="channels">Fantsona</string>
<string name="online_users">Mpampiasa an-tserasera</string>
<string name="no_one_connected">Tsy misy olona mifandray</string>
<string name="emergency_clear_hint">Tsindrio in-telo mba hamafana ny angona rehetra</string>
<string name="your_network">Tambazotry</string>
<!-- Fanamafisana bateria -->
<string name="battery_optimization_detected">Hita ny Fanamafisana Bateria</string>
<string name="battery_optimization_disabled">Najanona ny Fanamafisana Bateria</string>
<string name="battery_optimization_not_required">Tsy ilaina ny Fanamafisana Bateria</string>
<string name="battery_optimization_checking">Manamarina ny Fanamafisana Bateria</string>
<string name="battery_optimization_why_disable">Nahoana no mijanona ny fanamafisana bateria?</string>
<string name="battery_optimization_explanation">Mihazakazaka ao ambadika ny bitchat mba hitazona ny fifandraisana tambazotry mesh amin\'ny fitaovana akaiky. Ny fanamafisana bateria dia afaka manelingelina ireo fifandraisana ireo, ka mahatonga ny hafatra hataran-tara na very.\n\nNy fanajanona ny fanamafisana bateria dia miantoka ny fifandraisan-davitra azo itokisana.</string>
<string name="battery_optimization_disable_button">Hajanona ny Fanamafisana Bateria</string>
<string name="battery_optimization_note">Fanamarihana: Azonao ovaina ato aoriana izany amin\'ny Toetry Android &gt; Apps &gt; bitchat &gt; Bateria</string>
<string name="battery_optimization_not_supported_explanation">Ny fitaovanao dia tsy mila fametrahana fanamafisana bateria. Ny bitchat dia handeha ara-dalàna.</string>
<string name="battery_optimization_not_supported_message">Ny fitaovanao dia tsy mila fametrahana fanamafisana bateria. Ny bitchat dia handeha ara-dalàna.</string>
<string name="battery_optimization_success_message">Afaka mihazakazaka azo itokisana ao ambadika ny bitchat</string>
<string name="battery_optimization_benefits">• Miantoka ny fandefasana hafatra azo itokisana\n• Mitazona ny fifandraisana tambazotry mesh\n• Mamela ny famindrana hafatra ao ambadika\n• Misoroka ny fahatapahan\'ny fifandraisana</string>
<string name="battery_optimization_check_again">Hanamarina indray</string>
<string name="battery_optimization_skip">Hitsambikina ankehitriny</string>
<string name="battery_optimization_continue">Hanohy</string>
<string name="retry">Hanandrana indray</string>
<string name="skip">Hitsambikina</string>
<!-- Fampandrenesana -->
<string name="notification_summary_more">ary %1$d hafa</string>
<string name="notification_messages_from_people">%1$d hafatra avy amin\'ny olona %2$d</string>
<string name="notification_more_conversations">ary %1$d resaka hafa</string>
<string name="notification_active_peers_title">👥 bitchatter akaiky!</string>
<string name="notification_active_peers_one">Olona 1 manodidina</string>
<string name="notification_active_peers_many">Olona %1$d manodidina</string>
<string name="notification_new_messages">Hafatra vaovao</string>
<string name="notification_new_location_messages">Hafatra Toerana Vaovao</string>
<string name="notification_mentions_in">Voatonona ao amin\'ny %1$s</string>
<string name="notification_mentions_in_more">Voatonona ao amin\'ny %1$s (+%2$d hafa)</string>
<string name="notification_mentions_in_plural">%1$d fanaovana tsiahy ao amin\'ny %2$s</string>
<string name="notification_new_activity_in">Hetsika vaovao ao amin\'ny %1$s</string>
<string name="notification_messages_in">Hafatra ao amin\'ny %1$s</string>
<string name="notification_joined_conversation">%1$s dia niditra tamin\'ny resaka</string>
<string name="notification_geohash_summary_title_mentions">bitchat - %1$d fanaovana tsiahy</string>
<string name="notification_geohash_summary_title">bitchat - resaka toerana</string>
<string name="notification_geohash_summary_text">%1$d hafatra avy amin\'ny toerana %2$d</string>
<string name="notification_mesh_mention_title_singular">Voatonona ao amin\'ny Mesh Chat</string>
<string name="notification_mesh_mention_title_plural">%1$d fanaovana tsiahy ao amin\'ny Mesh Chat</string>
<string name="notification_more_locations">ary %1$d toerana hafa</string>
<string name="notification_and_more">ary %1$d hafa</string>
<!-- Fahafinaretana momba ny ankafizina -->
<string name="cd_add_favorite">Hampidirina amin\'ny ankafizina</string>
<string name="cd_remove_favorite">Hanesorana amin\'ny ankafizina</string>
<string name="cd_add_bookmark">Hanampy bookmark</string>
<!-- Lohan\'ny resaka & fahafaha-miditra -->
<string name="chat_back">miverina</string>
<string name="chat_channel_prefix">fantsona: %1$s</string>
<string name="chat_leave">hiala</string>
<string name="cd_nostr_reachable">Azo tratrarina amin\'ny alalan\'ny Nostr</string>
<string name="cd_unread_private_messages">Hafatra manokana tsy voavaky</string>
<string name="cd_toggle_bookmark">Hanova bookmark</string>
<string name="cd_teleported">Nafindra toerana</string>
<string name="cd_tor_status">Toe-javatra Tor</string>
<string name="cd_connected_peers">Mpiara-miasa mifandray</string>
<string name="cd_geohash_participants">Mpandray anjara Geohash</string>
<string name="cd_ready_for_handshake">Vonona ho amin\'ny fifampiraharahana</string>
<string name="cd_handshake_in_progress">Fifampiraharahana mandeha eo</string>
<string name="cd_encrypted">Voafono farany amin\'ny farany</string>
<string name="cd_handshake_failed">Tsy nahomby ny fifampiraharahana</string>
<!-- Fifanakalozan-dresaka momba ny rakitra -->
<string name="file_viewer_title">📎 Rakitra Voaray</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Habeny: %1$s</string>
<string name="file_viewer_type">🏷️ Karazana: %1$s</string>
<string name="file_viewer_open_save">📂 Hanokatra / Hitahiry</string>
<string name="close_with_emoji">❌ Hanakatona</string>
<string name="pick_image">Hifidy sary</string>
<!-- Momba ny takelaka -->
<string name="about_tagline">hafatra mesh tsy misy foibe misy fandokoana farany amin\'ny farany</string>
<string name="about_offline_mesh_title">Mesh Chat tsy an-tserasera</string>
<string name="about_offline_mesh_desc">Mifandraisa mivantana amin\'ny alalan\'ny Bluetooth LE tsy misy Internet na mpizara. Ny hafatra dia mamindra amin\'ny alalan\'ny fitaovana akaiky mba hanitarana ny elanelana.</string>
<string name="about_online_geohash_title">Fantsona Geohash an-tserasera</string>
<string name="about_online_geohash_desc">Mifandray amin\'ny olona eo amin\'ny faritra misy anao amin\'ny fampiasana fantsona mifototra amin\'ny geohash. Manitatra ny mesh amin\'ny fampiasana relay Internet ho an\'ny daholobe.</string>
<string name="about_e2e_title">Fandokoana Farany amin\'ny Farany</string>
<string name="about_e2e_desc">Voafono ny hafatra manokana. Hafatra ho an\'ny daholobe ny hafatra fantsona.</string>
<string name="about_appearance">endrika</string>
<string name="about_system">rafitra</string>
<string name="about_light">mazava</string>
<string name="about_dark">maizina</string>
<string name="about_pow">porofo asa</string>
<string name="about_pow_off">pow tapaka</string>
<string name="about_pow_on">pow mandeha</string>
<string name="about_pow_tip">ampio porofo asa amin\'ny hafatra geohash mba hanakanana spam.</string>
<string name="about_pow_difficulty">sarotra: %1$d bit (~%2$s)</string>
<string name="about_pow_difficulty_attempts">sarotra %1$d mitaky ~%2$s fanandramana hash</string>
<string name="about_pow_desc_none">tsy misy porofo asa ilaina</string>
<string name="about_pow_desc_very_low">ambany indrindra - fiarovana spam kely</string>
<string name="about_pow_desc_low">ambany - fiarovana spam fototra</string>
<string name="about_pow_desc_medium">antonony - fiarovana spam tsara</string>
<string name="about_pow_desc_high">avo - fiarovana spam matanjaka</string>
<string name="about_pow_desc_very_high">avo dia avo - mety miteraka fahatarana</string>
<string name="about_pow_desc_extreme">faran\'izany - mitaky kajy lehibe</string>
<string name="about_network">tambazotry</string>
<string name="about_tor_off">tor tapaka</string>
<string name="about_tor_on">tor mandeha</string>
<string name="about_tor_route">alefaso amin\'ny alalan\'ny tor ny Internet mba hahazoana fiainana manokana bebe kokoa.</string>
<string name="about_tor_status">Toe-javatra Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Farany: %1$s</string>
<string name="about_emergency_title">Famafana Angona Maika</string>
<string name="about_emergency_tip">Toro-hevitra: Tsindrio in-telo ny anaran\'ny fampiharana mba hamafana maika ny angona rehetra voatahiry ao anatin\'izany ny hafatra, ny lakile ary ny fametrahana.</string>
<string name="about_debug_settings">Fametrahana Debug</string>
<string name="about_footer">Loharanom-baovao misokatra • Fiainana manokana voalohany • Tsy misy foibe</string>
<string name="close_plain">Hanakatona</string>
<string name="cancel_lower">hanafoana</string>
<!-- Famaritana votoaty ankapobeny -->
<string name="cd_warning">Fampitandremana</string>
<string name="cd_location_services">Sampan-draharaham-pitoerana</string>
<string name="cd_privacy">Fiainana manokana</string>
<string name="cd_error">Hadisoana</string>
<string name="cd_battery_optimization">Fanamafisana Bateria</string>
<string name="cd_benefits">Tombontsoa</string>
<string name="cd_checking_battery_optimization">Manamarina ny Fanamafisana Bateria</string>
<string name="cd_not_supported_battery_optimization">Tsy tohanana ny Fanamafisana Bateria</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Hafatra tsy voavaky</string>
<string name="cd_open_map">Hanokatra sarintany</string>
<string name="cd_remove_bookmark">Hanesorana bookmark</string>
<string name="cd_teleport">Hamindra toerana</string>
<string name="cd_selected">Voafidy</string>
<string name="cd_leave_channel">Hiala amin\'ny fantsona</string>
<string name="cd_reachable_via_nostr">Azo tratrarina amin\'ny alalan\'ny Nostr</string>
<string name="cd_offline_favorite">Ankafizina tsy an-tserasera</string>
<string name="cd_decrease_precision">Hampihenana ny fahamarinana</string>
<string name="cd_increase_precision">Hampitombo ny fahamarinana</string>
<string name="cd_select_geohash">Hifidy geohash</string>
<string name="cd_scroll_to_bottom">Hidina any ambany</string>
<string name="cd_file">Rakitra</string>
<string name="cd_image">Sary</string>
<string name="cd_cancel">Hanafoana</string>
<string name="cd_link">Rohy</string>
<string name="cd_pick_media">Hifidy media</string>
<string name="cd_pick_file">Hifidy rakitra</string>
<string name="cd_save_current_image">Hitahiry ny sary ankehitriny</string>
<string name="cd_close">Hanakatona</string>
<string name="cd_image_index_of">Sary %1$d amin\'ny %2$d</string>
<string name="cd_privacy_protected">Voaaro ny Fiainana Manokana</string>
<string name="cd_record_voice">Handrakitra feo</string>
<string name="cd_offline_mesh_chat">Mesh Chat tsy an-tserasera</string>
<string name="cd_online_geohash_channels">Fantsona Geohash an-tserasera</string>
<string name="cd_end_to_end_encryption">Fandokoana Farany amin\'ny Farany</string>
<!-- Sary & rakitra -->
<string name="image_page_of">Sary %1$d amin\'ny %2$d</string>
<string name="image_unavailable">Tsy misy sary</string>
<string name="image_saved_to_downloads">Sary voatahiry ao amin\'ny Downloads</string>
<string name="image_save_failed">Tsy afaka mitahiry sary</string>
<string name="toast_image_saved">Sary voatahiry ao amin\'ny Downloads</string>
<string name="toast_failed_to_save_image">Tsy afaka mitahiry sary</string>
<string name="pick_file">Hifidy rakitra</string>
<string name="file_unavailable">[rakitra tsy misy]</string>
<string name="unknown">tsy fantatra</string>
<!-- Takelaka hetsika mpampiasa -->
<string name="choose_action_message_or_user">safidio hetsika ho an\'ity hafatra na mpampiasa ity</string>
<string name="choose_action_user">safidio hetsika ho an\'ity mpampiasa ity</string>
<string name="action_copy_message_title">adikao ny hafatra</string>
<string name="action_copy_message_subtitle">adikao ity hafatra ity any amin\'ny clipboard</string>
<string name="action_slap_title">kapohina %1$s</string>
<string name="action_slap_subtitle">handefasa hafatra kapohana an-dalao</string>
<string name="action_hug_title">honofinofy %1$s</string>
<string name="action_hug_subtitle">handefasa hafatra honofinofy sariaka</string>
<string name="action_block_title">hanorina %1$s</string>
<string name="action_block_subtitle">hanorina ny hafatra rehetra avy amin\'ity mpampiasa ity</string>
<!-- Takelaka fantsona toerana -->
<string name="location_channels_title">#fantsona toerana</string>
<string name="location_channels_desc">miresaka amin\'ny olona akaiky anao amin\'ny fampiasana fantsona geohash. geohash marivo ihany no zarainy, tsy GPS marina akory. aza maka sary an-efijery na mizara ity efijery ity mba hiarovana ny fiainanao manokana.</string>
<string name="grant_location_permission">omeo alalana momba ny toerana</string>
<string name="location_permission_denied">nolavina ny alalana momba ny toerana. alefaso ao amin\'ny fametrahana mba hampiasa fantsona toerana.</string>
<string name="open_settings">Hanokatra fametrahana</string>
<string name="location_permission_granted">\u2713 omena ny alalana momba ny toerana</string>
<string name="checking_permissions">manamarina ny alalana...</string>
<string name="finding_nearby_channels">mitady fantsona akaiky…</string>
<string name="bookmarked">voaisy bookmark</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">geohash tsy mety</string>
<string name="teleport">hamindra toerana</string>
<string name="disable_location_services">hanajanona sampan-draharaham-pitoerana</string>
<string name="enable_location_services">halefa sampan-draharaham-pitoerana</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">sakana</string>
<string name="location_level_neighborhood">manodidina</string>
<string name="location_level_city">tanàna</string>
<string name="location_level_province">faritany</string>
<string name="location_level_region">faritra</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnostika -->
<string name="debug_tools">fitaovana debug</string>
<string name="debug_tools_desc">fitaovana mpamorona ho an\'ny diagnostika sy fifehezana</string>
<string name="debug_verbose_logging">firaketana amin\'ny antsipiriany</string>
<string name="debug_verbose_hint">raketo ny fidiran\'ny mpiara-miasa / ny fialana, ny fanolorana fifandraisana, ny routing pakets ary ny relays</string>
<string name="debug_bluetooth_roles">andraikitry Bluetooth</string>
<string name="debug_gatt_server">mpizara GATT</string>
<string name="debug_connections_fmt">fifandraisana: %1$d / %2$d</string>
<string name="debug_max_server">mpizara max</string>
<string name="debug_gatt_client">mpanjifa GATT</string>
<string name="debug_max_client">mpanjifa max</string>
<string name="debug_overall_connections_fmt">fifandraisana: %1$d / %2$d</string>
<string name="debug_max_overall">max ankapobeny</string>
<string name="debug_packet_relay">relay pakets</string>
<string name="debug_since_start_fmt">hatramin\'ny fanombohana: %1$d</string>
<string name="debug_roles_hint">alefaso / tapaho ny andraikitra ary akatony ny fifandraisana rehetra rehefa tapaka</string>
<string name="debug_sync_settings">fametrahana sync</string>
<string name="debug_max_packets_per_sync_fmt">pakets max isaky ny sync: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">haben\'ny sivana GCS max: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">FPR kendrena: %1$.2f%%</string>
<string name="debug_connected_devices">fitaovana mifandray</string>
<string name="debug_our_device_id_fmt">ID fitaovanay: %1$s</string>
<string name="debug_none">tsy misy</string>
<string name="debug_disconnect">hisaraka</string>
<string name="debug_recent_scan_results">valim-panadihadiana vao haingana</string>
<string name="debug_connect">hifandray</string>
<string name="debug_debug_console">console debug</string>
<string name="debug_clear">hamafa</string>
<string name="debug_relays_window_fmt">10s farany: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P azo: %1$s • tombana singa max: %2$s</string>
<string name="debug_direct_suffix"> • mivantana</string>
<string name="debug_role_server">ho mpizara (isika mampiantrano)</string>
<string name="debug_role_client">ho mpanjifa (isika mifandray)</string>
<!-- Efijery fanombohana -->
<string name="location_services_required">Ilaina ny Sampan-draharaham-pitoerana</string>
<string name="privacy_first">Fiainana Manokana Voalohany</string>
<string name="location_explanation">Ny bitchat dia TSY manaraka ny toerananao.\n\nIlaina ny sampan-draharaham-pitoerana ho an\'ny scan Bluetooth sy ny endri-javatra resaka Geohash.</string>
<string name="location_needs_for">Ny bitchat dia mila sampan-draharaham-pitoerana ho an\'ny:</string>
<string name="location_needs_bullets">• Scan fitaovana Bluetooth\n• Fahitana mpampiasa akaiky amin\'ny tambazotry mesh\n• Endri-javatra resaka Geohash\n• Tsy misy fanaraha-maso na fanangonana toerana</string>
<string name="open_location_settings">Hanokatra Fametrahana Toerana</string>
<string name="check_again">Hanamarina Indray</string>
<string name="location_services_unavailable">Tsy Misy Sampan-draharaham-pitoerana</string>
<string name="location_unavailable_explanation">Tsy misy sampan-draharaham-pitoerana amin\'ity fitaovana ity. Mahagaga izany satria mahazatra amin\'ny fitaovana Android ny sampan-draharaham-pitoerana.\n\nMila sampan-draharaham-pitoerana ny bitchat mba hiasa tsara ny scan Bluetooth (takiana Android). Raha tsy izany, ny fampiharana dia tsy afaka mahita mpampiasa akaiky.</string>
<string name="checking_location_services">Manamarina sampan-draharaham-pitoerana...</string>
<string name="bluetooth_required">Ilaina ny Bluetooth</string>
<string name="bluetooth_needs_for">Mila Bluetooth ny bitchat mba:</string>
<string name="bluetooth_needs_bullets">• Hahita mpampiasa akaiky\n• Hamorona fifandraisana tambazotry mesh\n• Handefa sy handray hafatra\n• Hiasa tsy misy Internet na mpizara</string>
<string name="enable_bluetooth">Alefaso ny Bluetooth</string>
<string name="bluetooth_not_supported">Tsy Tohanana ny Bluetooth</string>
<string name="bluetooth_unsupported_explanation">Ity fitaovana ity dia tsy manohana ny Bluetooth Low Energy (BLE), izay ilaina mba hiasan\'ny bitchat.\n\nMila BLE ny bitchat mba hamoronana tambazotry mesh sy hifandray amin\'ny fitaovana akaiky tsy misy Internet.</string>
<string name="checking_bluetooth_status">Manamarina ny toe-javatra Bluetooth...</string>
<string name="battery_optimization_detected_title">hita ny fanamafisana bateria</string>
<string name="battery_optimization_enabled_title">Alefa ny Fanamafisana Bateria</string>
<string name="battery_optimization_explanation_short">Mila mihazakazaka ao ambadika ny bitchat mba hitazona ny fifandraisana mesh. ny fanamafisana bateria dia afaka manelingelina ireo fifandraisana ireo.</string>
<string name="benefits_of_disabling">Tombontsoam-panajanona</string>
<string name="battery_benefits_short">• fandefasana hafatra azo itokisana\n• mitazona ny fifandraisana mesh\n• misoroka ny fahatapahan\'ny fifandraisana</string>
<string name="disable_battery_optimization">Hajanona ny Fanamafisana Bateria</string>
<string name="battery_optimization_disabled_title">najanona ny fanamafisana bateria</string>
<string name="continue_btn">Hanohy</string>
<string name="initializing_mesh_network">Manomboka ny tambazotry mesh</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">Mametraka ny tambazotry mesh Bluetooth...</string>
<string name="should_take_seconds">Tokony haharitra segaondra vitsivitsy ihany izany</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">Tsy Vita ny Fametrahana</string>
<string name="try_again">Andramo Indray</string>
<string name="privacy_protected">Voaaro ny Fiainanao Manokana</string>
<string name="privacy_bullets">• tsy misy fanaraha-maso na fanangonana angona\n• tsy an-tserasera tanteraka ny resaka mesh Bluetooth\n• mampiasa Internet ny resaka Geohash</string>
<string name="permissions_header">alalana</string>
<string name="grant_permissions">Omeo Alalana</string>
<string name="location_tracking_warning">Ny bitchat dia TSY manaraka ny toerananao</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">OLONA</string>
<string name="nobody_around">tsy misy olona manodidina...</string>
<string name="you_suffix"> (ianao)</string>
<string name="pan_zoom_instruction">ahetsika sy ataovy lehibe mba hifidianana geohash</string>
<string name="select">hifidy</string>
<string name="type_a_message_placeholder">soraty hafatra...</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">hanonona</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">Sary</string>
<string name="media_type_file">Rakitra</string>
<!-- Famantarana toe-javatra hafatra -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- Mpanampy lahatsoratra fampandrenesana -->
<string name="notification_sent_image">📷 nandefasa sary</string>
<string name="notification_sent_voice">🎤 nandefasa hafatra feo</string>
<string name="notification_sent_file">📎 nandefasa rakitra</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- Fahafaha-miditra mpilalao feo -->
<string name="cd_play_voice">Hilalao</string>
<string name="cd_pause_voice">Hijanona</string>
<string name="cd_mining_pow">Mihaingam-poana PoW</string>
<string name="cd_pow_enabled">Alefa ny PoW</string>
<string name="cd_proof_of_work">Porofo Asa</string>
<string name="pow_mining_ellipsis">mihaingana...</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Famaritana alalana -->
<string name="perm_nearby_devices_desc">Ilaina mba hahitana mpampiasa bitchat amin\'ny alalan\'ny Bluetooth</string>
<string name="perm_nearby_devices_system">Avelao ny bitchat hifandray amin\'ny fitaovana akaiky</string>
<string name="perm_location_desc">Takian\'ny Android mba hahitana mpampiasa bitchat akaiky amin\'ny alalan\'ny Bluetooth</string>
<string name="perm_location_system">Mila izany ny bitchat mba hisikidy fitaovana akaiky</string>
<string name="perm_notifications_desc">Mandray fampandrenesana rehefa mahazo hafatra manokana ianao</string>
<string name="perm_notifications_system">Avelao ny bitchat handefasa fampandrenesana aminao</string>
<string name="perm_battery_desc">Ajanony ny fanamafisana bateria mba hahazoana antoka fa mihazakazaka azo itokisana ao ambadika ny bitchat ary mitazona ny fifandraisana tambazotry mesh</string>
<string name="perm_battery_system">Avelao ny bitchat handeha tsy misy famerana bateria</string>
<!-- Karazana alalana -->
<string name="perm_type_nearby_devices">Fitaovana Akaiky</string>
<string name="perm_type_precise_location">Toerana Marina</string>
<string name="perm_type_microphone">Mikraofona</string>
<string name="perm_type_notifications">Fampandrenesana</string>
<string name="perm_type_battery_optimization">Fanamafisana Bateria</string>
<string name="perm_type_other">Hafa</string>
<!-- Fifanakalozan-dresaka fangatahana teny miafina -->
<string name="pwd_prompt_title">Ampidiro ny Teny Miafina Fantsona</string>
<string name="pwd_prompt_message">Voaaro amin\'ny teny miafina ny fantsona %1$s. Ampidiro ny teny miafina mba hidirana.</string>
<string name="pwd_label">Teny miafina</string>
<string name="join">Hiditra</string>
<string name="cancel">Hanafoana</string>
<!-- Plurals -->
<plurals name="notification_and_more">
<item quantity="one">ary %d hafa</item>
<item quantity="other">ary %d hafa</item>
</plurals>
<plurals name="people_count">
<item quantity="one">Olona 1</item>
<item quantity="other">Olona %d</item>
</plurals>
</resources>
+5
View File
@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- TODO: Malay translations -->
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- अनुमति कारणहरू -->
<string name="permission_bluetooth_rationale">इन्टरनेट बिना प्रत्यक्ष कुराकानीका लागि ब्लुटुथ अनुमति आवश्यक हुन्छ।</string>
<string name="permission_location_rationale">ब्लुटुथमार्फत नजिकका यन्त्रहरू फेला पार्न स्थान अनुमति आवश्यक हुन्छ।</string>
<string name="permission_notification_rationale">नयाँ सन्देशबारे सूचित गर्न सूचनाको अनुमति आवश्यक हुन्छ।</string>
<!-- Placeholder / आधार UI -->
<string name="nickname_hint">उपनाम</string>
<string name="message_hint">सन्देश टाइप गर्नुहोस्…</string>
<string name="channel_password_hint">पासवर्ड</string>
<string name="join_channel">च्यानलमा जोडिनुहोस्</string>
<string name="leave_channel">छोड्नुहोस्</string>
<string name="send_message">पठाउनुहोस्</string>
<string name="show_commands">आज्ञाहरू देखाउनुहोस्</string>
<string name="back">पछाडि</string>
<string name="people">मानिसहरू</string>
<string name="channels">च्यानलहरू</string>
<string name="online_users">अनलाइन प्रयोगकर्ता</string>
<string name="no_one_connected">कसैसँग जडान छैन</string>
<string name="emergency_clear_hint">सबै डेटा मेटाउन तीन पटक ट्याप गर्नुहोस्</string>
<string name="your_network">सञ्जाल</string>
<!-- ब्याट्री अनुकूलन -->
<string name="battery_optimization_detected">ब्याट्री अनुकूलन भेटियो</string>
<string name="battery_optimization_disabled">ब्याट्री अनुकूलन बन्द</string>
<string name="battery_optimization_not_required">ब्याट्री अनुकूलन आवश्यक छैन</string>
<string name="battery_optimization_checking">ब्याट्री अनुकूलन जाँचिँदै</string>
<string name="battery_optimization_why_disable">ब्याट्री अनुकूलन किन बन्द गर्ने?</string>
<string name="battery_optimization_explanation">bitchat पछाडिबाट चल्छ ताकि नजिकका यन्त्रहरूसँग मेष जडान कायम रहोस्। ब्याट्री अनुकूलनले यी जडान विच्छेद गराउन सक्छ, जसले सन्देश ढिलो वा हराउन सक्छ।\n\nअनुकूलन बन्द गर्दा भरपर्दो peer‑to‑peer सन्देश सुनिश्चित हुन्छ।</string>
<string name="battery_optimization_disable_button">ब्याट्री अनुकूलन बन्द गर्नुहोस्</string>
<string name="battery_optimization_note">नोट: यो सेटिङ पछि Android सेटिङहरू &gt; Apps &gt; bitchat &gt; Battery मा परिवर्तन गर्न सकिन्छ।</string>
<string name="battery_optimization_not_supported_explanation">तपाईंको यन्त्रलाई ब्याट्री अनुकूलन सेटिङ आवश्यक छैन। bitchat सामान्य रूपमा चल्नेछ।</string>
<string name="battery_optimization_not_supported_message">तपाईंको यन्त्रलाई ब्याट्री अनुकूलन सेटिङ आवश्यक छैन। bitchat सामान्य रूपमा चल्नेछ।</string>
<string name="battery_optimization_success_message">bitchat पछाडिबाट भरपर्दो रूपमा चल्न सक्छ</string>
<string name="battery_optimization_benefits">• सन्देश विश्वसनीय डेलिभरी\n• मेष जडान कायम राख्ने\n• पृष्ठभूमिमा रिले\n• जडान विच्छेद हुन नदिने</string>
<string name="battery_optimization_check_again">फेरि जाँच्नुहोस्</string>
<string name="battery_optimization_skip">अहिलेलाई बेवास्ता गर्नुहोस्</string>
<string name="battery_optimization_continue">जारी राख्नुहोस्</string>
<string name="retry">फेरि प्रयास गर्नुहोस्</string>
<string name="skip">बेवास्ता गर्नुहोस्</string>
<!-- सूचनाहरू -->
<string name="notification_summary_more">र %1$d थप</string>
<string name="notification_messages_from_people">%1$d सन्देश %2$d जनाबाट</string>
<string name="notification_more_conversations">र %1$d अरू कुराकानी</string>
<string name="notification_active_peers_title">👥 नजिकै bitchatter हरू!</string>
<string name="notification_active_peers_one">१ जना नजिकै</string>
<string name="notification_active_peers_many">%1$d जना नजिकै</string>
<string name="notification_new_messages">नयाँ सन्देश</string>
<string name="notification_new_location_messages">नयाँ स्थान सन्देश</string>
<string name="notification_mentions_in">%1$s मा उल्लेख</string>
<string name="notification_mentions_in_more">%1$s मा उल्लेख (+%2$d थप)</string>
<string name="notification_mentions_in_plural">%1$d उल्लेख %2$s मा</string>
<string name="notification_new_activity_in">%1$s मा नयाँ गतिविधि</string>
<string name="notification_messages_in">%1$s मा सन्देश</string>
<string name="notification_joined_conversation">%1$s वार्तालापमा सामेल भयो</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d उल्लेख</string>
<string name="notification_geohash_summary_title">bitchat – स्थान च्याट</string>
<string name="notification_geohash_summary_text">%2$d स्थानबाट %1$d सन्देश</string>
<string name="notification_mesh_mention_title_singular">मेष च्याटमा उल्लेख</string>
<string name="notification_mesh_mention_title_plural">मेष च्याटमा %1$d उल्लेख</string>
<string name="notification_more_locations">र %1$d थप स्थान</string>
<string name="notification_and_more">र %1$d थप</string>
<!-- मनपर्ने / पहुँचयोग्यता -->
<string name="cd_add_favorite">मनपर्नेमा थप्नुहोस्</string>
<string name="cd_remove_favorite">मनपरिबाट हटाउनुहोस्</string>
<string name="cd_add_bookmark">बुकमार्क थप्नुहोस्</string>
<!-- च्याट शीर्षक / पहुँचयोग्यता -->
<string name="chat_back">पछाडि</string>
<string name="chat_channel_prefix">च्यानल: %1$s</string>
<string name="chat_leave">छोड्नुहोस्</string>
<string name="cd_nostr_reachable">Nostr मार्फत पुग्न सकिने</string>
<string name="cd_unread_private_messages">नपढिएका निजी सन्देश</string>
<string name="cd_toggle_bookmark">बुकमार्क टगल</string>
<string name="cd_teleported">टेलिपोर्ट भयो</string>
<string name="cd_tor_status">Tor स्थिति</string>
<string name="cd_connected_peers">जडान भएका साथीहरू</string>
<string name="cd_geohash_participants">Geohash सहभागिहरू</string>
<string name="cd_ready_for_handshake">ह्यान्डशेकका लागि तयार</string>
<string name="cd_handshake_in_progress">ह्यान्डशेक भइरहेको</string>
<string name="cd_encrypted">अन्त्यदेखि अन्त्य एनक्रिप्टेड</string>
<string name="cd_handshake_failed">ह्यान्डशेक असफल</string>
<!-- फाइल दर्शक संवाद -->
<string name="file_viewer_title">📎 फाइल प्राप्त भयो</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 साइज: %1$s</string>
<string name="file_viewer_type">🏷️ प्रकार: %1$s</string>
<string name="file_viewer_open_save">📂 खोल्नुहोस् / बचत गर्नुहोस्</string>
<string name="close_with_emoji">❌ बन्द गर्नुहोस्</string>
<string name="pick_image">तस्वीर छान्नुहोस्</string>
<!-- अबाउट शीट -->
<string name="about_tagline">विकेन्द्रित मेष सन्देश अन्त्यदेखि अन्त्य इन्क्रिप्सनसहित</string>
<string name="about_offline_mesh_title">अफलाइन मेष च्याट</string>
<string name="about_offline_mesh_desc">इन्टरनेट वा सर्भर बिना सिधै Bluetooth LE मार्फत सञ्चार गर्नुहोस्। नजिकका यन्त्रहरूबाट सन्देश रिल레이 हुन्छ।</string>
<string name="about_online_geohash_title">अनलाइन Geohash च्यानलहरू</string>
<string name="about_online_geohash_desc">Geohash आधारित च्यानलमार्फत नजिकका मानिसहरूसँग जोडिनुहोस्। सार्वजनिक इन्टरनेट रिलेलाई प्रयोग गरेर मेष विस्तार गर्नुहोस्।</string>
<string name="about_e2e_title">एन्ड‑टु‑एन्ड इन्क्रिप्सन</string>
<string name="about_e2e_desc">निजी सन्देश इन्क्रिप्टेड हुन्छन्। च्यानल सन्देश सार्वजनिक हुन्छन्।</string>
<string name="about_appearance">देखावट</string>
<string name="about_system">सिस्टम</string>
<string name="about_light">हल्का</string>
<string name="about_dark">गाढा</string>
<string name="about_pow">प्रुफ अफ वर्क</string>
<string name="about_pow_off">pow बन्द</string>
<string name="about_pow_on">pow चालु</string>
<string name="about_pow_tip">स्पाम रोकथामका लागि geohash सन्देशमा proof of work थप्नुहोस्।</string>
<string name="about_pow_difficulty">कठिनाइ: %1$d बिट (~%2$s)</string>
<string name="about_pow_difficulty_attempts">कठिनाइ %1$d का लागि ~%2$s ह्यास प्रयास</string>
<string name="about_pow_desc_none">proof of work आवश्यक छैन</string>
<string name="about_pow_desc_very_low">अति कम – न्यून सुरक्षा</string>
<string name="about_pow_desc_low">कम – आधारभूत सुरक्षा</string>
<string name="about_pow_desc_medium">मध्यम – राम्रो सुरक्षा</string>
<string name="about_pow_desc_high">उच्च – बलियो सुरक्षा</string>
<string name="about_pow_desc_very_high">एकदम उच्च – ढिलाइ हुन सक्छ</string>
<string name="about_pow_desc_extreme">अत्यधिक – धेरै गणना आवश्यक</string>
<string name="about_network">सञ्जाल</string>
<string name="about_tor_off">tor बन्द</string>
<string name="about_tor_on">tor चालु</string>
<string name="about_tor_route">बढी गोपनीयताका लागि Tor मार्फत इन्टरनेट रुट गर्नुहोस्।</string>
<string name="about_tor_status">Tor स्थिति: %1$s, बुटस्ट्र्याप %2$d%%</string>
<string name="about_last">अन्तिम: %1$s</string>
<string name="about_emergency_title">आपतकालीन डेटा मेटाउने</string>
<string name="about_emergency_tip">सुझाव: एप शीर्षक तीन पटक ट्याप गरी सबै डेटा (सन्देश, कुञ्जी, सेटिङ) मेटाउनुहोस्।</string>
<string name="about_debug_settings">डिबग सेटिङ</string>
<string name="about_footer">Open Source • Privacy First • विकेन्द्रित</string>
<string name="close_plain">बन्द गर्नुहोस्</string>
<string name="cancel_lower">रद्द गर्नुहोस्</string>
<!-- सामान्य CD -->
<string name="cd_warning">चेतावनी</string>
<string name="cd_location_services">स्थान सेवाहरू</string>
<string name="cd_privacy">गोपनीयता</string>
<string name="cd_error">त्रुटि</string>
<string name="cd_battery_optimization">ब्याट्री अनुकूलन</string>
<string name="cd_benefits">फाइदाहरू</string>
<string name="cd_checking_battery_optimization">ब्याट्री अनुकूलन जाँचिँदै</string>
<string name="cd_not_supported_battery_optimization">समर्थन छैन</string>
<string name="cd_bluetooth">ब्लुटुथ</string>
<string name="cd_unread_message">नपढिएको सन्देश</string>
<string name="cd_open_map">नक्सा खोल्नुहोस्</string>
<string name="cd_remove_bookmark">बुकमार्क हटाउनुहोस्</string>
<string name="cd_teleport">टेलिपोर्ट</string>
<string name="cd_selected">छानिएको</string>
<string name="cd_leave_channel">च्यानल छोड्नुहोस्</string>
<string name="cd_reachable_via_nostr">Nostr बाट पहुँचयोग्य</string>
<string name="cd_offline_favorite">मनपर्ने (अफलाइन)</string>
<string name="cd_decrease_precision">शुद्धता घटाउनुहोस्</string>
<string name="cd_increase_precision">शुद्धता बढाउनुहोस्</string>
<string name="cd_select_geohash">geohash छान्नुहोस्</string>
<string name="cd_scroll_to_bottom">तल स्क्रोल गर्नुहोस्</string>
<string name="cd_file">फाइल</string>
<string name="cd_image">तस्वीर</string>
<string name="cd_cancel">रद्द</string>
<string name="cd_link">लिङ्क</string>
<string name="cd_pick_media">मेडिया छान्नुहोस्</string>
<string name="cd_record_voice">भ्वाइस नोट रेकर्ड</string>
<string name="cd_offline_mesh_chat">अफलाइन मेष च्याट</string>
<string name="cd_online_geohash_channels">अनलाइन Geohash च्यानल</string>
<string name="cd_end_to_end_encryption">एन्ड‑टु‑एन्ड इन्क्रिप्सन</string>
<!-- छवि / फाइल -->
<string name="image_page_of">तस्वीर %1$d / %2$d</string>
<string name="image_unavailable">तस्वीर उपलब्ध छैन</string>
<string name="image_saved_to_downloads">तस्वीर "Downloads" मा सुरक्षित भयो</string>
<string name="image_save_failed">तस्वीर बचत असफल</string>
<string name="pick_file">फाइल छान्नुहोस्</string>
<string name="file_unavailable">[फाइल उपलब्ध छैन]</string>
<string name="unknown">अज्ञात</string>
<!-- प्रयोगकर्ता कार्य शीट -->
<string name="choose_action_message_or_user">यो सन्देश वा प्रयोगकर्ताका लागि कार्य छान्नुहोस्</string>
<string name="choose_action_user">यस प्रयोगकर्ताका लागि कार्य छान्नुहोस्</string>
<string name="action_copy_message_title">सन्देश प्रतिलिपि</string>
<string name="action_copy_message_subtitle">यो सन्देश क्लिपबोर्डमा प्रतिलिपि गर्नुहोस्</string>
<string name="action_slap_title">%1$s लाई चड्कन</string>
<string name="action_slap_subtitle">मनोरञ्जनका लागि चड्कन पठाउनुहोस्</string>
<string name="action_hug_title">%1$s लाई अँगालो</string>
<string name="action_hug_subtitle">मैत्रीपूर्ण अँगालो पठाउनुहोस्</string>
<string name="action_block_title">%1$s लाई ब्लक गर्नुहोस्</string>
<string name="action_block_subtitle">यस प्रयोगकर्ताबाट सबै सन्देश ब्लक गर्नुहोस्</string>
<!-- स्थान च्यानल शीट -->
<string name="location_channels_title">#स्थान च्यानल</string>
<string name="location_channels_desc">तपाईंको वरिपरिका मानिसहरूसँग geohash च्यानल प्रयोग गरी च्याट गर्नुहोस्। केवल सामान्य geohash साझा हुन्छ, कहिल्यै ठ्याक्कै GPS होइन। गोपनीयताका लागि स्क्रिनसट नलिनुहोस् र नबाँड्नुहोस्।</string>
<string name="grant_location_permission">स्थान अनुमति दिनुहोस्</string>
<string name="location_permission_denied">स्थान अनुमति अस्वीकार। स्थान च्यानल प्रयोग गर्न सेटिङमा सक्षम गर्नुहोस्।</string>
<string name="open_settings">सेटिङ खोल्नुहोस्</string>
<string name="location_permission_granted">\u2713 स्थान अनुमति दिइयो</string>
<string name="checking_permissions">अनुमति जाँचिँदै…</string>
<string name="finding_nearby_channels">नजिकका च्यानल खोजिँदै…</string>
<string name="bookmarked">बुकमार्क गरिएको</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">अवैध geohash</string>
<string name="teleport">टेलिपोर्ट</string>
<string name="disable_location_services">स्थान सेवाहरू बन्द गर्नुहोस्</string>
<string name="enable_location_services">स्थान सेवाहरू सुरु गर्नुहोस्</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">ब्लक</string>
<string name="location_level_neighborhood">छिमेक</string>
<string name="location_level_city">सहर</string>
<string name="location_level_province">प्रान्त</string>
<string name="location_level_region">क्षेत्र</string>
<!-- डिबग / निदान -->
<string name="debug_tools">डिबग उपकरण</string>
<string name="debug_verbose_logging">विस्तृत लगिङ</string>
<string name="debug_bluetooth_roles">ब्लुटुथ भूमिकाहरू</string>
<string name="debug_gatt_server">GATT सर्भर</string>
<string name="debug_connections_fmt">जडान: %1$d / %2$d</string>
<string name="debug_max_server">अधिकतम सर्भर</string>
<string name="debug_gatt_client">GATT क्लाइन्ट</string>
<string name="debug_max_client">अधिकतम क्लाइन्ट</string>
<string name="debug_overall_connections_fmt">जडान: %1$d / %2$d</string>
<string name="debug_max_overall">अधिकतम कुल</string>
<string name="debug_packet_relay">प्याकेट रिल레이</string>
<string name="debug_since_start_fmt">सुरु भएकोयता: %1$d</string>
<string name="debug_sync_settings">सिङ्क सेटिङ</string>
<string name="debug_max_packets_per_sync_fmt">प्रत्येक सिङ्कका अधिकतम प्याकेट: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">GCS फिल्टर साइज अधिकतम: %1$d बाइट (1281024)</string>
<string name="debug_target_fpr_fmt">लक्ष्य FPR: %1$.2f%%</string>
<string name="debug_connected_devices">जडान भएका यन्त्रहरू</string>
<string name="debug_our_device_id_fmt">हाम्रो यन्त्र आईडी: %1$s</string>
<string name="debug_none">केही छैन</string>
<string name="debug_disconnect">डिस्कनेक्ट</string>
<string name="debug_recent_scan_results">हालैका स्क्यान नतिजा</string>
<string name="debug_connect">जोड्नुहोस्</string>
<string name="debug_debug_console">डिबग कन्सोल</string>
<string name="debug_clear">खाली गर्नुहोस्</string>
<string name="debug_relays_window_fmt">अन्तिम 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">व्युत्पन्न P: %1$s • अनुमानित अधिकतम तत्व: %2$s</string>
<string name="debug_direct_suffix"> • प्रत्यक्ष</string>
<string name="debug_question_mark">?</string>
<string name="debug_role_server">सर्भरको रूपमा (हामी होस्ट गर्छौं)</string>
<string name="debug_role_client">क्लाइन्टको रूपमा (हामी जडान गर्छौं)</string>
<!-- अनबोर्डिङ स्क्रिन -->
<string name="location_services_required">स्थान सेवाहरू आवश्यक</string>
<string name="privacy_first">गोपनीयता पहिलो</string>
<string name="location_explanation">bitchat ले तपाईंको स्थान पछ्याउँदैन।\n\nब्लुटुथ स्क्यान र Geohash च्याट सुविधा लागि स्थान सेवा आवश्यक छन्।</string>
<string name="location_needs_for">bitchat लाई स्थान सेवा आवश्यक पर्छ:</string>
<string name="location_needs_bullets">• ब्लुटुथ यन्त्र स्क्यान\n• मेष सञ्जालमा नजिकका प्रयोगकर्ता पत्ता लगाउने\n• Geohash च्याट सुविधा\n• कुनै ट्र्याकिङ वा स्थान सङ्कलन छैन</string>
<string name="open_location_settings">स्थान सेटिङ खोल्नुहोस्</string>
<string name="check_again">फेरि जाँच्नुहोस्</string>
<string name="location_services_unavailable">स्थान सेवाहरू उपलब्ध छैनन्</string>
<string name="location_unavailable_explanation">यस यन्त्रमा स्थान सेवाहरू उपलब्ध छैनन्। यो असामान्य हो किनकि Android यन्त्रमा यो मानक हो।\n\nब्लुटुथ स्क्यान ठीकसँग चल्न (Android को आवश्यक) स्थान सेवा चाहिन्छ। अन्यथा नजिकका प्रयोगकर्ता पत्ता लाग्दैनन्।</string>
<string name="checking_location_services">स्थान सेवाहरू जाँचिँदै…</string>
<string name="bluetooth_required">ब्लुटुथ आवश्यक</string>
<string name="bluetooth_needs_for">bitchat लाई ब्लुटुथ आवश्यक छ:</string>
<string name="bluetooth_needs_bullets">• नजिकका प्रयोगकर्ता पत्ता लगाउने\n• मेष जडान बनाउने\n• सन्देश पठाउने/प्राप्त गर्ने\n• इन्टरनेट वा सर्भर बिना काम गर्ने</string>
<string name="enable_bluetooth">ब्लुटुथ सक्षम गर्नुहोस्</string>
<string name="bluetooth_not_supported">ब्लुटुथ समर्थित छैन</string>
<string name="bluetooth_unsupported_explanation">यो यन्त्रले Bluetooth Low Energy (BLE) समर्थन गर्दैन, जुन bitchat को लागि आवश्यक छ।\n\nनजिकका यन्त्रहरूसँग इन्टरनेट बिना सञ्चार गर्न र मेष बनाउन BLE चाहिन्छ।</string>
<string name="checking_bluetooth_status">ब्लुटुथ स्थिति जाँचिँदै…</string>
<string name="battery_optimization_detected_title">ब्याट्री अनुकूलन भेटियो</string>
<string name="battery_optimization_enabled_title">ब्याट्री अनुकूलन सक्षम</string>
<string name="battery_optimization_explanation_short">मेष जडान कायम राख्न bitchat पछाडिबाट चल्नुपर्छ। ब्याट्री अनुकूलनले जडान काट्न सक्छ।</string>
<string name="benefits_of_disabling">बन्द गर्ने फाइदाहरू</string>
<string name="battery_benefits_short">• भरपर्दो डेलिभरी\n• मेष कन्नेक्टिभिटी कायम\n• विच्छेद रोक्छ</string>
<string name="disable_battery_optimization">अनुकूलन बन्द गर्नुहोस्</string>
<string name="battery_optimization_disabled_title">ब्याट्री अनुकूलन बन्द</string>
<string name="continue_btn">जारी राख्नुहोस्</string>
<string name="initializing_mesh_network">मेष सञ्जाल सुरु गर्दै</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">ब्लुटुथ मेष सेटअप गर्दै…</string>
<string name="should_take_seconds">यसलाई केही सेकेन्ड मात्र लाग्छ</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">सेटअप पूरा भएन</string>
<string name="try_again">फेरि प्रयास गर्नुहोस्</string>
<string name="privacy_protected">तपाईंको गोपनीयता सुरक्षित छ</string>
<string name="privacy_bullets">• कुनै ट्र्याकिङ वा डेटा सङ्कलन छैन\n• ब्लुटुथ मेष च्याट पूर्णतया अफलाइन\n• Geohash च्याट इन्टरनेट प्रयोग गर्छ</string>
<string name="permissions_header">अनुमति</string>
<string name="grant_permissions">अनुमति दिनुहोस्</string>
<string name="location_tracking_warning">bitchat ले तपाईंको स्थान पछ्याउँदैन</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">मानिसहरू</string>
<string name="nobody_around">वरिपरि कोही छैन…</string>
<string name="you_suffix"> (तपाईं)</string>
<string name="pan_zoom_instruction">geohash छान्न प्यान र जुम गर्नुहोस्</string>
<string name="select">छान्नुहोस्</string>
<string name="type_a_message_placeholder">सन्देश टाइप गर्नुहोस्…</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">उल्लेख</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">तस्वीर</string>
<string name="media_type_file">फाइल</string>
<!-- सन्देश स्थिति -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- सूचना पाठ सहायक -->
<string name="notification_sent_image">📷 तस्वीर पठाइयो</string>
<string name="notification_sent_voice">🎤 भ्वाइस सन्देश पठाइयो</string>
<string name="notification_sent_file">📎 फाइल पठाइयो</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- भ्वाइस प्लेयर पहुँचयोग्यता -->
<string name="cd_play_voice">प्ले</string>
<string name="cd_pause_voice">पज</string>
<!-- अनुमति विवरण -->
<string name="perm_nearby_devices_desc">ब्लुटुथमार्फत bitchat प्रयोगकर्ता फेला पार्न आवश्यक</string>
<string name="perm_nearby_devices_system">bitchat लाई नजिकका यन्त्र जडान गर्न अनुमति दिनुहोस्</string>
<string name="perm_location_desc">Android अनुसार ब्लुटुथमार्फत नजिकका प्रयोगकर्ता फेला पार्न आवश्यक</string>
<string name="perm_location_system">नजिकका यन्त्र स्क्यान गर्न bitchat लाई आवश्यक</string>
<string name="perm_notifications_desc">निजी सन्देश आउँदा सूचना पाउनुहोस्</string>
<string name="perm_notifications_system">bitchat लाई तपाईंलाई सूचना पठाउन दिनुहोस्</string>
<string name="perm_battery_desc">bitchat लाई पछाडिबाट भरपर्दो रूपमा चलाउन र मेष जडान कायम राख्न ब्याट्री अनुकूलन बन्द गर्नुहोस्</string>
<string name="perm_battery_system">ब्याट्री प्रतिबन्ध बिना चल्न अनुमति दिनुहोस्</string>
<!-- अनुमति प्रकार -->
<string name="perm_type_nearby_devices">नजिकका यन्त्रहरू</string>
<string name="perm_type_precise_location">ठ्याक्कै स्थान</string>
<string name="perm_type_microphone">माइक</string>
<string name="perm_type_notifications">सूचना</string>
<string name="perm_type_battery_optimization">ब्याट्री अनुकूलन</string>
<string name="perm_type_other">अन्य</string>
<!-- पासवर्ड संवाद -->
<string name="pwd_prompt_title">च्यानल पासवर्ड प्रविष्ट गर्नुहोस्</string>
<string name="pwd_prompt_message">%1$s च्यानल पासवर्ड सुरक्षित छ। जडान हुन पासवर्ड लेख्नुहोस्।</string>
<string name="pwd_label">पासवर्ड</string>
<string name="join">जोडिनुहोस्</string>
<string name="cancel">रद्द</string>
<!-- Plurals -->
<plurals name="notification_and_more">
<item quantity="one">र %d थप</item>
<item quantity="other">र %d थप</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 जना</item>
<item quantity="other">%d जना</item>
</plurals>
</resources>
+397
View File
@@ -0,0 +1,397 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Toestemmingsredenen -->
<string name="permission_bluetooth_rationale">Bluetooth-toestemming is vereist voor peer-to-peer berichten zonder internet.</string>
<string name="permission_location_rationale">Locatietoestemming is vereist om apparaten in de buurt via Bluetooth te ontdekken.</string>
<string name="permission_notification_rationale">Meldingstoestemming is vereist om u te waarschuwen voor nieuwe berichten.</string>
<!-- Tijdelijke aanduidingen / basis UI -->
<string name="nickname_hint">bijnaam</string>
<string name="message_hint">typ een bericht…</string>
<string name="channel_password_hint">Wachtwoord</string>
<string name="join_channel">Kanaal deelnemen</string>
<string name="leave_channel">Verlaten</string>
<string name="send_message">Verzenden</string>
<string name="show_commands">Commando\'s weergeven</string>
<string name="back">Terug</string>
<string name="people">Personen</string>
<string name="channels">Kanalen</string>
<string name="online_users">Online gebruikers</string>
<string name="no_one_connected">Niemand verbonden</string>
<string name="emergency_clear_hint">Tik drie keer om alle gegevens te wissen</string>
<string name="your_network">Netwerk</string>
<!-- Batterijoptimalisatie -->
<string name="battery_optimization_detected">Batterijoptimalisatie gedetecteerd</string>
<string name="battery_optimization_disabled">Batterijoptimalisatie uitgeschakeld</string>
<string name="battery_optimization_not_required">Batterijoptimalisatie niet vereist</string>
<string name="battery_optimization_checking">Batterijoptimalisatie controleren</string>
<string name="battery_optimization_why_disable">Waarom batterijoptimalisatie uitschakelen?</string>
<string name="battery_optimization_explanation">bitchat draait op de achtergrond om meshnetwerkverbindingen met apparaten in de buurt te onderhouden. Batterijoptimalisatie kan deze verbindingen onderbreken, waardoor berichten vertraagd of gemist worden.\n\nHet uitschakelen van batterijoptimalisatie zorgt voor betrouwbare peer-to-peer communicatie.</string>
<string name="battery_optimization_disable_button">Batterijoptimalisatie uitschakelen</string>
<string name="battery_optimization_note">Opmerking: U kunt deze instelling later wijzigen in Android-instellingen &gt; Apps &gt; bitchat &gt; Batterij</string>
<string name="battery_optimization_not_supported_explanation">Uw apparaat vereist geen batterijoptimalisatie-instellingen. bitchat zal normaal draaien.</string>
<string name="battery_optimization_not_supported_message">Uw apparaat vereist geen batterijoptimalisatie-instellingen. bitchat zal normaal draaien.</string>
<string name="battery_optimization_success_message">bitchat kan betrouwbaar op de achtergrond draaien</string>
<string name="battery_optimization_benefits">• Zorgt voor betrouwbare berichtbezorging\n• Onderhoudt meshnetwerkconnectiviteit\n• Staat berichtrelay op achtergrond toe\n• Voorkomt verbindingsonderbrekingen</string>
<string name="battery_optimization_check_again">Opnieuw controleren</string>
<string name="battery_optimization_skip">Nu overslaan</string>
<string name="battery_optimization_continue">Doorgaan</string>
<string name="retry">Opnieuw proberen</string>
<string name="skip">Overslaan</string>
<!-- Meldingen -->
<string name="notification_summary_more">en %1$d meer</string>
<string name="notification_messages_from_people">%1$d berichten van %2$d personen</string>
<string name="notification_more_conversations">en %1$d meer conversaties</string>
<string name="notification_active_peers_title">👥 bitchatters in de buurt!</string>
<string name="notification_active_peers_one">1 persoon in de buurt</string>
<string name="notification_active_peers_many">%1$d personen in de buurt</string>
<string name="notification_new_messages">Nieuwe berichten</string>
<string name="notification_new_location_messages">Nieuwe locatieberichten</string>
<string name="notification_mentions_in">Vermeld in %1$s</string>
<string name="notification_mentions_in_more">Vermeld in %1$s (+%2$d meer)</string>
<string name="notification_mentions_in_plural">%1$d vermeldingen in %2$s</string>
<string name="notification_new_activity_in">Nieuwe activiteit in %1$s</string>
<string name="notification_messages_in">Berichten in %1$s</string>
<string name="notification_joined_conversation">%1$s is toegetreden tot het gesprek</string>
<string name="notification_geohash_summary_title_mentions">bitchat - %1$d vermeldingen</string>
<string name="notification_geohash_summary_title">bitchat - locatiechats</string>
<string name="notification_geohash_summary_text">%1$d berichten van %2$d locaties</string>
<string name="notification_mesh_mention_title_singular">Vermeld in meshchat</string>
<string name="notification_mesh_mention_title_plural">%1$d vermeldingen in meshchat</string>
<string name="notification_more_locations">en %1$d meer locaties</string>
<string name="notification_and_more">en %1$d meer</string>
<!-- Favorieten toegankelijkheid -->
<string name="cd_add_favorite">Toevoegen aan favorieten</string>
<string name="cd_remove_favorite">Verwijderen uit favorieten</string>
<string name="cd_add_bookmark">Bladwijzer toevoegen</string>
<!-- Chatkop & toegankelijkheid -->
<string name="chat_back">terug</string>
<string name="chat_channel_prefix">kanaal: %1$s</string>
<string name="chat_leave">verlaten</string>
<string name="cd_nostr_reachable">Bereikbaar via Nostr</string>
<string name="cd_unread_private_messages">Ongelezen privéberichten</string>
<string name="cd_toggle_bookmark">Bladwijzer omschakelen</string>
<string name="cd_teleported">Geteleporteerd</string>
<string name="cd_tor_status">Tor-status</string>
<string name="cd_connected_peers">Verbonden peers</string>
<string name="cd_geohash_participants">Geohash-deelnemers</string>
<string name="cd_ready_for_handshake">Klaar voor handshake</string>
<string name="cd_handshake_in_progress">Handshake bezig</string>
<string name="cd_encrypted">End-to-end versleuteld</string>
<string name="cd_handshake_failed">Handshake mislukt</string>
<!-- Bestandsweergave dialoog -->
<string name="file_viewer_title">📎 Bestand ontvangen</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Grootte: %1$s</string>
<string name="file_viewer_type">🏷️ Type: %1$s</string>
<string name="file_viewer_open_save">📂 Openen / Opslaan</string>
<string name="close_with_emoji">❌ Sluiten</string>
<string name="pick_image">Afbeelding kiezen</string>
<!-- Info-sheet -->
<string name="about_tagline">gedecentraliseerde meshcommunicatie met end-to-end-versleuteling</string>
<string name="about_offline_mesh_title">Offline meshchat</string>
<string name="about_offline_mesh_desc">Communiceer rechtstreeks via Bluetooth LE zonder internet of servers. Berichten worden doorgestuurd via apparaten in de buurt om het bereik te vergroten.</string>
<string name="about_online_geohash_title">Online geohash-kanalen</string>
<string name="about_online_geohash_desc">Maak contact met mensen in uw omgeving met geohash-gebaseerde kanalen. Breid het mesh uit met openbare internetrelays.</string>
<string name="about_e2e_title">End-to-end-versleuteling</string>
<string name="about_e2e_desc">Privéberichten zijn versleuteld. Kanaalberichten zijn openbaar.</string>
<string name="about_appearance">uiterlijk</string>
<string name="about_system">systeem</string>
<string name="about_light">licht</string>
<string name="about_dark">donker</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">PoW uit</string>
<string name="about_pow_on">PoW aan</string>
<string name="about_pow_tip">voeg proof of work toe aan geohash-berichten voor spamafschrikking.</string>
<string name="about_pow_difficulty">moeilijkheidsgraad: %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">moeilijkheidsgraad %1$d vereist ~%2$s hash-pogingen</string>
<string name="about_pow_desc_none">geen proof of work vereist</string>
<string name="about_pow_desc_very_low">zeer laag - minimale spambescherming</string>
<string name="about_pow_desc_low">laag - basis spambescherming</string>
<string name="about_pow_desc_medium">gemiddeld - goede spambescherming</string>
<string name="about_pow_desc_high">hoog - sterke spambescherming</string>
<string name="about_pow_desc_very_high">zeer hoog - kan vertragingen veroorzaken</string>
<string name="about_pow_desc_extreme">extreem - aanzienlijke berekening vereist</string>
<string name="about_network">netwerk</string>
<string name="about_tor_off">Tor uit</string>
<string name="about_tor_on">Tor aan</string>
<string name="about_tor_route">route internet via Tor voor verbeterde privacy.</string>
<string name="about_tor_status">Tor-status: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Laatste: %1$s</string>
<string name="about_emergency_title">Noodgegevensverwijdering</string>
<string name="about_emergency_tip">Tip: Driedubbel klik op de app-titel om alle opgeslagen gegevens inclusief berichten, sleutels en instellingen noodmatig te verwijderen.</string>
<string name="about_debug_settings">Debug-instellingen</string>
<string name="about_footer">Open Source • Privacy First • Gedecentraliseerd</string>
<string name="close_plain">Sluiten</string>
<string name="cancel_lower">annuleren</string>
<!-- Algemene content-beschrijvingen -->
<string name="cd_warning">Waarschuwing</string>
<string name="cd_location_services">Locatiediensten</string>
<string name="cd_privacy">Privacy</string>
<string name="cd_error">Fout</string>
<string name="cd_battery_optimization">Batterijoptimalisatie</string>
<string name="cd_benefits">Voordelen</string>
<string name="cd_checking_battery_optimization">Batterijoptimalisatie controleren</string>
<string name="cd_not_supported_battery_optimization">Batterijoptimalisatie niet ondersteund</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Ongelezen bericht</string>
<string name="cd_open_map">Kaart openen</string>
<string name="cd_remove_bookmark">Bladwijzer verwijderen</string>
<string name="cd_teleport">Teleporteren</string>
<string name="cd_selected">Geselecteerd</string>
<string name="cd_leave_channel">Kanaal verlaten</string>
<string name="cd_reachable_via_nostr">Bereikbaar via Nostr</string>
<string name="cd_offline_favorite">Offline favoriet</string>
<string name="cd_decrease_precision">Precisie verlagen</string>
<string name="cd_increase_precision">Precisie verhogen</string>
<string name="cd_select_geohash">Geohash selecteren</string>
<string name="cd_scroll_to_bottom">Naar beneden scrollen</string>
<string name="cd_file">Bestand</string>
<string name="cd_image">Afbeelding</string>
<string name="cd_cancel">Annuleren</string>
<string name="cd_link">Link</string>
<string name="cd_pick_media">Media kiezen</string>
<string name="cd_pick_file">Bestand kiezen</string>
<string name="cd_save_current_image">Huidige afbeelding opslaan</string>
<string name="cd_close">Sluiten</string>
<string name="cd_image_index_of">Afbeelding %1$d van %2$d</string>
<string name="cd_privacy_protected">Privacy beschermd</string>
<string name="cd_record_voice">Spraaknotitie opnemen</string>
<string name="cd_offline_mesh_chat">Offline meshchat</string>
<string name="cd_online_geohash_channels">Online geohash-kanalen</string>
<string name="cd_end_to_end_encryption">End-to-end-versleuteling</string>
<!-- Afbeeldingen & bestanden -->
<string name="image_page_of">Afbeelding %1$d van %2$d</string>
<string name="image_unavailable">Afbeelding niet beschikbaar</string>
<string name="image_saved_to_downloads">Afbeelding opgeslagen in Downloads</string>
<string name="image_save_failed">Opslaan afbeelding mislukt</string>
<string name="toast_image_saved">Afbeelding opgeslagen in Downloads</string>
<string name="toast_failed_to_save_image">Opslaan afbeelding mislukt</string>
<string name="pick_file">Bestand kiezen</string>
<string name="file_unavailable">[bestand niet beschikbaar]</string>
<string name="unknown">onbekend</string>
<!-- Gebruikersactie-sheet -->
<string name="choose_action_message_or_user">kies een actie voor dit bericht of deze gebruiker</string>
<string name="choose_action_user">kies een actie voor deze gebruiker</string>
<string name="action_copy_message_title">bericht kopiëren</string>
<string name="action_copy_message_subtitle">kopieer dit bericht naar klembord</string>
<string name="action_slap_title">%1$s een tik geven</string>
<string name="action_slap_subtitle">stuur een speelse tik</string>
<string name="action_hug_title">%1$s knuffelen</string>
<string name="action_hug_subtitle">stuur een vriendelijke knuffel</string>
<string name="action_block_title">%1$s blokkeren</string>
<string name="action_block_subtitle">blokkeer alle berichten van deze gebruiker</string>
<!-- Locatiekanalen sheet -->
<string name="location_channels_title">#locatiekanalen</string>
<string name="location_channels_desc">chat met mensen in uw buurt via geohash-kanalen. alleen een grove geohash wordt gedeeld, nooit exacte GPS. maak geen screenshot of deel dit scherm niet om uw privacy te beschermen.</string>
<string name="grant_location_permission">locatietoestemming verlenen</string>
<string name="location_permission_denied">locatietoestemming geweigerd. schakel in instellingen in om locatiekanalen te gebruiken.</string>
<string name="open_settings">Instellingen openen</string>
<string name="location_permission_granted">\u2713 locatietoestemming verleend</string>
<string name="checking_permissions">toestemmingen controleren…</string>
<string name="finding_nearby_channels">nabije kanalen zoeken…</string>
<string name="bookmarked">bladwijzer toegevoegd</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">ongeldige geohash</string>
<string name="teleport">teleporteren</string>
<string name="disable_location_services">locatiediensten uitschakelen</string>
<string name="enable_location_services">locatiediensten inschakelen</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">blok</string>
<string name="location_level_neighborhood">buurt</string>
<string name="location_level_city">stad</string>
<string name="location_level_province">provincie</string>
<string name="location_level_region">regio</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Debug / Diagnostiek -->
<string name="debug_tools">debug-tools</string>
<string name="debug_tools_desc">ontwikkelaarsgereedschap voor diagnostiek en controle</string>
<string name="debug_verbose_logging">uitgebreide logging</string>
<string name="debug_verbose_hint">logt peer deelnames/vertrek, verbindingsrichting, pakketrouting en relays</string>
<string name="debug_bluetooth_roles">Bluetooth-rollen</string>
<string name="debug_gatt_server">GATT-server</string>
<string name="debug_connections_fmt">verbindingen: %1$d / %2$d</string>
<string name="debug_max_server">max server</string>
<string name="debug_gatt_client">GATT-client</string>
<string name="debug_max_client">max client</string>
<string name="debug_overall_connections_fmt">verbindingen: %1$d / %2$d</string>
<string name="debug_max_overall">max totaal</string>
<string name="debug_packet_relay">pakketrelay</string>
<string name="debug_since_start_fmt">sinds start: %1$d</string>
<string name="debug_roles_hint">schakel rollen in/uit en sluit alle verbindingen bij uitschakelen</string>
<string name="debug_sync_settings">sync-instellingen</string>
<string name="debug_max_packets_per_sync_fmt">max pakketten per sync: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">max GCS-filtergrootte: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">doel-FPR: %1$.2f%%</string>
<string name="debug_connected_devices">verbonden apparaten</string>
<string name="debug_our_device_id_fmt">ons apparaat-ID: %1$s</string>
<string name="debug_none">geen</string>
<string name="debug_disconnect">verbreken</string>
<string name="debug_recent_scan_results">recente scanresultaten</string>
<string name="debug_connect">verbinden</string>
<string name="debug_debug_console">debug-console</string>
<string name="debug_clear">wissen</string>
<string name="debug_relays_window_fmt">laatste 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">afgeleide P: %1$s • gesch. max elementen: %2$s</string>
<string name="debug_direct_suffix"> • direct</string>
<string name="debug_role_server">als server (wij hosten)</string>
<string name="debug_role_client">als client (wij verbinden)</string>
<!-- Onboarding-schermen -->
<string name="location_services_required">Locatiediensten vereist</string>
<string name="privacy_first">Privacy eerst</string>
<string name="location_explanation">bitchat volgt NIET uw locatie.\n\nLocatiediensten zijn vereist voor Bluetooth-scanning en voor de geohash-chatfunctie.</string>
<string name="location_needs_for">bitchat heeft locatiediensten nodig voor:</string>
<string name="location_needs_bullets">• Bluetooth-apparaat scanning\n• Ontdekken van gebruikers in de buurt op meshnetwerk\n• Geohash-chatfunctie\n• Geen tracking of locatieverzameling</string>
<string name="open_location_settings">Locatie-instellingen openen</string>
<string name="check_again">Opnieuw controleren</string>
<string name="location_services_unavailable">Locatiediensten niet beschikbaar</string>
<string name="location_unavailable_explanation">Locatiediensten zijn niet beschikbaar op dit apparaat. Dit is ongebruikelijk omdat locatiediensten standaard zijn op Android-apparaten.\n\nbitchat heeft locatiediensten nodig om Bluetooth-scanning goed te laten werken (Android-vereiste). Zonder dit kan de app geen gebruikers in de buurt ontdekken.</string>
<string name="checking_location_services">Locatiediensten controleren…</string>
<string name="bluetooth_required">Bluetooth vereist</string>
<string name="bluetooth_needs_for">bitchat heeft Bluetooth nodig om:</string>
<string name="bluetooth_needs_bullets">• Gebruikers in de buurt te ontdekken\n• Meshnetwerkverbindingen te maken\n• Berichten te verzenden en ontvangen\n• Te werken zonder internet of servers</string>
<string name="enable_bluetooth">Bluetooth inschakelen</string>
<string name="bluetooth_not_supported">Bluetooth niet ondersteund</string>
<string name="bluetooth_unsupported_explanation">Dit apparaat ondersteunt geen Bluetooth Low Energy (BLE), wat vereist is om bitchat te laten functioneren.\n\nbitchat heeft BLE nodig om meshnetwerken te maken en te communiceren met apparaten in de buurt zonder internet.</string>
<string name="checking_bluetooth_status">Bluetooth-status controleren…</string>
<string name="battery_optimization_detected_title">batterijoptimalisatie gedetecteerd</string>
<string name="battery_optimization_enabled_title">Batterijoptimalisatie ingeschakeld</string>
<string name="battery_optimization_explanation_short">bitchat moet op de achtergrond draaien om meshverbindingen te onderhouden. batterijoptimalisatie kan deze verbindingen onderbreken.</string>
<string name="benefits_of_disabling">Voordelen van uitschakelen</string>
<string name="battery_benefits_short">• betrouwbare berichtbezorging\n• onderhoudt meshconnectiviteit\n• voorkomt verbindingsonderbrekingen</string>
<string name="disable_battery_optimization">Batterijoptimalisatie uitschakelen</string>
<string name="battery_optimization_disabled_title">batterijoptimalisatie uitgeschakeld</string>
<string name="continue_btn">Doorgaan</string>
<string name="initializing_mesh_network">Meshnetwerk initialiseren</string>
<string name="setting_up_bluetooth">Bluetooth-meshnetwerk instellen…</string>
<string name="should_take_seconds">Dit zou slechts enkele seconden moeten duren</string>
<string name="setup_not_complete">Installatie niet voltooid</string>
<string name="try_again">Opnieuw proberen</string>
<string name="privacy_protected">Uw privacy is beschermd</string>
<string name="privacy_bullets">• geen tracking of gegevensverzameling\n• Bluetooth-meshchats zijn volledig offline\n• Geohash-chats gebruiken internet</string>
<string name="permissions_header">toestemmingen</string>
<string name="grant_permissions">Toestemmingen verlenen</string>
<string name="location_tracking_warning">bitchat volgt NIET uw locatie</string>
<string name="geohash_people_header">PERSONEN</string>
<string name="nobody_around">niemand in de buurt…</string>
<string name="you_suffix"> (jij)</string>
<string name="pan_zoom_instruction">pan en zoom om een geohash te selecteren</string>
<string name="select">selecteren</string>
<string name="type_a_message_placeholder">typ een bericht…</string>
<string name="mention">vermelden</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Afbeelding</string>
<string name="media_type_file">Bestand</string>
<!-- Berichtstatus-tekst helpers -->
<string name="notification_sent_image">📷 heeft een afbeelding verstuurd</string>
<string name="notification_sent_voice">🎤 heeft een spraakbericht verstuurd</string>
<string name="notification_sent_file">📎 heeft een bestand verstuurd</string>
<!-- Spraakspeler toegankelijkheid -->
<string name="cd_play_voice">Afspelen</string>
<string name="cd_pause_voice">Pauzeren</string>
<string name="cd_mining_pow">Mining-PoW</string>
<string name="cd_pow_enabled">PoW ingeschakeld</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">minen…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Toestemmingsbeschrijvingen -->
<string name="perm_nearby_devices_desc">Vereist om bitchat-gebruikers via Bluetooth te ontdekken</string>
<string name="perm_nearby_devices_system">bitchat toestaan om verbinding te maken met apparaten in de buurt</string>
<string name="perm_location_desc">Vereist door Android om bitchat-gebruikers in de buurt via Bluetooth te ontdekken</string>
<string name="perm_location_system">bitchat heeft dit nodig om te scannen naar apparaten in de buurt</string>
<string name="perm_notifications_desc">Ontvang meldingen wanneer u privéberichten ontvangt</string>
<string name="perm_notifications_system">bitchat toestaan om u meldingen te sturen</string>
<string name="perm_battery_desc">Schakel batterijoptimalisatie uit om ervoor te zorgen dat bitchat betrouwbaar op de achtergrond draait en meshnetwerkverbindingen onderhoudt</string>
<string name="perm_battery_system">bitchat toestaan om zonder batterijbeperkingen te draaien</string>
<!-- Toestemmingstypen -->
<string name="perm_type_nearby_devices">Apparaten in de buurt</string>
<string name="perm_type_precise_location">Precieze locatie</string>
<string name="perm_type_microphone">Microfoon</string>
<string name="perm_type_notifications">Meldingen</string>
<string name="perm_type_battery_optimization">Batterijoptimalisatie</string>
<string name="perm_type_other">Overig</string>
<!-- Wachtwoord-dialoog -->
<string name="pwd_prompt_title">Kanaalwachtwoord invoeren</string>
<string name="pwd_prompt_message">Kanaal %1$s is met een wachtwoord beveiligd. Voer het wachtwoord in om deel te nemen.</string>
<string name="pwd_label">Wachtwoord</string>
<string name="join">Deelnemen</string>
<string name="cancel">Annuleren</string>
<!-- Symbolen & speciale strings -->
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="at_nickname">@%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="dot">.</string>
<string name="warning_emoji">⚠️</string>
<string name="debug_question_mark">?</string>
<!-- Berichtstatus-pictogrammen -->
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<!-- Meldingsbestand-emojis -->
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<!-- Meervouden -->
<plurals name="notification_and_more">
<item quantity="one">en %d meer</item>
<item quantity="other">en %d meer</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 persoon</item>
<item quantity="other">%d personen</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d notitie</item>
<item quantity="other">#%1$s ± 1 • %2$d notities</item>
</plurals>
<string name="location_notes_description">voeg korte permanente notities toe aan deze locatie zodat andere bezoekers ze kunnen vinden.</string>
<string name="location_notes_relays_unavailable">geo-relays niet beschikbaar; notities gepauzeerd</string>
<string name="location_notes_no_relays_title">geen geo-relays in de buurt</string>
<string name="location_notes_no_relays_desc">notities zijn afhankelijk van geo-relays. controleer de verbinding en probeer opnieuw.</string>
<string name="loading_location_notes">notities laden…</string>
<string name="location_notes_empty_title">nog geen notities</string>
<string name="location_notes_empty_desc">wees de eerste die een notitie voor deze plek toevoegt.</string>
<string name="dismiss">sluiten</string>
<string name="location_notes_input_placeholder">voeg een notitie toe voor deze plek</string>
</resources>
+352
View File
@@ -0,0 +1,352 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- اجازت دی وجہ -->
<string name="permission_bluetooth_rationale">انٹرنیٹ توں بغیر سیدھی چیٹ لئی بلوٹوتھ دی اجازت ضروری اے۔</string>
<string name="permission_location_rationale">بلوٹوتھ راہین نیڑے ڈیوائس لبھن لئی لوکیشن دی اجازت ضروری اے۔</string>
<string name="permission_notification_rationale">نوٹیفکیشن دی اجازت نواں پیغام دسدے لئی ضروری اے۔</string>
<!-- پلیس ہولڈر / بنیادی UI -->
<string name="nickname_hint">عرفی ناں</string>
<string name="message_hint">پیغام لکھو…</string>
<string name="channel_password_hint">پاس ورڈ</string>
<string name="join_channel">چینل وچ شامل ہوو</string>
<string name="leave_channel">باہر آؤ</string>
<string name="send_message">پھجو</string>
<string name="show_commands">کمانڈ وکھاؤ</string>
<string name="back">واپس</string>
<string name="people">لوگ</string>
<string name="channels">چینل</string>
<string name="online_users">آن لائن یوزر</string>
<string name="no_one_connected">کوئی وی منسلک نہیں</string>
<string name="emergency_clear_hint">ساری ڈیٹا مٹاون لئی تین وار ٹیپ کرو</string>
<string name="your_network">نیٹ ورک</string>
<!-- بیٹری آپٹمائزیشن -->
<string name="battery_optimization_detected">بیٹری آپٹمائزیشن لبھیا گیا</string>
<string name="battery_optimization_disabled">بیٹری آپٹمائزیشن بند اے</string>
<string name="battery_optimization_not_required">بیٹری آپٹمائزیشن دی لوڑ نئیں</string>
<string name="battery_optimization_checking">بیٹری آپٹمائزیشن چیک ہورہی اے</string>
<string name="battery_optimization_why_disable">بیٹری آپٹمائزیشن کیوں بند کریے؟</string>
<string name="battery_optimization_explanation">bitchat پس منظر وچ چلدا اے تے نیڑے ڈیوائس نال میش کنکشن برقرار رکھدا اے۔ بیٹری آپٹمائزیشن ایہ کنکشناں نوں روک سکدی اے، جِنہ نال پیغام لیٹ یا غائب ہوسکدے نیں۔\n\nبیٹری آپٹمائزیشن بند کرن نال معتبر ہم رتبہ رابطہ یقینی ہوندا اے۔</string>
<string name="battery_optimization_disable_button">بیٹری آپٹمائزیشن بند کرو</string>
<string name="battery_optimization_note">نوٹ: تُسی ایہ بعد وچ Android سیٹنگز &gt; ایپس &gt; bitchat &gt; بیٹری وچ بدَل سکدے او۔</string>
<string name="battery_optimization_not_supported_explanation">توانڈے ڈیوائس نوں بیٹری آپٹمائزیشن سیٹنگ دی لوڑ نئیں۔ bitchat عام طرح چلّو گا۔</string>
<string name="battery_optimization_not_supported_message">توانڈے ڈیوائس نوں بیٹری آپٹمائزیشن سیٹنگ دی لوڑ نئیں۔ bitchat عام طرح چلّو گا۔</string>
<string name="battery_optimization_success_message">bitchat پس منظر وچ قابلِ اعتماد چل سکدا اے</string>
<string name="battery_optimization_benefits">• معتبر پیغام ترسیل\n• میش کنکشن برقرار\n• پس منظر وچ پیغام ریلے\n• کنکشن ٹٹّن توں بچاؤ</string>
<string name="battery_optimization_check_again">فیر چیک کرو</string>
<string name="battery_optimization_skip">ہور ویلے</string>
<string name="battery_optimization_continue">جاری رکھو</string>
<string name="retry">فیر کوشِش کرو</string>
<string name="skip">سکِپ</string>
<!-- نوٹیفکیشن -->
<string name="notification_summary_more">تے %1$d ہور</string>
<string name="notification_messages_from_people">%2$d لوکان کولوں %1$d پیغام</string>
<string name="notification_more_conversations">تے %1$d ہور گلاں</string>
<string name="notification_active_peers_title">👥 نیڑے bitchatter!</string>
<string name="notification_active_peers_one">نیڑے 1 بندہ</string>
<string name="notification_active_peers_many">نیڑے %1$d بندے</string>
<string name="notification_new_messages">نویں پیغام</string>
<string name="notification_new_location_messages">نویں لوکیشن پیغام</string>
<string name="notification_mentions_in">%1$s وچ ذکر ہویا</string>
<string name="notification_mentions_in_more">%1$s وچ ذکر (+%2$d ہور)</string>
<string name="notification_mentions_in_plural">%2$s وچ %1$d وار ذکر</string>
<string name="notification_new_activity_in">%1$s وچ نویں سرگرمی</string>
<string name="notification_messages_in">%1$s وچ پیغام</string>
<string name="notification_joined_conversation">%1$s گفتگو وچ شامل ہویا</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d ذکر</string>
<string name="notification_geohash_summary_title">bitchat – لوکیشن چیٹ</string>
<string name="notification_geohash_summary_text">%2$d ٹھاں توں %1$d پیغام</string>
<string name="notification_mesh_mention_title_singular">میش چیٹ وچ ذکر</string>
<string name="notification_mesh_mention_title_plural">میش چیٹ وچ %1$d ذکر</string>
<string name="notification_more_locations">تے %1$d ہور ٹھاں</string>
<string name="notification_and_more">تے %1$d ہور</string>
<!-- پسندیدہ رسائی پذیری -->
<string name="cd_add_favorite">پسندیدہ وچ پاؤ</string>
<string name="cd_remove_favorite">پسندیدہ توں ہٹاؤ</string>
<string name="cd_add_bookmark">بُک مارک پاؤ</string>
<!-- چیٹ ہیڈر & رسائی پذیری -->
<string name="chat_back">واپس</string>
<string name="chat_channel_prefix">چینل: %1$s</string>
<string name="chat_leave">باہر آؤ</string>
<string name="cd_nostr_reachable">Nostr راہین پہنچ ممکن اے</string>
<string name="cd_unread_private_messages">انہ پڑھیا ذاتی پیغام</string>
<string name="cd_toggle_bookmark">بُک مارک ٹوگل کرو</string>
<string name="cd_teleported">ٹیلپورٹ کیتا گیا</string>
<string name="cd_tor_status">Tor حالت</string>
<string name="cd_connected_peers">جُڑے پیئر</string>
<string name="cd_geohash_participants">geohash شریک</string>
<string name="cd_ready_for_handshake">ہینڈشیک لئی تیار</string>
<string name="cd_handshake_in_progress">ہینڈشیک جاری</string>
<string name="cd_encrypted">اینڈ ٹو اینڈ انکرپٹڈ</string>
<string name="cd_handshake_failed">ہینڈشیک فیل ہویا</string>
<!-- فائل ویؤر ڈائیلاگ -->
<string name="file_viewer_title">📎 فائل ملی</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 سائز: %1$s</string>
<string name="file_viewer_type">🏷️ قسم: %1$s</string>
<string name="file_viewer_open_save">📂 کھولو / سیو کرو</string>
<string name="close_with_emoji">❌ بند کرو</string>
<string name="pick_image">تصویر چُنو</string>
<!-- بارے شیٹ -->
<string name="about_tagline">اینڈ ٹو اینڈ انکرپشن نال غیر مرکزی میش چیٹ</string>
<string name="about_offline_mesh_title">آف لائن میش چیٹ</string>
<string name="about_offline_mesh_desc">انٹرنیٹ یا سرور توں بغیر Bluetooth LE راہین سیدھا رابطہ کرو۔ رینج ودھاؤن لئی پیغام نیڑے ڈیوائساں راہین ریلے ہوندے نیں۔</string>
<string name="about_online_geohash_title">آن لائن geohash چینل</string>
<string name="about_online_geohash_desc">geohash بیسڈ چینلاں راہین اپنے علاقے دے لوکاں نال جڑو۔ پبلک انٹرنیٹ ریلے راہین میش نوں وسیع کرو۔</string>
<string name="about_e2e_title">اینڈ ٹو اینڈ انکرپشن</string>
<string name="about_e2e_desc">ذاتی پیغام انکرپٹڈ ہوندے نیں۔ چینل پیغام پبلک ہوندے نیں۔</string>
<string name="about_appearance">دِکھ</string>
<string name="about_system">سسٹم</string>
<string name="about_light">ہلکا</string>
<string name="about_dark">گھُپ</string>
<string name="about_pow">ثبوتِ کار (Proof of Work)</string>
<string name="about_pow_off">PoW بند</string>
<string name="about_pow_on">PoW چالو</string>
<string name="about_pow_tip">سپیم مشکل کرن لئی geohash پیغام وچ Proof of Work شامل کرو۔</string>
<string name="about_pow_difficulty">مشکلی: %1$d بٹ (~%2$s)</string>
<string name="about_pow_difficulty_attempts">مشکلی %1$d لئی ~%2$s ہیش کوششاں چاہیدن</string>
<string name="about_pow_desc_none">کسے Proof of Work دی لوڑ نئیں</string>
<string name="about_pow_desc_very_low">بوہت گھٹ – گھٹ توں گھٹ سپیم تحفظ</string>
<string name="about_pow_desc_low">گھٹ – بنیادی سپیم تحفظ</string>
<string name="about_pow_desc_medium">درمیانہ – اچھا سپیم تحفظ</string>
<string name="about_pow_desc_high">وڈا – مضبوط سپیم تحفظ</string>
<string name="about_pow_desc_very_high">بوہت وڈا – ڈیلے ہوسکدا اے</string>
<string name="about_pow_desc_extreme">انتہائی – وڈی کمپیوٹنگ پاور دی لوڑ</string>
<string name="about_network">نیٹ ورک</string>
<string name="about_tor_off">Tor بند</string>
<string name="about_tor_on">Tor چالو</string>
<string name="about_tor_route">وَدھ پرائیویسی لئی انٹرنیٹ ٹریفک نوں Tor راہین رُوٹ کرو۔</string>
<string name="about_tor_status">Tor حالت: %1$s، بوٹ اسٹرَیپ %2$d%%</string>
<string name="about_last">آخری: %1$s</string>
<string name="about_emergency_title">ایمرجنسی ڈیٹا صاف</string>
<string name="about_emergency_tip">ٹِپ: سارے محفوظ ڈیٹا (پیغام، کُنجیاں، سیٹنگا) مٹاؤن لئی ایپ دے عنوان تے تین وار ٹیپ کرو۔</string>
<string name="about_debug_settings">ڈی بگ سیٹنگا</string>
<string name="about_footer">اوپن سورس • پرائیویسی پہلے • غیر مرکزی</string>
<string name="close_plain">بند کرو</string>
<string name="cancel_lower">منسوخ</string>
<!-- عمومی مواد دی وضاحت -->
<string name="cd_warning">خبردار</string>
<string name="cd_location_services">لوکیشن سروسز</string>
<string name="cd_privacy">پرائیویسی</string>
<string name="cd_error">غلطی</string>
<string name="cd_battery_optimization">بیٹری آپٹمائزیشن</string>
<string name="cd_benefits">فائدے</string>
<string name="cd_checking_battery_optimization">بیٹری آپٹمائزیشن چیک ہورہی اے</string>
<string name="cd_not_supported_battery_optimization">بیٹری آپٹمائزیشن سپورٹڈ نئیں</string>
<string name="cd_bluetooth">بلوٹوتھ</string>
<string name="cd_unread_message">انہ پڑھیا پیغام</string>
<string name="cd_open_map">نقشہ کھولو</string>
<string name="cd_remove_bookmark">بُک مارک ہٹاؤ</string>
<string name="cd_teleport">ٹیلپورٹ</string>
<string name="cd_selected">چُنے ہوۓ</string>
<string name="cd_leave_channel">چینل چھوڑو</string>
<string name="cd_reachable_via_nostr">Nostr راہین پہنچ ممکن اے</string>
<string name="cd_offline_favorite">پسندیدہ (آف لائن)</string>
<string name="cd_decrease_precision">درستگی گھٹاؤ</string>
<string name="cd_increase_precision">درستگی وداؤ</string>
<string name="cd_select_geohash">geohash چُنو</string>
<string name="cd_scroll_to_bottom">تھلے سکرول کرو</string>
<string name="cd_file">فائل</string>
<string name="cd_image">تصویر</string>
<string name="cd_cancel">منسوخ</string>
<string name="cd_link">لنک</string>
<string name="cd_pick_media">میڈیا چُنو</string>
<string name="cd_pick_file">فائل چُنو</string>
<string name="cd_save_current_image">موجودہ تصویر سیو کرو</string>
<string name="cd_close">بند کرو</string>
<string name="cd_image_index_of">تصویر %1$d توں %2$d</string>
<string name="cd_privacy_protected">پرائیویسی محفوظ اے</string>
<string name="cd_record_voice">وائس پیغام ریکارڈ کرو</string>
<string name="cd_offline_mesh_chat">آف لائن میش چیٹ</string>
<string name="cd_online_geohash_channels">آن لائن geohash چینل</string>
<string name="cd_end_to_end_encryption">اینڈ ٹو اینڈ انکرپشن</string>
<!-- تصویراں & فائلز -->
<string name="image_page_of">تصویر %1$d وچوں %2$d</string>
<string name="image_unavailable">تصویر دستیاب نئیں</string>
<string name="image_saved_to_downloads">تصویر \"Downloads\" وچ سیو ہو گئی</string>
<string name="image_save_failed">تصویر سیو نئیں ہو سکدی</string>
<string name="toast_image_saved">تصویر \"Downloads\" وچ سیو ہو گئی</string>
<string name="toast_failed_to_save_image">تصویر سیو نئیں ہو سکدی</string>
<string name="pick_file">فائل چُنو</string>
<string name="file_unavailable">[فائل دستیاب نئیں]</string>
<string name="unknown">نامعلوم</string>
<!-- یوزر ایکشن شیٹ -->
<string name="choose_action_message_or_user">اس پیغام یا یوزر لئی عمل چُنو</string>
<string name="choose_action_user">اس یوزر لئی عمل چُنو</string>
<string name="action_copy_message_title">پیغام کاپی کرو</string>
<string name="action_copy_message_subtitle">ایہ پیغام کلپ بورڈ وچ کاپی کرو</string>
<string name="action_slap_title">%1$s نوں چپیڑ مارو</string>
<string name="action_slap_subtitle">مزاحیہ چپیڑ پھجو</string>
<string name="action_hug_title">%1$s نوں گلے لاؤ</string>
<string name="action_hug_subtitle">دوستانہ گلے ملنا پھجو</string>
<string name="action_block_title">%1$s نوں بلاک کرو</string>
<string name="action_block_subtitle">اس یوزر دے سارے پیغام بلاک کرو</string>
<!-- geohash چینل شیٹ -->
<string name="location_channels_title">#لوکیشن چینل</string>
<string name="location_channels_desc">geohash چینلاں راہین اپنے نیڑے والے لوکاں نال چیٹ کرو۔ صرف اوکھا geohash شیئر ہوندا اے، ٹھیک GPS ڈیٹا نئیں۔ پرائیویسی لئی مہربانی کر کے ایہہ ویو اسکرین شاٹ یا شیئر نہ کرو۔</string>
<string name="grant_location_permission">لوکیشن دی اجازت دو</string>
<string name="location_permission_denied">لوکیشن دی اجازت رد ہوگئی۔ لوکیشن چینل لئی سیٹنگز وچ فعال کرو۔</string>
<string name="open_settings">سیٹنگز کھولو</string>
<string name="location_permission_granted">\u2713 لوکیشن دی اجازت مل گئی</string>
<string name="checking_permissions">اجازت چیک ہورہی اے …</string>
<string name="finding_nearby_channels">نیڑے چینل لبھ رہے آں …</string>
<string name="bookmarked">بُک مارک ہویا</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">غلط geohash</string>
<string name="teleport">ٹیلپورٹ</string>
<string name="disable_location_services">لوکیشن سروسز بند کرو</string>
<string name="enable_location_services">لوکیشن سروسز چالو کرو</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">بلاک</string>
<string name="location_level_neighborhood">پڑوس</string>
<string name="location_level_city">شہر</string>
<string name="location_level_province">صوبہ</string>
<string name="location_level_region">خطہ</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- ڈیبگ / تشخیص -->
<string name="debug_tools">ڈی بگ ٹول</string>
<string name="debug_tools_desc">تشخیصی تے کنٹرول لئی ڈویلپر ٹول</string>
<string name="debug_verbose_logging">تفصیلی لاگنگ</string>
<string name="debug_verbose_hint">پیئر جوائن/لیو، کنکشن سمت، پیکٹ فارورڈنگ تے ریلے لاگ کرو</string>
<string name="debug_bluetooth_roles">بلوٹوتھ کردار</string>
<string name="debug_gatt_server">GATT سرور</string>
<string name="debug_connections_fmt">کنکشن: %1$d / %2$d</string>
<string name="debug_max_server">وڈ توں وڈ سرور</string>
<string name="debug_gatt_client">GATT کلائنٹ</string>
<string name="debug_max_client">وڈ توں وڈ کلائنٹ</string>
<string name="debug_overall_connections_fmt">کنکشن: %1$d / %2$d</string>
<string name="debug_max_overall">کل وڈ توں وڈ</string>
<string name="debug_packet_relay">پیکٹ ریلے</string>
<string name="debug_since_start_fmt">شروع توں: %1$d</string>
<string name="debug_roles_hint">کردار آن/آف کرو تے غیر فعال کرن تے سارے کنکشن بند کرو</string>
<string name="debug_sync_settings">سنک سیٹنگا</string>
<string name="debug_max_packets_per_sync_fmt">ہر سنک وِچ وڈ توں وڈ پیکٹ: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">وڈ توں وڈ GCS فلٹر سائز: %1$d بائٹ (1281024)</string>
<string name="debug_target_fpr_fmt">ٹارگٹ FPR: %1$.2f%%</string>
<string name="debug_connected_devices">جڑے ڈیوائس</string>
<string name="debug_our_device_id_fmt">ساڈا ڈیوائس ID: %1$s</string>
<string name="debug_none">کچھ وی نئیں</string>
<string name="debug_disconnect">ڈس کنیکٹ</string>
<string name="debug_recent_scan_results">حال ہی وچ سکین ہوۓ ڈیوائس</string>
<string name="debug_connect">جڑو</string>
<string name="debug_debug_console">ڈی بگ کنسول</string>
<string name="debug_clear">صاف کرو</string>
<string name="debug_relays_window_fmt">پچھلے 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">مشتق P: %1$s • اندازاً وڈ توں وڈ عناصر: %2$s</string>
<string name="debug_direct_suffix"> • سیدھا</string>
<string name="debug_role_server">سرور (اسی ہوسٹ آں)</string>
<string name="debug_role_client">کلائنٹ (اسی جُڑدے آں)</string>
<!-- آن بورڈنگ سکرینا -->
<string name="location_services_required">لوکیشن سروسز لازمی نیں</string>
<string name="privacy_first">پرائیویسی پہلے</string>
<string name="location_explanation">bitchat توانڈی لوکیشن نئیں ٹریک کردا۔\n\nبلوٹوتھ سکیننگ تے geohash چیٹ فیچر لئی لوکیشن سروسز دی لوڑ اے۔</string>
<string name="location_needs_for">bitchat نوں لوکیشن سروسز دی لوڑ اے لئی:</string>
<string name="location_needs_bullets">• بلوٹوتھ ڈیوائس سکیننگ\n• میش نیٹ ورک وچ نیڑے یوزراں دی تلاش\n• geohash چیٹ فیچر\n• کوئی ٹریکنگ یا لوکیشن جمع نئیں</string>
<string name="open_location_settings">لوکیشن سیٹنگز کھولو</string>
<string name="check_again">فیر چیک کرو</string>
<string name="location_services_unavailable">لوکیشن سروسز دستیاب نئیں</string>
<string name="location_unavailable_explanation">اس ڈیوائس تے لوکیشن سروسز دستیاب نئیں۔ ایہ غیر معمولی اے کیونجے Android ڈیوائساں تے لوکیشن سروسز معیاری نیں۔\n\nبلوٹوتھ سکیننگ نوں ٹھیک کم کرن لئی bitchat نوں لوکیشن سروسز چاہیدیاں نیں (Android دی شرط)۔ بنا اس دے، ایپ نیڑے یوزر نئیں لبھ سکدی۔</string>
<string name="checking_location_services">لوکیشن سروسز چیک ہورھیاں نیں …</string>
<string name="bluetooth_required">بلوٹوتھ لازمی اے</string>
<string name="bluetooth_needs_for">bitchat نوں بلوٹوتھ چاہیدا اے لئی:</string>
<string name="bluetooth_needs_bullets">• نیڑے یوزر لبھنا\n• میش نیٹ ورک کنکشن بنانا\n• پیغام بھیجنا تے لینا\n• انٹرنیٹ یا سرور توں بغیر کم کرنا</string>
<string name="enable_bluetooth">بلوٹوتھ چالو کرو</string>
<string name="bluetooth_not_supported">بلوٹوتھ سپورٹڈ نئیں</string>
<string name="bluetooth_unsupported_explanation">ایہ ڈیوائس Bluetooth Low Energy (BLE) نئیں سپورٹ کردا، جو bitchat لئی ضروری اے۔\n\nbitchat نوں BLE چاہیدا اے میش نیٹ ورک بناؤن تے نیڑے ڈیوائساں نال انٹرنیٹ توں بغیر گل کرن لئی۔</string>
<string name="checking_bluetooth_status">بلوٹوتھ حالت چیک ہورہی اے …</string>
<string name="battery_optimization_detected_title">بیٹری آپٹمائزیشن لبھیا گیا</string>
<string name="battery_optimization_enabled_title">بیٹری آپٹمائزیشن چالو اے</string>
<string name="battery_optimization_explanation_short">میش کنکشن قائم رکھن لئی bitchat نوں پس منظر وچ چلنا پوے گا۔ بیٹری آپٹمائزیشن ایہ کنکشناں وچ رکاوٹ پا سکدی اے۔</string>
<string name="benefits_of_disabling">بند کرن دے فائدے</string>
<string name="battery_benefits_short">• معتبر پیغام رسانی\n• میش کنکشن برقرار\n• کنکشن ٹٹّن توں بچاؤ</string>
<string name="disable_battery_optimization">بیٹری آپٹمائزیشن بند کرو</string>
<string name="battery_optimization_disabled_title">بیٹری آپٹمائزیشن بند اے</string>
<string name="continue_btn">جاری رکھو</string>
<string name="initializing_mesh_network">میش نیٹ ورک شروع ہورہا اے</string>
<string name="setting_up_bluetooth">بلوٹوتھ میش نیٹ ورک سیٹ اپ ہورہا …</string>
<string name="should_take_seconds">ایہ صرف چند سیکنڈ لگنے چاہیدے نیں</string>
<string name="setup_not_complete">سیٹ اپ مکمل نئیں</string>
<string name="try_again">فیر کوشِش کرو</string>
<string name="privacy_protected">توانڈی پرائیویسی محفوظ اے</string>
<string name="privacy_bullets">• کوئی ٹریکنگ یا ڈیٹا جمع نئیں\n• بلوٹوتھ میش چیٹ مکمل آف لائن\n• geohash چیٹ انٹرنیٹ استعمال کردی اے</string>
<string name="permissions_header">اجازتاں</string>
<string name="grant_permissions">اجازت دو</string>
<string name="location_tracking_warning">bitchat توانڈی لوکیشن نئیں ٹریک کردا</string>
<string name="geohash_people_header">لوگ</string>
<string name="nobody_around">کوئی وی نیڑے نئیں …</string>
<string name="you_suffix"> (تُسی)</string>
<string name="pan_zoom_instruction">geohash چُنن لئی پین تے زوم کرو</string>
<string name="select">چُنو</string>
<string name="type_a_message_placeholder">پیغام لکھو …</string>
<string name="mention">ذکر</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">تصویر</string>
<string name="media_type_file">فائل</string>
<!-- نوٹیفکیشن متن مددگار -->
<string name="notification_sent_image">📷 تصویر بھیجی</string>
<string name="notification_sent_voice">🎤 وائس پیغام بھیجیا</string>
<string name="notification_sent_file">📎 فائل بھیجی</string>
<!-- وائس پلیئر رسائی پذیری -->
<string name="cd_play_voice">چلاؤ</string>
<string name="cd_pause_voice">روکੋ</string>
<string name="cd_mining_pow">PoW مائننگ</string>
<string name="cd_pow_enabled">PoW چالو</string>
<string name="cd_proof_of_work">Proof of Work</string>
<string name="pow_mining_ellipsis">مائننگ …</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- اجازت دیاں وضاحتاں -->
<string name="perm_nearby_devices_desc">بلوٹوتھ راہین bitchat یوزر لبھن لئی ضروری</string>
<string name="perm_nearby_devices_system">bitchat نوں نیڑے ڈیوائساں نال جُڑن دی اجازت دو</string>
<string name="perm_location_desc">Android نوں بلوٹوتھ راہین نیڑے bitchat یوزراں دی تلاش لئی لوڑ اے</string>
<string name="perm_location_system">bitchat نوں نیڑے ڈیوائساں سکین کرن لئی ایہ چاہیدہ</string>
<string name="perm_notifications_desc">جدو تُہانوں ذاتی پیغام مِلن تاں نوٹیفکیشن لؤ</string>
<string name="perm_notifications_system">bitchat نوں نوٹیفکیشن بھیجن دی اجازت دو</string>
<string name="perm_battery_desc">ایہ یقینی بناؤن لئی بیٹری آپٹمائزیشن بند کرو کہ bitchat پس منظر وچ معتبر چلّے تے میش نیٹ ورک کنکشناں برقرار رہن</string>
<string name="perm_battery_system">bitchat نوں بغیر بیٹری پابندیاں دے چلّن دی اجازت دو</string>
<!-- اجازت دیاں قسماں -->
<string name="perm_type_nearby_devices">نیڑے ڈیوائس</string>
<string name="perm_type_precise_location">ٹھیک لوکیشن</string>
<string name="perm_type_microphone">مائیکروفون</string>
<string name="perm_type_notifications">نوٹیفکیشن</string>
<string name="perm_type_battery_optimization">بیٹری آپٹمائزیشن</string>
<string name="perm_type_other">ہور</string>
<!-- پاس ورڈ ڈائیلاگ -->
<string name="pwd_prompt_title">چینل دا پاس ورڈ لکھو</string>
<string name="pwd_prompt_message">چینل %1$s پاس ورڈ نال محفوظ اے۔ شامل ہون لئی پاس ورڈ لکھو۔</string>
<string name="pwd_label">پاس ورڈ</string>
<string name="join">شامل ہوو</string>
<string name="cancel">منسوخ</string>
<!-- جمع -->
<plurals name="notification_and_more">
<item quantity="one">تے %d ہور</item>
<item quantity="other">تے %d ہور</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 بندہ</item>
<item quantity="other">%d بندے</item>
</plurals>
</resources>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- TODO: Polish translations -->
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d notatka</item>
<item quantity="other">#%1$s ± 1 • %2$d notatek</item>
</plurals>
<string name="location_notes_description">dodaj krótkie stałe notatki do tej lokalizacji, aby inni odwiedzający mogli je znaleźć.</string>
<string name="location_notes_relays_unavailable">przekaźniki geo niedostępne; notatki wstrzymane</string>
<string name="location_notes_no_relays_title">brak przekaźników geo w pobliżu</string>
<string name="location_notes_no_relays_desc">notatki zależą od przekaźników geo. sprawdź połączenie i spróbuj ponownie.</string>
<string name="loading_location_notes">ładowanie notatek…</string>
<string name="location_notes_empty_title">brak notatek</string>
<string name="location_notes_empty_desc">bądź pierwszy, który doda notatkę dla tego miejsca.</string>
<string name="dismiss">zamknij</string>
<string name="location_notes_input_placeholder">dodaj notatkę dla tego miejsca</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Justificativas de permissões (BR) -->
<string name="permission_bluetooth_rationale">A permissão de Bluetooth é necessária para conversar diretamente com outras pessoas sem internet.</string>
<string name="permission_location_rationale">A permissão de localização é necessária para encontrar dispositivos próximos via Bluetooth.</string>
<string name="permission_notification_rationale">A permissão de notificações é necessária para avisar sobre novas mensagens.</string>
<!-- Placeholders / UI básica -->
<string name="nickname_hint">Apelido</string>
<string name="message_hint">Digite uma mensagem…</string>
<string name="channel_password_hint">Senha</string>
<string name="join_channel">Entrar no canal</string>
<string name="leave_channel">Sair</string>
<string name="send_message">Enviar</string>
<string name="show_commands">Mostrar comandos</string>
<string name="back">Voltar</string>
<string name="people">Pessoas</string>
<string name="channels">Canais</string>
<string name="online_users">Usuários online</string>
<string name="no_one_connected">Ninguém conectado</string>
<string name="emergency_clear_hint">Toque 3 vezes para apagar todos os dados</string>
<string name="your_network">Sua rede</string>
<!-- Otimização de bateria -->
<string name="battery_optimization_detected">Otimização de bateria detectada</string>
<string name="battery_optimization_disabled">Otimização de bateria desativada</string>
<string name="battery_optimization_not_required">Otimização de bateria não necessária</string>
<string name="battery_optimization_checking">Verificando otimização de bateria</string>
<string name="battery_optimization_why_disable">Por que desativar a otimização de bateria?</string>
<string name="battery_optimization_explanation">O bitchat roda em segundo plano para manter conexões mesh com dispositivos próximos. A otimização de bateria pode interromper essas conexões, fazendo com que mensagens atrasem ou se percam.\n\nDesativar a otimização de bateria garante comunicação P2P confiável.</string>
<string name="battery_optimization_disable_button">Desativar otimização de bateria</string>
<string name="battery_optimization_note">Nota: Você pode alterar isso depois em Configurações do Android &gt; Apps &gt; bitchat &gt; Bateria.</string>
<string name="battery_optimization_not_supported_explanation">Seu dispositivo não requer ajustes de otimização de bateria. O bitchat funcionará normalmente.</string>
<string name="battery_optimization_not_supported_message">Seu dispositivo não requer ajustes de otimização de bateria. O bitchat funcionará normalmente.</string>
<string name="battery_optimization_success_message">O bitchat pode operar de forma confiável em segundo plano</string>
<string name="battery_optimization_benefits">• Entrega confiável de mensagens\n• Manutenção da conexão mesh\n• Encaminhamento em segundo plano\n• Evita quedas de conexão</string>
<string name="battery_optimization_check_again">Verificar novamente</string>
<string name="battery_optimization_skip">Pular agora</string>
<string name="battery_optimization_continue">Continuar</string>
<string name="retry">Tentar novamente</string>
<string name="skip">Pular</string>
<!-- Notificações -->
<string name="notification_summary_more">e mais %1$d</string>
<string name="notification_messages_from_people">%1$d mensagens de %2$d pessoas</string>
<string name="notification_more_conversations">e mais %1$d conversas</string>
<string name="notification_active_peers_title">👥 pessoas do bitchat por perto!</string>
<string name="notification_active_peers_one">1 pessoa por perto</string>
<string name="notification_active_peers_many">%1$d pessoas por perto</string>
<string name="notification_new_messages">Novas mensagens</string>
<string name="notification_new_location_messages">Novas mensagens de localização</string>
<string name="notification_mentions_in">Mencionado em %1$s</string>
<string name="notification_mentions_in_more">Mencionado em %1$s (+%2$d)</string>
<string name="notification_mentions_in_plural">%1$d menções em %2$s</string>
<string name="notification_new_activity_in">Nova atividade em %1$s</string>
<string name="notification_messages_in">Mensagens em %1$s</string>
<string name="notification_joined_conversation">%1$s entrou na conversa</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d menções</string>
<string name="notification_geohash_summary_title">bitchat Chats por localização</string>
<string name="notification_geohash_summary_text">%1$d mensagens de %2$d locais</string>
<string name="notification_mesh_mention_title_singular">Mencionado no chat mesh</string>
<string name="notification_mesh_mention_title_plural">%1$d menções no chat mesh</string>
<string name="notification_more_locations">e mais %1$d locais</string>
<string name="notification_and_more">e mais %1$d</string>
<!-- Acessibilidade de favoritos -->
<string name="cd_add_favorite">Adicionar aos favoritos</string>
<string name="cd_remove_favorite">Remover dos favoritos</string>
<string name="cd_add_bookmark">Adicionar favorito</string>
<!-- Cabeçalho do chat & acessibilidade -->
<string name="chat_back">voltar</string>
<string name="chat_channel_prefix">Canal: %1$s</string>
<string name="chat_leave">sair</string>
<string name="cd_nostr_reachable">Acessível via Nostr</string>
<string name="cd_unread_private_messages">Mensagens privadas não lidas</string>
<string name="cd_toggle_bookmark">Alternar favorito</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Status do Tor</string>
<string name="cd_connected_peers">Peers conectados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Pronto para handshake</string>
<string name="cd_handshake_in_progress">Handshake em andamento</string>
<string name="cd_encrypted">Criptografado de ponta a ponta</string>
<string name="cd_handshake_failed">Handshake falhou</string>
<!-- Diálogo do visualizador de arquivos -->
<string name="file_viewer_title">📎 Arquivo recebido</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Tamanho: %1$s</string>
<string name="file_viewer_type">🏷️ Tipo: %1$s</string>
<string name="file_viewer_open_save">📂 Abrir / Salvar</string>
<string name="close_with_emoji">❌ Fechar</string>
<string name="pick_image">Escolher imagem</string>
<!-- Sobre -->
<string name="about_tagline">chat mesh descentralizado com criptografia de ponta a ponta</string>
<string name="about_offline_mesh_title">Chat mesh offline</string>
<string name="about_offline_mesh_desc">Comunique diretamente via Bluetooth LE sem internet ou servidores. As mensagens são retransmitidas por dispositivos próximos para ampliar o alcance.</string>
<string name="about_online_geohash_title">Canais geohash online</string>
<string name="about_online_geohash_desc">Conecte-se com pessoas próximas através de canais baseados em geohash. Expanda a mesh por meio de relays públicos na internet.</string>
<string name="about_e2e_title">Criptografia de ponta a ponta</string>
<string name="about_e2e_desc">Mensagens privadas são criptografadas. Mensagens de canal são públicas.</string>
<string name="about_appearance">Aparência</string>
<string name="about_system">Sistema</string>
<string name="about_light">Claro</string>
<string name="about_dark">Escuro</string>
<string name="about_pow">Prova de Trabalho</string>
<string name="about_pow_off">PoW desligado</string>
<string name="about_pow_on">PoW ligado</string>
<string name="about_pow_tip">Adicione prova de trabalho às mensagens geohash para dificultar spam.</string>
<string name="about_pow_difficulty">Dificuldade: %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">Dificuldade %1$d requer ~%2$s tentativas de hash</string>
<string name="about_pow_desc_none">nenhuma prova de trabalho necessária</string>
<string name="about_pow_desc_very_low">muito baixa proteção mínima contra spam</string>
<string name="about_pow_desc_low">baixa proteção básica contra spam</string>
<string name="about_pow_desc_medium">média boa proteção contra spam</string>
<string name="about_pow_desc_high">alta proteção forte contra spam</string>
<string name="about_pow_desc_very_high">muito alta pode causar atrasos</string>
<string name="about_pow_desc_extreme">extrema requer muita capacidade de processamento</string>
<string name="about_network">Rede</string>
<string name="about_tor_off">Tor desligado</string>
<string name="about_tor_on">Tor ligado</string>
<string name="about_tor_route">Roteie o tráfego de internet via Tor para mais privacidade.</string>
<string name="about_tor_status">Status do Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Último: %1$s</string>
<string name="about_emergency_title">Limpeza de dados de emergência</string>
<string name="about_emergency_tip">Dica: Toque 3 vezes no título do app para apagar todos os dados salvos incluindo mensagens, chaves e configurações.</string>
<string name="about_debug_settings">Configurações de depuração</string>
<string name="about_footer">Código aberto • Privacidade em primeiro lugar • Descentralizado</string>
<string name="close_plain">Fechar</string>
<string name="cancel_lower">cancelar</string>
<!-- Descrições de conteúdo -->
<string name="cd_warning">Aviso</string>
<string name="cd_location_services">Serviços de localização</string>
<string name="cd_privacy">Privacidade</string>
<string name="cd_error">Erro</string>
<string name="cd_battery_optimization">Otimização de bateria</string>
<string name="cd_benefits">Benefícios</string>
<string name="cd_checking_battery_optimization">Verificando otimização de bateria</string>
<string name="cd_not_supported_battery_optimization">Otimização de bateria não suportada</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Mensagem não lida</string>
<string name="cd_open_map">Abrir mapa</string>
<string name="cd_remove_bookmark">Remover favorito</string>
<string name="cd_teleport">Teletransportar</string>
<string name="cd_selected">Selecionado</string>
<string name="cd_leave_channel">Sair do canal</string>
<string name="cd_reachable_via_nostr">Acessível via Nostr</string>
<string name="cd_offline_favorite">Favorito (offline)</string>
<string name="cd_decrease_precision">Diminuir precisão</string>
<string name="cd_increase_precision">Aumentar precisão</string>
<string name="cd_select_geohash">Selecionar geohash</string>
<string name="cd_scroll_to_bottom">Rolar para o fim</string>
<string name="cd_file">Arquivo</string>
<string name="cd_image">Imagem</string>
<string name="cd_cancel">Cancelar</string>
<string name="cd_link">Link</string>
<string name="cd_pick_media">Escolher mídia</string>
<string name="cd_pick_file">Escolher arquivo</string>
<string name="cd_save_current_image">Salvar imagem atual</string>
<string name="cd_close">Fechar</string>
<string name="cd_image_index_of">Imagem %1$d de %2$d</string>
<string name="cd_privacy_protected">Privacidade protegida</string>
<string name="cd_record_voice">Gravar nota de voz</string>
<string name="cd_offline_mesh_chat">Chat mesh offline</string>
<string name="cd_online_geohash_channels">Canais geohash online</string>
<string name="cd_end_to_end_encryption">Criptografia de ponta a ponta</string>
<!-- Imagens & arquivos -->
<string name="image_page_of">Imagem %1$d de %2$d</string>
<string name="image_unavailable">Imagem indisponível</string>
<string name="image_saved_to_downloads">Imagem salva em "Downloads"</string>
<string name="image_save_failed">Não foi possível salvar a imagem</string>
<string name="toast_image_saved">Imagem salva em "Downloads"</string>
<string name="toast_failed_to_save_image">Não foi possível salvar a imagem</string>
<string name="pick_file">Escolher arquivo</string>
<string name="file_unavailable">[Arquivo indisponível]</string>
<string name="unknown">desconhecido</string>
<!-- Ações do usuário -->
<string name="choose_action_message_or_user">Escolha uma ação para esta mensagem ou usuário</string>
<string name="choose_action_user">Escolha uma ação para este usuário</string>
<string name="action_copy_message_title">Copiar mensagem</string>
<string name="action_copy_message_subtitle">Copiar esta mensagem para a área de transferência</string>
<string name="action_slap_title">Dar um tapa em %1$s</string>
<string name="action_slap_subtitle">Enviar um tapa brincalhão</string>
<string name="action_hug_title">Abraçar %1$s</string>
<string name="action_hug_subtitle">Enviar um abraço amigável</string>
<string name="action_block_title">Bloquear %1$s</string>
<string name="action_block_subtitle">Bloquear todas as mensagens deste usuário</string>
<!-- Canais geohash -->
<string name="location_channels_title">#Canais de localização</string>
<string name="location_channels_desc">Converse com pessoas próximas através de canais geohash. Apenas um geohash aproximado é compartilhado, nunca dados exatos de GPS. Para preservar sua privacidade, não tire capturas de tela nem compartilhe esta tela.</string>
<string name="grant_location_permission">Conceder permissão de localização</string>
<string name="location_permission_denied">Permissão de localização negada. Ative nas configurações para usar canais de localização.</string>
<string name="open_settings">Abrir configurações</string>
<string name="location_permission_granted">\u2713 Permissão de localização concedida</string>
<string name="checking_permissions">Verificando permissões…</string>
<string name="finding_nearby_channels">Procurando canais próximos…</string>
<string name="bookmarked">Marcado</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">Geohash inválido</string>
<string name="teleport">teletransportar</string>
<string name="disable_location_services">Desativar serviços de localização</string>
<string name="enable_location_services">Ativar serviços de localização</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">Quadra</string>
<string name="location_level_neighborhood">Vizinhança</string>
<string name="location_level_city">Cidade</string>
<string name="location_level_province">Estado</string>
<string name="location_level_region">Região</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Depuração / Diagnóstico -->
<string name="debug_tools">Ferramentas de depuração</string>
<string name="debug_tools_desc">Ferramentas do desenvolvedor para diagnóstico e controle</string>
<string name="debug_verbose_logging">log detalhado</string>
<string name="debug_verbose_hint">Registra entradas/saídas de peers, direção da conexão, retransmissão de pacotes e relays</string>
<string name="debug_bluetooth_roles">Funções do Bluetooth</string>
<string name="debug_gatt_server">Servidor GATT</string>
<string name="debug_connections_fmt">Conexões: %1$d / %2$d</string>
<string name="debug_max_server">máx. servidor</string>
<string name="debug_gatt_client">Cliente GATT</string>
<string name="debug_max_client">máx. cliente</string>
<string name="debug_overall_connections_fmt">Conexões: %1$d / %2$d</string>
<string name="debug_max_overall">máx. geral</string>
<string name="debug_packet_relay">Retransmissão de pacotes</string>
<string name="debug_since_start_fmt">desde o início: %1$d</string>
<string name="debug_roles_hint">Alternar funções e fechar todas as conexões ao desativar</string>
<string name="debug_sync_settings">Configurações de sincronização</string>
<string name="debug_max_packets_per_sync_fmt">máx. pacotes por sincronização: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">máx. tamanho do filtro GCS: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">FPR alvo: %1$.2f%%</string>
<string name="debug_connected_devices">dispositivos conectados</string>
<string name="debug_our_device_id_fmt">nosso ID do dispositivo: %1$s</string>
<string name="debug_none">nenhum</string>
<string name="debug_disconnect">desconectar</string>
<string name="debug_recent_scan_results">dispositivos escaneados recentemente</string>
<string name="debug_connect">conectar</string>
<string name="debug_debug_console">Console de depuração</string>
<string name="debug_clear">limpar</string>
<string name="debug_relays_window_fmt">últimos 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P derivado: %1$s • itens máx. estimados: %2$s</string>
<string name="debug_direct_suffix"> • direto</string>
<string name="debug_role_server">como servidor (nós hospedamos)</string>
<string name="debug_role_client">como cliente (nós conectamos)</string>
<!-- Onboarding -->
<string name="location_services_required">Serviços de localização necessários</string>
<string name="privacy_first">Privacidade em primeiro lugar</string>
<string name="location_explanation">O bitchat NÃO rastreia sua localização.\n\nOs serviços de localização são necessários para a varredura do Bluetooth e o recurso de chat geohash.</string>
<string name="location_needs_for">O bitchat precisa de serviços de localização para:</string>
<string name="location_needs_bullets">• Varredura de dispositivos Bluetooth\n• Descobrir usuários próximos na rede mesh\n• Recurso de chat geohash\n• Sem rastreamento nem coleta de localização</string>
<string name="open_location_settings">Abrir configurações de localização</string>
<string name="check_again">Verificar novamente</string>
<string name="location_services_unavailable">Serviços de localização indisponíveis</string>
<string name="location_unavailable_explanation">Os serviços de localização não estão disponíveis neste dispositivo. Isso é incomum, pois serviços de localização são padrão em dispositivos Android.\n\nO bitchat requer serviços de localização para a varredura Bluetooth funcionar corretamente (requisito do Android). Sem isso, o app não consegue descobrir usuários próximos.</string>
<string name="checking_location_services">Verificando serviços de localização…</string>
<string name="bluetooth_required">Bluetooth necessário</string>
<string name="bluetooth_needs_for">O bitchat precisa de Bluetooth para:</string>
<string name="bluetooth_needs_bullets">• Descobrir usuários próximos\n• Criar conexões mesh\n• Enviar e receber mensagens\n• Funcionar sem internet ou servidores</string>
<string name="enable_bluetooth">Ativar Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth não suportado</string>
<string name="bluetooth_unsupported_explanation">Este dispositivo não suporta Bluetooth Low Energy (BLE), necessário para o bitchat.\n\nO BLE é necessário para criar redes mesh e comunicar com dispositivos próximos sem internet.</string>
<string name="checking_bluetooth_status">Verificando status do Bluetooth…</string>
<string name="battery_optimization_detected_title">Otimização de bateria detectada</string>
<string name="battery_optimization_enabled_title">Otimização de bateria ativada</string>
<string name="battery_optimization_explanation_short">O bitchat precisa rodar em segundo plano para manter conexões mesh. A otimização de bateria pode interromper essas conexões.</string>
<string name="benefits_of_disabling">Benefícios de desativar</string>
<string name="battery_benefits_short">• entrega confiável\n• mantém conectividade mesh\n• evita quedas</string>
<string name="disable_battery_optimization">Desativar otimização de bateria</string>
<string name="battery_optimization_disabled_title">Otimização de bateria desativada</string>
<string name="continue_btn">Continuar</string>
<string name="initializing_mesh_network">Inicializando rede mesh</string>
<string name="setting_up_bluetooth">Configurando rede mesh Bluetooth…</string>
<string name="should_take_seconds">Deve levar apenas alguns segundos</string>
<string name="setup_not_complete">Configuração não concluída</string>
<string name="try_again">Tentar novamente</string>
<string name="privacy_protected">Sua privacidade está protegida</string>
<string name="privacy_bullets">• sem rastreamento ou coleta de dados\n• chats mesh Bluetooth são totalmente offline\n• chats geohash usam internet</string>
<string name="permissions_header">Permissões</string>
<string name="grant_permissions">Conceder permissões</string>
<string name="location_tracking_warning">O bitchat NÃO rastreia sua localização</string>
<string name="geohash_people_header">PESSOAS</string>
<string name="nobody_around">ninguém por perto…</string>
<string name="you_suffix"> (você)</string>
<string name="pan_zoom_instruction">arraste/amplie para selecionar um geohash</string>
<string name="select">selecionar</string>
<string name="type_a_message_placeholder">Digite uma mensagem…</string>
<string name="mention">mencionar</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Imagem</string>
<string name="media_type_file">Arquivo</string>
<!-- Auxiliares de notificação -->
<string name="notification_sent_image">📷 enviou uma imagem</string>
<string name="notification_sent_voice">🎤 enviou uma mensagem de voz</string>
<string name="notification_sent_file">📎 enviou um arquivo</string>
<!-- Acessibilidade do player de voz -->
<string name="cd_play_voice">Reproduzir</string>
<string name="cd_pause_voice">Pausar</string>
<string name="cd_mining_pow">Minerando PoW</string>
<string name="cd_pow_enabled">PoW ativado</string>
<string name="cd_proof_of_work">Prova de Trabalho</string>
<string name="pow_mining_ellipsis">Minerando…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Descrições de permissões -->
<string name="perm_nearby_devices_desc">Necessário para descobrir usuários do bitchat via Bluetooth</string>
<string name="perm_nearby_devices_system">Permita que o bitchat se conecte a dispositivos próximos</string>
<string name="perm_location_desc">Necessário pelo Android para descobrir usuários próximos via Bluetooth</string>
<string name="perm_location_system">O bitchat precisa disso para escanear dispositivos próximos</string>
<string name="perm_notifications_desc">Receber notificações quando você receber mensagens privadas</string>
<string name="perm_notifications_system">Permita que o bitchat envie notificações</string>
<string name="perm_battery_desc">Desative a otimização de bateria para que o bitchat funcione de forma confiável em segundo plano e mantenha conexões mesh</string>
<string name="perm_battery_system">Permita que o bitchat funcione sem restrições de bateria</string>
<!-- Tipos de permissões -->
<string name="perm_type_nearby_devices">Dispositivos próximos</string>
<string name="perm_type_precise_location">Localização precisa</string>
<string name="perm_type_microphone">Microfone</string>
<string name="perm_type_notifications">Notificações</string>
<string name="perm_type_battery_optimization">Otimização de bateria</string>
<string name="perm_type_other">Outros</string>
<!-- Diálogo de senha -->
<string name="pwd_prompt_title">Digite a senha do canal</string>
<string name="pwd_prompt_message">O canal %1$s é protegido por senha. Digite a senha para entrar.</string>
<string name="pwd_label">Senha</string>
<string name="join">Entrar</string>
<string name="cancel">Cancelar</string>
<!-- Plurais -->
<plurals name="notification_and_more">
<item quantity="one">e mais %d</item>
<item quantity="other">e mais %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 pessoa</item>
<item quantity="other">%d pessoas</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d nota</item>
<item quantity="other">#%1$s ± 1 • %2$d notas</item>
</plurals>
<string name="location_notes_description">adicione notas curtas e permanentes a este local para que outros visitantes as encontrem.</string>
<string name="location_notes_relays_unavailable">relés geográficos indisponíveis; notas em pausa</string>
<string name="location_notes_no_relays_title">nenhum relé geográfico nas proximidades</string>
<string name="location_notes_no_relays_desc">as notas dependem de relés geográficos. verifique a conexão e tente novamente.</string>
<string name="loading_location_notes">carregando notas…</string>
<string name="location_notes_empty_title">ainda não há notas</string>
<string name="location_notes_empty_desc">seja o primeiro a adicionar uma para este local.</string>
<string name="dismiss">fechar</string>
<string name="location_notes_input_placeholder">adicione uma nota para este local</string>
</resources>
+365
View File
@@ -0,0 +1,365 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<!-- Justificativas de permissões -->
<string name="permission_bluetooth_rationale">A permissão do Bluetooth é necessária para conversar diretamente com outros sem internet.</string>
<string name="permission_location_rationale">A permissão de localização é necessária para encontrar dispositivos próximos via Bluetooth.</string>
<string name="permission_notification_rationale">A permissão de notificações é necessária para alertá-lo sobre novas mensagens.</string>
<!-- Placeholders / UI básica -->
<string name="nickname_hint">Apelido</string>
<string name="message_hint">Digite uma mensagem…</string>
<string name="channel_password_hint">Palavra-passe</string>
<string name="join_channel">Juntar-se ao canal</string>
<string name="leave_channel">Sair</string>
<string name="send_message">Enviar</string>
<string name="show_commands">Mostrar comandos</string>
<string name="back">Voltar</string>
<string name="people">Pessoas</string>
<string name="channels">Canais</string>
<string name="online_users">Utilizadores online</string>
<string name="no_one_connected">Ninguém ligado</string>
<string name="emergency_clear_hint">Toque três vezes para apagar todos os dados</string>
<string name="your_network">A sua rede</string>
<!-- Otimização da bateria -->
<string name="battery_optimization_detected">Detetada otimização da bateria</string>
<string name="battery_optimization_disabled">Otimização da bateria desativada</string>
<string name="battery_optimization_not_required">Otimização da bateria não necessária</string>
<string name="battery_optimization_checking">A verificar otimização da bateria</string>
<string name="battery_optimization_why_disable">Por que desativar a otimização da bateria?</string>
<string name="battery_optimization_explanation">O bitchat funciona em segundo plano para manter conexões de rede mesh com dispositivos próximos. A otimização da bateria pode interromper essas conexões, fazendo com que as mensagens cheguem atrasadas ou se percam.\n\nDesativar a otimização da bateria garante comunicação peer-to-peer confiável.</string>
<string name="battery_optimization_disable_button">Desativar otimização da bateria</string>
<string name="battery_optimization_note">Nota: Pode alterar isso posteriormente em Definições do Android &gt; Aplicações &gt; bitchat &gt; Bateria.</string>
<string name="battery_optimization_not_supported_explanation">O seu dispositivo não requer definições de otimização da bateria. O bitchat funcionará normalmente.</string>
<string name="battery_optimization_not_supported_message">O seu dispositivo não requer definições de otimização da bateria. O bitchat funcionará normalmente.</string>
<string name="battery_optimization_success_message">O bitchat pode funcionar de forma confiável em segundo plano</string>
<string name="battery_optimization_benefits">• Entrega confiável de mensagens\n• Manutenção da conexão mesh\n• Reencaminhamento de mensagens em segundo plano\n• Previne desconexões</string>
<string name="battery_optimization_check_again">Verificar novamente</string>
<string name="battery_optimization_skip">Ignorar por agora</string>
<string name="battery_optimization_continue">Continuar</string>
<string name="retry">Tentar novamente</string>
<string name="skip">Ignorar</string>
<!-- Notificações -->
<string name="notification_summary_more">e mais %1$d</string>
<string name="notification_messages_from_people">%1$d mensagens de %2$d pessoas</string>
<string name="notification_more_conversations">e mais %1$d conversas</string>
<string name="notification_active_peers_title">👥 bitchatters por perto!</string>
<string name="notification_active_peers_one">1 pessoa por perto</string>
<string name="notification_active_peers_many">%1$d pessoas por perto</string>
<string name="notification_new_messages">Novas mensagens</string>
<string name="notification_new_location_messages">Novas mensagens de localização</string>
<string name="notification_mentions_in">Mencionado em %1$s</string>
<string name="notification_mentions_in_more">Mencionado em %1$s (+%2$d)</string>
<string name="notification_mentions_in_plural">%1$d menções em %2$s</string>
<string name="notification_new_activity_in">Nova atividade em %1$s</string>
<string name="notification_messages_in">Mensagens em %1$s</string>
<string name="notification_joined_conversation">%1$s juntou-se à conversa</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d menções</string>
<string name="notification_geohash_summary_title">bitchat Conversas de localização</string>
<string name="notification_geohash_summary_text">%1$d mensagens de %2$d localizações</string>
<string name="notification_mesh_mention_title_singular">Mencionado no chat mesh</string>
<string name="notification_mesh_mention_title_plural">%1$d menções no chat mesh</string>
<string name="notification_more_locations">e mais %1$d localizações</string>
<string name="notification_and_more">e mais %1$d</string>
<!-- Acessibilidade de favoritos -->
<string name="cd_add_favorite">Adicionar aos favoritos</string>
<string name="cd_remove_favorite">Remover dos favoritos</string>
<string name="cd_add_bookmark">Adicionar marcador</string>
<!-- Cabeçalho do chat e acessibilidade -->
<string name="chat_back">voltar</string>
<string name="chat_channel_prefix">Canal: %1$s</string>
<string name="chat_leave">sair</string>
<string name="cd_nostr_reachable">Alcançável via Nostr</string>
<string name="cd_unread_private_messages">Mensagens privadas não lidas</string>
<string name="cd_toggle_bookmark">Alternar marcador</string>
<string name="cd_teleported">Teletransportado</string>
<string name="cd_tor_status">Estado do Tor</string>
<string name="cd_connected_peers">Pares ligados</string>
<string name="cd_geohash_participants">Participantes geohash</string>
<string name="cd_ready_for_handshake">Pronto para handshake</string>
<string name="cd_handshake_in_progress">Handshake em andamento</string>
<string name="cd_encrypted">Encriptado ponto a ponto</string>
<string name="cd_handshake_failed">Handshake falhado</string>
<!-- Diálogo do visualizador de ficheiros -->
<string name="file_viewer_title">📎 Ficheiro recebido</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Tamanho: %1$s</string>
<string name="file_viewer_type">🏷️ Tipo: %1$s</string>
<string name="file_viewer_open_save">📂 Abrir / Guardar</string>
<string name="close_with_emoji">❌ Fechar</string>
<string name="pick_image">Escolher imagem</string>
<!-- Folha sobre -->
<string name="about_tagline">chat mesh descentralizado com encriptação ponto a ponto</string>
<string name="about_offline_mesh_title">Chat mesh offline</string>
<string name="about_offline_mesh_desc">Comunique diretamente via Bluetooth LE sem internet ou servidores. As mensagens são retransmitidas através de dispositivos próximos para estender o alcance.</string>
<string name="about_online_geohash_title">Canais geohash online</string>
<string name="about_online_geohash_desc">Conecte-se com pessoas perto de si através de canais baseados em geohash. Estenda a mesh através de repetidores de internet pública.</string>
<string name="about_e2e_title">Encriptação ponto a ponto</string>
<string name="about_e2e_desc">Mensagens privadas são encriptadas. Mensagens de canal são públicas.</string>
<string name="about_appearance">Aparência</string>
<string name="about_system">Sistema</string>
<string name="about_light">Claro</string>
<string name="about_dark">Escuro</string>
<string name="about_pow">Prova de Trabalho</string>
<string name="about_pow_off">PoW desligado</string>
<string name="about_pow_on">PoW ligado</string>
<string name="about_pow_tip">Adicionar prova de trabalho às mensagens geohash para tornar o spam mais difícil.</string>
<string name="about_pow_difficulty">Dificuldade: %1$d bits (~%2$s)</string>
<string name="about_pow_difficulty_attempts">Dificuldade %1$d requer ~%2$s tentativas de hash</string>
<string name="about_pow_desc_none">nenhuma prova de trabalho necessária</string>
<string name="about_pow_desc_very_low">muito baixo proteção mínima contra spam</string>
<string name="about_pow_desc_low">baixo proteção básica contra spam</string>
<string name="about_pow_desc_medium">médio boa proteção contra spam</string>
<string name="about_pow_desc_high">alto proteção forte contra spam</string>
<string name="about_pow_desc_very_high">muito alto pode causar atrasos</string>
<string name="about_pow_desc_extreme">extremo requer potência computacional significativa</string>
<string name="about_network">Rede</string>
<string name="about_tor_off">Tor desligado</string>
<string name="about_tor_on">Tor ligado</string>
<string name="about_tor_route">Encaminhar tráfego de internet através do Tor para maior privacidade.</string>
<string name="about_tor_status">Estado do Tor: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Último: %1$s</string>
<string name="about_emergency_title">Limpeza de dados de emergência</string>
<string name="about_emergency_tip">Dica: Toque três vezes no título da aplicação para apagar todos os dados guardados incluindo mensagens, chaves e definições.</string>
<string name="about_debug_settings">Definições de depuração</string>
<string name="about_footer">Código aberto • Privacidade primeiro • Descentralizado</string>
<string name="close_plain">Fechar</string>
<string name="cancel_lower">cancelar</string>
<!-- Descrições de conteúdo gerais -->
<string name="cd_warning">Aviso</string>
<string name="cd_location_services">Serviços de localização</string>
<string name="cd_privacy">Privacidade</string>
<string name="cd_error">Erro</string>
<string name="cd_battery_optimization">Otimização da bateria</string>
<string name="cd_benefits">Benefícios</string>
<string name="cd_checking_battery_optimization">A verificar otimização da bateria</string>
<string name="cd_not_supported_battery_optimization">Otimização da bateria não suportada</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Mensagem não lida</string>
<string name="cd_open_map">Abrir mapa</string>
<string name="cd_remove_bookmark">Remover marcador</string>
<string name="cd_teleport">Teletransportar</string>
<string name="cd_selected">Selecionado</string>
<string name="cd_leave_channel">Sair do canal</string>
<string name="cd_reachable_via_nostr">Alcançável via Nostr</string>
<string name="cd_offline_favorite">Favorito (offline)</string>
<string name="cd_decrease_precision">Diminuir precisão</string>
<string name="cd_increase_precision">Aumentar precisão</string>
<string name="cd_select_geohash">Selecionar geohash</string>
<string name="cd_scroll_to_bottom">Deslocar para baixo</string>
<string name="cd_file">Ficheiro</string>
<string name="cd_image">Imagem</string>
<string name="cd_cancel">Cancelar</string>
<string name="cd_link">Ligação</string>
<string name="cd_pick_media">Escolher multimédia</string>
<string name="cd_pick_file">Escolher ficheiro</string>
<string name="cd_save_current_image">Guardar imagem atual</string>
<string name="cd_close">Fechar</string>
<string name="cd_image_index_of">Imagem %1$d de %2$d</string>
<string name="cd_privacy_protected">Privacidade protegida</string>
<string name="cd_record_voice">Gravar nota de voz</string>
<string name="cd_offline_mesh_chat">Chat mesh offline</string>
<string name="cd_online_geohash_channels">Canais geohash online</string>
<string name="cd_end_to_end_encryption">Encriptação ponto a ponto</string>
<!-- Imagens e ficheiros -->
<string name="image_page_of">Imagem %1$d de %2$d</string>
<string name="image_unavailable">Imagem indisponível</string>
<string name="image_saved_to_downloads">Imagem guardada em "Transferências"</string>
<string name="image_save_failed">Não foi possível guardar a imagem</string>
<string name="toast_image_saved">Imagem guardada em "Transferências"</string>
<string name="toast_failed_to_save_image">Não foi possível guardar a imagem</string>
<string name="pick_file">Escolher ficheiro</string>
<string name="file_unavailable">[Ficheiro indisponível]</string>
<string name="unknown">desconhecido</string>
<!-- Folha de ações do utilizador -->
<string name="choose_action_message_or_user">Escolher ação para esta mensagem ou utilizador</string>
<string name="choose_action_user">Escolher ação para este utilizador</string>
<string name="action_copy_message_title">Copiar mensagem</string>
<string name="action_copy_message_subtitle">Copiar esta mensagem para a área de transferência</string>
<string name="action_slap_title">Dar uma palmada em %1$s</string>
<string name="action_slap_subtitle">Enviar uma palmada brincalhona</string>
<string name="action_hug_title">Abraçar %1$s</string>
<string name="action_hug_subtitle">Enviar um abraço amigável</string>
<string name="action_block_title">Bloquear %1$s</string>
<string name="action_block_subtitle">Bloquear todas as mensagens deste utilizador</string>
<!-- Folha de canais geohash -->
<string name="location_channels_title">#Canais de localização</string>
<string name="location_channels_desc">Converse com pessoas perto de si através de canais geohash. Apenas um geohash aproximado é partilhado, nunca dados GPS exatos. Para preservar a sua privacidade, não tire capturas de ecrã nem partilhe este ecrã.</string>
<string name="grant_location_permission">Conceder permissão de localização</string>
<string name="location_permission_denied">Permissão de localização negada. Ative nas definições para usar canais de localização.</string>
<string name="open_settings">Abrir definições</string>
<string name="location_permission_granted">\u2713 Permissão de localização concedida</string>
<string name="checking_permissions">A verificar permissões…</string>
<string name="finding_nearby_channels">A procurar canais próximos…</string>
<string name="bookmarked">Marcado</string>
<string name="geohash_placeholder">Geohash</string>
<string name="invalid_geohash">Geohash inválido</string>
<string name="teleport">teletransportar</string>
<string name="disable_location_services">Desativar serviços de localização</string>
<string name="enable_location_services">Ativar serviços de localização</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">Quarteirão</string>
<string name="location_level_neighborhood">Bairro</string>
<string name="location_level_city">Cidade</string>
<string name="location_level_province">Província</string>
<string name="location_level_region">Região</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<!-- Depuração / Diagnóstico -->
<string name="debug_tools">Ferramentas de depuração</string>
<string name="debug_tools_desc">Ferramentas de programador para diagnóstico e controlo</string>
<string name="debug_verbose_logging">registo detalhado</string>
<string name="debug_verbose_hint">Regista entradas/saídas de pares, direção de conexão, retransmissão de pacotes e repetidores</string>
<string name="debug_bluetooth_roles">Funções Bluetooth</string>
<string name="debug_gatt_server">Servidor GATT</string>
<string name="debug_connections_fmt">Conexões: %1$d / %2$d</string>
<string name="debug_max_server">máx. servidor</string>
<string name="debug_gatt_client">Cliente GATT</string>
<string name="debug_max_client">máx. cliente</string>
<string name="debug_overall_connections_fmt">Conexões: %1$d / %2$d</string>
<string name="debug_max_overall">máx. geral</string>
<string name="debug_packet_relay">Retransmissão de pacotes</string>
<string name="debug_since_start_fmt">desde o início: %1$d</string>
<string name="debug_roles_hint">Alternar funções ligado/desligado e fechar todas as conexões ao desativar</string>
<string name="debug_sync_settings">Definições de sincronização</string>
<string name="debug_max_packets_per_sync_fmt">máx. pacotes por sincronização: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">máx. tamanho do filtro GCS: %1$d bytes (1281024)</string>
<string name="debug_target_fpr_fmt">FPR alvo: %1$.2f%%</string>
<string name="debug_connected_devices">dispositivos ligados</string>
<string name="debug_our_device_id_fmt">nosso ID do dispositivo: %1$s</string>
<string name="debug_none">nenhum</string>
<string name="debug_disconnect">desligar</string>
<string name="debug_recent_scan_results">dispositivos digitalizados recentemente</string>
<string name="debug_connect">ligar</string>
<string name="debug_debug_console">Consola de depuração</string>
<string name="debug_clear">limpar</string>
<string name="debug_relays_window_fmt">últimos 10s: %1$d • 1m: %2$d • 15m: %3$d</string>
<string name="debug_derived_p_fmt">P derivado: %1$s • máx. itens estimados: %2$s</string>
<string name="debug_direct_suffix"> • direto</string>
<string name="debug_role_server">como servidor (nós hospedamos)</string>
<string name="debug_role_client">como cliente (nós ligamos)</string>
<!-- Ecrãs de integração -->
<string name="location_services_required">Serviços de localização necessários</string>
<string name="privacy_first">Privacidade primeiro</string>
<string name="location_explanation">O bitchat NÃO rastreia a sua localização.\n\nOs serviços de localização são necessários para a digitalização Bluetooth e a funcionalidade de chat geohash.</string>
<string name="location_needs_for">O bitchat precisa de serviços de localização para:</string>
<string name="location_needs_bullets">• Digitalização de dispositivos Bluetooth\n• Descobrir utilizadores próximos na rede mesh\n• Funcionalidade de chat geohash\n• Sem rastreamento ou recolha de localização</string>
<string name="open_location_settings">Abrir definições de localização</string>
<string name="check_again">Verificar novamente</string>
<string name="location_services_unavailable">Serviços de localização indisponíveis</string>
<string name="location_unavailable_explanation">Os serviços de localização não estão disponíveis neste dispositivo. Isto é incomum, uma vez que os serviços de localização são padrão em dispositivos Android.\n\nO bitchat requer serviços de localização para o funcionamento adequado da digitalização Bluetooth (requisito do Android). Sem isso, a aplicação não pode descobrir utilizadores próximos.</string>
<string name="checking_location_services">A verificar serviços de localização…</string>
<string name="bluetooth_required">Bluetooth necessário</string>
<string name="bluetooth_needs_for">O bitchat precisa de Bluetooth para:</string>
<string name="bluetooth_needs_bullets">• Descobrir utilizadores próximos\n• Criar conexões de rede mesh\n• Enviar e receber mensagens\n• Funcionar sem internet ou servidores</string>
<string name="enable_bluetooth">Ativar Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth não suportado</string>
<string name="bluetooth_unsupported_explanation">Este dispositivo não suporta Bluetooth Low Energy (BLE), que é necessário para o bitchat funcionar.\n\nO BLE é necessário para criar redes mesh e comunicar com dispositivos próximos sem internet.</string>
<string name="checking_bluetooth_status">A verificar estado do Bluetooth…</string>
<string name="battery_optimization_detected_title">Otimização da bateria detetada</string>
<string name="battery_optimization_enabled_title">Otimização da bateria ativada</string>
<string name="battery_optimization_explanation_short">O bitchat precisa de funcionar em segundo plano para manter conexões mesh. A otimização da bateria pode interromper essas conexões.</string>
<string name="benefits_of_disabling">Benefícios de desativar</string>
<string name="battery_benefits_short">• entrega confiável de mensagens\n• mantém conectividade mesh\n• previne desconexões</string>
<string name="disable_battery_optimization">Desativar otimização da bateria</string>
<string name="battery_optimization_disabled_title">Otimização da bateria desativada</string>
<string name="continue_btn">Continuar</string>
<string name="initializing_mesh_network">A inicializar rede mesh</string>
<string name="setting_up_bluetooth">A configurar rede mesh Bluetooth…</string>
<string name="should_take_seconds">Isto deve demorar apenas alguns segundos</string>
<string name="setup_not_complete">Configuração não concluída</string>
<string name="try_again">Tentar novamente</string>
<string name="privacy_protected">A sua privacidade está protegida</string>
<string name="privacy_bullets">• sem rastreamento ou recolha de dados\n• chats mesh Bluetooth são completamente offline\n• chats geohash usam internet</string>
<string name="permissions_header">Permissões</string>
<string name="grant_permissions">Conceder permissões</string>
<string name="location_tracking_warning">O bitchat NÃO rastreia a sua localização</string>
<string name="geohash_people_header">PESSOAS</string>
<string name="nobody_around">ninguém por perto…</string>
<string name="you_suffix"> (você)</string>
<string name="pan_zoom_instruction">arraste e amplie para selecionar um geohash</string>
<string name="select">selecionar</string>
<string name="type_a_message_placeholder">Digite uma mensagem…</string>
<string name="mention">mencionar</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="version_prefix">v%1$s</string>
<string name="image_star">image/*</string>
<string name="media_type_image">Imagem</string>
<string name="media_type_file">Ficheiro</string>
<!-- Auxiliares de texto de notificação -->
<string name="notification_sent_image">📷 enviou uma imagem</string>
<string name="notification_sent_voice">🎤 enviou uma nota de voz</string>
<string name="notification_sent_file">📎 enviou um ficheiro</string>
<!-- Acessibilidade do reprodutor de voz -->
<string name="cd_play_voice">Reproduzir</string>
<string name="cd_pause_voice">Pausar</string>
<string name="cd_mining_pow">A minerar PoW</string>
<string name="cd_pow_enabled">PoW ativado</string>
<string name="cd_proof_of_work">Prova de Trabalho</string>
<string name="pow_mining_ellipsis">A minerar…</string>
<string name="pow_label_format">pow: %1$dbit</string>
<!-- Descrições de permissões -->
<string name="perm_nearby_devices_desc">Necessário para descobrir utilizadores bitchat via Bluetooth</string>
<string name="perm_nearby_devices_system">Permitir que o bitchat se ligue a dispositivos próximos</string>
<string name="perm_location_desc">Requerido pelo Android para descobrir utilizadores bitchat próximos via Bluetooth</string>
<string name="perm_location_system">O bitchat precisa disto para digitalizar dispositivos próximos</string>
<string name="perm_notifications_desc">Receber notificações quando recebe mensagens privadas</string>
<string name="perm_notifications_system">Permitir que o bitchat lhe envie notificações</string>
<string name="perm_battery_desc">Desativar otimização da bateria para garantir que o bitchat funcione de forma confiável em segundo plano e mantenha conexões de rede mesh</string>
<string name="perm_battery_system">Permitir que o bitchat funcione sem restrições de bateria</string>
<!-- Tipos de permissões -->
<string name="perm_type_nearby_devices">Dispositivos próximos</string>
<string name="perm_type_precise_location">Localização precisa</string>
<string name="perm_type_microphone">Microfone</string>
<string name="perm_type_notifications">Notificações</string>
<string name="perm_type_battery_optimization">Otimização da bateria</string>
<string name="perm_type_other">Outro</string>
<!-- Diálogo de palavra-passe -->
<string name="pwd_prompt_title">Inserir palavra-passe do canal</string>
<string name="pwd_prompt_message">O canal %1$s está protegido por palavra-passe. Insira a palavra-passe para entrar.</string>
<string name="pwd_label">Palavra-passe</string>
<string name="join">Entrar</string>
<string name="cancel">Cancelar</string>
<!-- Plurais -->
<plurals name="notification_and_more">
<item quantity="one">e mais %d</item>
<item quantity="other">e mais %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 pessoa</item>
<item quantity="other">%d pessoas</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d nota</item>
<item quantity="other">#%1$s ± 1 • %2$d notas</item>
</plurals>
<string name="location_notes_description">adicione notas curtas e permanentes a este local para que outros visitantes as encontrem.</string>
<string name="location_notes_relays_unavailable">relés geográficos indisponíveis; notas em pausa</string>
<string name="location_notes_no_relays_title">nenhum relé geográfico nas proximidades</string>
<string name="location_notes_no_relays_desc">as notas dependem de relés geográficos. verifique a conexão e tente novamente.</string>
<string name="loading_location_notes">carregando notas…</string>
<string name="location_notes_empty_title">ainda não há notas</string>
<string name="location_notes_empty_desc">seja o primeiro a adicionar uma para este local.</string>
<string name="dismiss">fechar</string>
<string name="location_notes_input_placeholder">adicione uma nota para este local</string>
</resources>
+355
View File
@@ -0,0 +1,355 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<string name="permission_bluetooth_rationale">Требуется разрешение Bluetooth для общения p2p без интернета.</string>
<string name="permission_location_rationale">Требуется доступ к геопозиции для поиска ближайших устройств по Bluetooth.</string>
<string name="permission_notification_rationale">Требуется доступ к уведомлениям для оповещения о новых сообщениях.</string>
<string name="nickname_hint">ник</string>
<string name="message_hint">введите сообщение…</string>
<string name="channel_password_hint">Пароль</string>
<string name="join_channel">Войти в канал</string>
<string name="leave_channel">Покинуть</string>
<string name="send_message">Отправить</string>
<string name="show_commands">Показать команды</string>
<string name="back">Назад</string>
<string name="people">Люди</string>
<string name="channels">Каналы</string>
<string name="online_users">Пользователи онлайн</string>
<string name="no_one_connected">Нет подключённых</string>
<string name="emergency_clear_hint">Тройной тап для удаления всех данных</string>
<string name="your_network">Сеть</string>
<string name="battery_optimization_detected">Обнаружена оптимизация батареи</string>
<string name="battery_optimization_disabled">Оптимизация батареи отключена</string>
<string name="battery_optimization_not_required">Оптимизация батареи не требуется</string>
<string name="battery_optimization_checking">Проверка оптимизации батареи</string>
<string name="battery_optimization_why_disable">Зачем отключать оптимизацию?</string>
<string name="battery_optimization_explanation">bitchat работает в фоне для поддержания mesh‑подключений с ближайшими устройствами. Оптимизация батареи может их прервать, что ведёт к задержкам и потерям сообщений.\n\nОтключение гарантирует надёжный обмен p2p.</string>
<string name="battery_optimization_disable_button">Отключить оптимизацию</string>
<string name="battery_optimization_note">Примечание: это можно изменить позже в Настройки Android &gt; Приложения &gt; bitchat &gt; Батарея</string>
<string name="battery_optimization_not_supported_explanation">На вашем устройстве не требуются настройки оптимизации. bitchat будет работать штатно.</string>
<string name="battery_optimization_not_supported_message">На вашем устройстве не требуются настройки оптимизации. bitchat будет работать штатно.</string>
<string name="battery_optimization_success_message">bitchat может надёжно работать в фоне</string>
<string name="battery_optimization_benefits">• Надёжная доставка сообщений\n• Поддержка mesh‑связи\n• Фоновая ретрансляция\n• Предотвращение обрывов связи</string>
<string name="battery_optimization_check_again">Проверить снова</string>
<string name="battery_optimization_skip">Пропустить пока</string>
<string name="battery_optimization_continue">Продолжить</string>
<string name="retry">Повторить</string>
<string name="skip">Пропустить</string>
<string name="notification_summary_more">и ещё %1$d</string>
<string name="notification_messages_from_people">%1$d сообщений от %2$d людей</string>
<string name="notification_more_conversations">и ещё %1$d бесед</string>
<string name="notification_active_peers_title">👥 bitchatter рядом!</string>
<string name="notification_active_peers_one">Рядом 1 человек</string>
<string name="notification_active_peers_many">Рядом %1$d человек</string>
<string name="notification_new_messages">Новые сообщения</string>
<string name="notification_new_location_messages">Новые сообщения локаций</string>
<string name="notification_mentions_in">Упоминание в %1$s</string>
<string name="notification_mentions_in_more">Упоминание в %1$s (+%2$d)</string>
<string name="notification_mentions_in_plural">%1$d упоминаний в %2$s</string>
<string name="notification_new_activity_in">Новая активность в %1$s</string>
<string name="notification_messages_in">Сообщения в %1$s</string>
<string name="notification_joined_conversation">%1$s присоединился к беседе</string>
<string name="notification_geohash_summary_title_mentions">bitchat — %1$d упоминаний</string>
<string name="notification_geohash_summary_title">bitchat — чаты по локациям</string>
<string name="notification_geohash_summary_text">%1$d сообщений из %2$d локаций</string>
<string name="notification_mesh_mention_title_singular">Упоминание в Mesh‑чате</string>
<string name="notification_mesh_mention_title_plural">%1$d упоминаний в Mesh‑чате</string>
<string name="notification_more_locations">и ещё %1$d локаций</string>
<string name="notification_and_more">и ещё %1$d</string>
<string name="cd_add_favorite">В избранное</string>
<string name="cd_remove_favorite">Убрать из избранного</string>
<string name="cd_add_bookmark">Добавить закладку</string>
<string name="chat_back">назад</string>
<string name="chat_channel_prefix">канал: %1$s</string>
<string name="chat_leave">выйти</string>
<string name="cd_nostr_reachable">Доступен через Nostr</string>
<string name="cd_unread_private_messages">Непрочитанные личные</string>
<string name="cd_toggle_bookmark">Переключить закладку</string>
<string name="cd_teleported">Телепортировано</string>
<string name="cd_tor_status">Статус Tor</string>
<string name="cd_connected_peers">Подключённые узлы</string>
<string name="cd_geohash_participants">Участники geohash</string>
<string name="cd_ready_for_handshake">Готов к рукопожатию</string>
<string name="cd_handshake_in_progress">Рукопожатие…</string>
<string name="cd_encrypted">Сквозное шифрование</string>
<string name="cd_handshake_failed">Не удалось договориться</string>
<string name="file_viewer_title">📎 Получен файл</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Размер: %1$s</string>
<string name="file_viewer_type">🏷️ Тип: %1$s</string>
<string name="file_viewer_open_save">📂 Открыть / Сохранить</string>
<string name="close_with_emoji">❌ Закрыть</string>
<string name="pick_image">Выбрать изображение</string>
<string name="about_tagline">децентрализованный mesh‑чат со сквозным шифрованием</string>
<string name="about_offline_mesh_title">Оффлайн Mesh‑чат</string>
<string name="about_offline_mesh_desc">Общение напрямую по Bluetooth LE без интернета и серверов. Сообщения ретранслируются близлежащими устройствами.</string>
<string name="about_online_geohash_title">Онлайн‑каналы Geohash</string>
<string name="about_online_geohash_desc">Общайся с людьми поблизости через каналы на основе geohash. Расширяй mesh через публичные ретрансляторы.</string>
<string name="about_e2e_title">Сквозное шифрование</string>
<string name="about_e2e_desc">Личные сообщения — зашифрованы. Канальные — публичны.</string>
<string name="about_appearance">оформление</string>
<string name="about_system">система</string>
<string name="about_light">светлая</string>
<string name="about_dark">тёмная</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">pow выкл</string>
<string name="about_pow_on">pow вкл</string>
<string name="about_pow_tip">добавь proof of work к сообщениям geohash для защиты от спама.</string>
<string name="about_pow_difficulty">сложность: %1$d бит (~%2$s)</string>
<string name="about_pow_difficulty_attempts">сложность %1$d ≈ ~%2$s попыток хеширования</string>
<string name="about_pow_desc_none">proof of work не требуется</string>
<string name="about_pow_desc_very_low">очень низкая — минимальная защита</string>
<string name="about_pow_desc_low">низкая — базовая защита</string>
<string name="about_pow_desc_medium">средняя — хорошая защита</string>
<string name="about_pow_desc_high">высокая — сильная защита</string>
<string name="about_pow_desc_very_high">очень высокая — возможны задержки</string>
<string name="about_pow_desc_extreme">экстремальная — требуется много вычислений</string>
<string name="about_network">сеть</string>
<string name="about_tor_off">tor выкл</string>
<string name="about_tor_on">tor вкл</string>
<string name="about_tor_route">направляй интернет через Tor для приватности.</string>
<string name="about_tor_status">статус Tor: %1$s, загрузка %2$d%%</string>
<string name="about_last">Последнее: %1$s</string>
<string name="about_emergency_title">Экстренное удаление данных</string>
<string name="about_emergency_tip">Совет: тройной тап по заголовку — удалить все данные (сообщения, ключи, настройки).</string>
<string name="about_debug_settings">Настройки отладки</string>
<string name="about_footer">Open Source • Privacy First • Децентрализация</string>
<string name="close_plain">Закрыть</string>
<string name="cancel_lower">отмена</string>
<string name="cd_warning">Предупреждение</string>
<string name="cd_location_services">Службы локации</string>
<string name="cd_privacy">Приватность</string>
<string name="cd_error">Ошибка</string>
<string name="cd_battery_optimization">Оптимизация батареи</string>
<string name="cd_benefits">Преимущества</string>
<string name="cd_checking_battery_optimization">Проверка оптимизации</string>
<string name="cd_not_supported_battery_optimization">Не поддерживается</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Непрочитанное сообщение</string>
<string name="cd_open_map">Открыть карту</string>
<string name="cd_remove_bookmark">Удалить закладку</string>
<string name="cd_teleport">Телепорт</string>
<string name="cd_selected">Выбрано</string>
<string name="cd_leave_channel">Покинуть канал</string>
<string name="cd_reachable_via_nostr">Доступен через Nostr</string>
<string name="cd_offline_favorite">Избранное (оффлайн)</string>
<string name="cd_decrease_precision">Уменьшить точность</string>
<string name="cd_increase_precision">Увеличить точность</string>
<string name="cd_select_geohash">Выбрать geohash</string>
<string name="cd_scroll_to_bottom">Прокрутить вниз</string>
<string name="cd_file">Файл</string>
<string name="cd_image">Изображение</string>
<string name="cd_cancel">Отмена</string>
<string name="cd_link">Ссылка</string>
<string name="cd_pick_media">Выбрать медиа</string>
<string name="cd_record_voice">Записать голос</string>
<string name="cd_offline_mesh_chat">Оффлайн Mesh‑чат</string>
<string name="cd_online_geohash_channels">Онлайн‑каналы Geohash</string>
<string name="cd_end_to_end_encryption">Сквозное шифрование</string>
<string name="image_page_of">Изображение %1$d / %2$d</string>
<string name="image_unavailable">Изображение недоступно</string>
<string name="image_saved_to_downloads">Изображение сохранено в «Загрузки»</string>
<string name="image_save_failed">Не удалось сохранить изображение</string>
<string name="pick_file">Выбрать файл</string>
<string name="file_unavailable">[файл недоступен]</string>
<string name="unknown">неизвестно</string>
<string name="choose_action_message_or_user">выберите действие для сообщения или пользователя</string>
<string name="choose_action_user">выберите действие для пользователя</string>
<string name="action_copy_message_title">копировать сообщение</string>
<string name="action_copy_message_subtitle">скопировать сообщение в буфер</string>
<string name="action_slap_title">дать пощёчину %1$s</string>
<string name="action_slap_subtitle">отправить шутливую пощёчину</string>
<string name="action_hug_title">обнять %1$s</string>
<string name="action_hug_subtitle">отправить дружеские объятия</string>
<string name="action_block_title">заблокировать %1$s</string>
<string name="action_block_subtitle">заблокировать все сообщения от этого пользователя</string>
<string name="location_channels_title">#каналы локации</string>
<string name="location_channels_desc">общайся с людьми рядом через каналы geohash. делится только грубый geohash, никогда точный gps. не делай скриншоты и не делись экраном для защиты приватности.</string>
<string name="grant_location_permission">выдать доступ к локации</string>
<string name="location_permission_denied">доступ к локации запрещён. включите в настройках для использования каналов.</string>
<string name="open_settings">Открыть настройки</string>
<string name="location_permission_granted">\u2713 доступ к локации выдан</string>
<string name="checking_permissions">проверка разрешений…</string>
<string name="finding_nearby_channels">поиск близких каналов…</string>
<string name="bookmarked">в закладках</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">некорректный geohash</string>
<string name="teleport">телепорт</string>
<string name="disable_location_services">отключить службы локации</string>
<string name="enable_location_services">включить службы локации</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">квартал</string>
<string name="location_level_neighborhood">район</string>
<string name="location_level_city">город</string>
<string name="location_level_province">область</string>
<string name="location_level_region">регион</string>
<string name="debug_tools">инструменты отладки</string>
<string name="debug_verbose_logging">подробное логирование</string>
<string name="debug_bluetooth_roles">роли Bluetooth</string>
<string name="debug_gatt_server">сервер GATT</string>
<string name="debug_connections_fmt">подключения: %1$d / %2$d</string>
<string name="debug_max_server">макс. сервер</string>
<string name="debug_gatt_client">клиент GATT</string>
<string name="debug_max_client">макс. клиент</string>
<string name="debug_overall_connections_fmt">подключения: %1$d / %2$d</string>
<string name="debug_max_overall">макс. всего</string>
<string name="debug_packet_relay">ретрансляция пакетов</string>
<string name="debug_since_start_fmt">с начала: %1$d</string>
<string name="debug_sync_settings">настройки синхр.</string>
<string name="debug_max_packets_per_sync_fmt">макс. пакетов на синхр.: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">макс. размер фильтра GCS: %1$d байт (1281024)</string>
<string name="debug_target_fpr_fmt">целевой FPR: %1$.2f%%</string>
<string name="debug_connected_devices">подключённые устройства</string>
<string name="debug_our_device_id_fmt">ID нашего устройства: %1$s</string>
<string name="debug_none">нет</string>
<string name="debug_disconnect">отключить</string>
<string name="debug_recent_scan_results">последние результаты сканирования</string>
<string name="debug_connect">подключить</string>
<string name="debug_debug_console">консоль отладки</string>
<string name="debug_clear">очистить</string>
<string name="debug_relays_window_fmt">посл. 10с: %1$d • 1м: %2$d • 15м: %3$d</string>
<string name="debug_derived_p_fmt">выведенный P: %1$s • оцен. макс. элементов: %2$s</string>
<string name="debug_direct_suffix"> • напрямую</string>
<string name="debug_question_mark">?</string>
<string name="debug_role_server">как сервер (мы хостим)</string>
<string name="debug_role_client">как клиент (мы подключаемся)</string>
<string name="location_services_required">Требуются службы локации</string>
<string name="privacy_first">Приватность прежде всего</string>
<string name="location_explanation">bitchat НЕ отслеживает вашу геопозицию.\n\nСлужбы локации нужны для сканирования Bluetooth и функции чата Geohash.</string>
<string name="location_needs_for">bitchat нужны службы локации для:</string>
<string name="location_needs_bullets">• Сканирования устройств Bluetooth\n• Поиска ближайших пользователей в mesh\n• Функции чата Geohash\n• Без отслеживания и сбора геоданных</string>
<string name="open_location_settings">Открыть настройки локации</string>
<string name="check_again">Проверить снова</string>
<string name="location_services_unavailable">Службы локации недоступны</string>
<string name="location_unavailable_explanation">На этом устройстве службы локации недоступны — это необычно.\n\nОни требуются Android для корректной работы сканирования Bluetooth. Иначе невозможно обнаружить ближайших пользователей.</string>
<string name="checking_location_services">Проверка служб локации…</string>
<string name="bluetooth_required">Требуется Bluetooth</string>
<string name="bluetooth_needs_for">bitchat нужен Bluetooth для:</string>
<string name="bluetooth_needs_bullets">• Обнаружения ближайших пользователей\n• Создания mesh‑подключений\n• Отправки и получения сообщений\n• Работы без интернета/серверов</string>
<string name="enable_bluetooth">Включить Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth не поддерживается</string>
<string name="bluetooth_unsupported_explanation">Это устройство не поддерживает Bluetooth Low Energy (BLE), необходимый для работы bitchat.\n\nBLE нужен для построения mesh и обмена с ближайшими устройствами без интернета.</string>
<string name="checking_bluetooth_status">Проверка статуса Bluetooth…</string>
<string name="battery_optimization_detected_title">обнаружена оптимизация батареи</string>
<string name="battery_optimization_enabled_title">Оптимизация включена</string>
<string name="battery_optimization_explanation_short">bitchat должен работать в фоне для mesh; оптимизация может прерывать.</string>
<string name="benefits_of_disabling">Преимущества отключения</string>
<string name="battery_benefits_short">• надёжная доставка\n• поддержка связности\n• предотвращает обрывы</string>
<string name="disable_battery_optimization">Отключить оптимизацию</string>
<string name="battery_optimization_disabled_title">оптимизация отключена</string>
<string name="continue_btn">Продолжить</string>
<string name="initializing_mesh_network">Инициализация mesh‑сети</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">Настройка Bluetooth mesh…</string>
<string name="should_take_seconds">Займёт лишь несколько секунд</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">Настройка не завершена</string>
<string name="try_again">Повторить</string>
<string name="privacy_protected">Ваша приватность защищена</string>
<string name="privacy_bullets">• без трекинга и сбора данных\n• Bluetooth‑mesh чаты полностью оффлайн\n• Geohash‑чаты используют интернет</string>
<string name="permissions_header">разрешения</string>
<string name="grant_permissions">Выдать разрешения</string>
<string name="location_tracking_warning">bitchat НЕ отслеживает вашу геопозицию</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">ЛЮДИ</string>
<string name="nobody_around">никого рядом…</string>
<string name="you_suffix"> (вы)</string>
<string name="pan_zoom_instruction">прокрутите/масштабируйте для выбора geohash</string>
<string name="select">выбрать</string>
<string name="type_a_message_placeholder">введите сообщение…</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">упоминание</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">Изображение</string>
<string name="media_type_file">Файл</string>
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<string name="notification_sent_image">📷 отправил изображение</string>
<string name="notification_sent_voice">🎤 отправил голосовое</string>
<string name="notification_sent_file">📎 отправил файл</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<string name="cd_play_voice">Воспроизвести</string>
<string name="cd_pause_voice">Пауза</string>
<string name="perm_nearby_devices_desc">Нужно для поиска пользователей bitchat по Bluetooth</string>
<string name="perm_nearby_devices_system">Разрешить bitchat подключаться к ближайшим устройствам</string>
<string name="perm_location_desc">Требуется Android для поиска по Bluetooth</string>
<string name="perm_location_system">bitchat нужно для сканирования ближайших устройств</string>
<string name="perm_notifications_desc">Получать уведомления о личных сообщениях</string>
<string name="perm_notifications_system">Разрешить bitchat отправлять вам уведомления</string>
<string name="perm_battery_desc">Отключить оптимизацию, чтобы bitchat работал в фоне и поддерживал mesh‑связь</string>
<string name="perm_battery_system">Разрешить работу без ограничений батареи</string>
<string name="perm_type_nearby_devices">Ближайшие устройства</string>
<string name="perm_type_precise_location">Точная геопозиция</string>
<string name="perm_type_microphone">Микрофон</string>
<string name="perm_type_notifications">Уведомления</string>
<string name="perm_type_battery_optimization">Оптимизация батареи</string>
<string name="perm_type_other">Другое</string>
<string name="pwd_prompt_title">Введите пароль канала</string>
<string name="pwd_prompt_message">Канал %1$s защищён паролем. Введите пароль, чтобы присоединиться.</string>
<string name="pwd_label">Пароль</string>
<string name="join">Войти</string>
<string name="cancel">Отмена</string>
<plurals name="notification_and_more">
<item quantity="one">и ещё %d</item>
<item quantity="other">и ещё %d</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 человек</item>
<item quantity="other">%d человек</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d заметка</item>
<item quantity="other">#%1$s ± 1 • %2$d заметок</item>
</plurals>
<string name="location_notes_description">добавьте короткие постоянные заметки к этому месту, чтобы другие посетители могли их найти.</string>
<string name="location_notes_relays_unavailable">гео-релей недоступны; заметки приостановлены</string>
<string name="location_notes_no_relays_title">рядом нет гео-релеев</string>
<string name="location_notes_no_relays_desc">заметки зависят от гео-релеев. проверьте подключение и повторите попытку.</string>
<string name="loading_location_notes">загрузка заметок…</string>
<string name="location_notes_empty_title">заметок пока нет</string>
<string name="location_notes_empty_desc">станьте первым, кто добавит заметку для этого места.</string>
<string name="dismiss">закрыть</string>
<string name="location_notes_input_placeholder">добавьте заметку для этого места</string>
</resources>
+353
View File
@@ -0,0 +1,353 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">bitchat</string>
<string name="permission_bluetooth_rationale">Bluetooth-behörighet krävs för direktmeddelanden utan internet.</string>
<string name="permission_location_rationale">Platsbehörighet krävs för att hitta enheter i närheten via Bluetooth.</string>
<string name="permission_notification_rationale">Aviseringsbehörighet krävs för att meddela nya meddelanden.</string>
<string name="nickname_hint">smeknamn</string>
<string name="message_hint">skriv ett meddelande…</string>
<string name="channel_password_hint">Lösenord</string>
<string name="join_channel">Gå med i kanal</string>
<string name="leave_channel">Lämna</string>
<string name="send_message">Skicka</string>
<string name="show_commands">Visa kommandon</string>
<string name="back">Tillbaka</string>
<string name="people">Personer</string>
<string name="channels">Kanaler</string>
<string name="online_users">Användare online</string>
<string name="no_one_connected">Ingen ansluten</string>
<string name="emergency_clear_hint">Tryck tre gånger för att rensa all data</string>
<string name="your_network">Nätverk</string>
<string name="battery_optimization_detected">Batterioptimering upptäckt</string>
<string name="battery_optimization_disabled">Batterioptimering inaktiverad</string>
<string name="battery_optimization_not_required">Batterioptimering krävs inte</string>
<string name="battery_optimization_checking">Kontrollerar batterioptimering</string>
<string name="battery_optimization_why_disable">Varför inaktivera?</string>
<string name="battery_optimization_explanation">bitchat körs i bakgrunden för att upprätthålla mesh-anslutningar till enheter i närheten. Batterioptimering kan avbryta dessa och orsaka fördröjda eller missade meddelanden.\n\nAtt inaktivera säkerställer tillförlitlig P2P-meddelandetrafik.</string>
<string name="battery_optimization_disable_button">Inaktivera optimering</string>
<string name="battery_optimization_note">Obs: kan ändras senare i Android-inställningar &gt; Appar &gt; bitchat &gt; Batteri</string>
<string name="battery_optimization_not_supported_explanation">Din enhet kräver inte batterioptimeringsinställningar. bitchat körs normalt.</string>
<string name="battery_optimization_not_supported_message">Din enhet kräver inte batterioptimeringsinställningar. bitchat körs normalt.</string>
<string name="battery_optimization_success_message">bitchat kan köras tillförlitligt i bakgrunden</string>
<string name="battery_optimization_benefits">• Tillförlitlig leverans\n• Upprätthåller mesh-anslutning\n• Bakgrundsrelä\n• Förhindrar avbrott</string>
<string name="battery_optimization_check_again">Kontrollera igen</string>
<string name="battery_optimization_skip">Hoppa över nu</string>
<string name="battery_optimization_continue">Fortsätt</string>
<string name="retry">Försök igen</string>
<string name="skip">Hoppa över</string>
<string name="notification_summary_more">och %1$d till</string>
<string name="notification_messages_from_people">%1$d meddelanden från %2$d personer</string>
<string name="notification_more_conversations">och %1$d fler konversationer</string>
<string name="notification_active_peers_title">👥 bitchatter i närheten!</string>
<string name="notification_active_peers_one">1 person i närheten</string>
<string name="notification_active_peers_many">%1$d personer i närheten</string>
<string name="notification_new_messages">Nya meddelanden</string>
<string name="notification_new_location_messages">Nya platsmeddelanden</string>
<string name="notification_mentions_in">Nämnd i %1$s</string>
<string name="notification_mentions_in_more">Nämnd i %1$s (+%2$d till)</string>
<string name="notification_mentions_in_plural">%1$d nämningar i %2$s</string>
<string name="notification_new_activity_in">Ny aktivitet i %1$s</string>
<string name="notification_messages_in">Meddelanden i %1$s</string>
<string name="notification_joined_conversation">%1$s gick med i konversationen</string>
<string name="notification_geohash_summary_title_mentions">bitchat %1$d nämningar</string>
<string name="notification_geohash_summary_title">bitchat platschattar</string>
<string name="notification_geohash_summary_text">%1$d meddelanden från %2$d platser</string>
<string name="notification_mesh_mention_title_singular">Nämnd i Meshchatt</string>
<string name="notification_mesh_mention_title_plural">%1$d nämningar i Meshchatt</string>
<string name="notification_more_locations">och %1$d fler platser</string>
<string name="notification_and_more">och %1$d till</string>
<string name="cd_add_favorite">Lägg till som favorit</string>
<string name="cd_remove_favorite">Ta bort favorit</string>
<string name="cd_add_bookmark">Lägg till bokmärke</string>
<string name="chat_back">tillbaka</string>
<string name="chat_channel_prefix">kanal: %1$s</string>
<string name="chat_leave">lämna</string>
<string name="cd_nostr_reachable">Nås via Nostr</string>
<string name="cd_unread_private_messages">Olästa privata meddelanden</string>
<string name="cd_toggle_bookmark">Växla bokmärke</string>
<string name="cd_teleported">Teleporterad</string>
<string name="cd_tor_status">Torstatus</string>
<string name="cd_connected_peers">Anslutna noder</string>
<string name="cd_geohash_participants">Geohashdeltagare</string>
<string name="cd_ready_for_handshake">Redo för handshake</string>
<string name="cd_handshake_in_progress">Handshake pågår</string>
<string name="cd_encrypted">Ändatill‑ändakrypterat</string>
<string name="cd_handshake_failed">Handshake misslyckades</string>
<string name="file_viewer_title">📎 Fil mottagen</string>
<string name="file_viewer_name">📄 %1$s</string>
<string name="file_viewer_size">📏 Storlek: %1$s</string>
<string name="file_viewer_type">🏷️ Typ: %1$s</string>
<string name="file_viewer_open_save">📂 Öppna / Spara</string>
<string name="close_with_emoji">❌ Stäng</string>
<string name="pick_image">Välj bild</string>
<string name="about_tagline">decentraliserad meshmeddelanden med ändatill‑ändakryptering</string>
<string name="about_offline_mesh_title">Offline Meshchatt</string>
<string name="about_offline_mesh_desc">Kommunicera direkt via Bluetooth LE utan internet eller servrar. Meddelanden reläas av enheter i närheten.</string>
<string name="about_online_geohash_title">Online Geohashkanaler</string>
<string name="about_online_geohash_desc">Anslut med personer i närheten via geohashkanaler. Utöka mesh via publika internetreläer.</string>
<string name="about_e2e_title">Ändatill‑ändakryptering</string>
<string name="about_e2e_desc">Privata meddelanden är krypterade. Kanalmeddelanden är publika.</string>
<string name="about_appearance">utseende</string>
<string name="about_system">system</string>
<string name="about_light">ljus</string>
<string name="about_dark">mörk</string>
<string name="about_pow">proof of work</string>
<string name="about_pow_off">pow av</string>
<string name="about_pow_on">pow på</string>
<string name="about_pow_tip">lägg till proof of work i geohashmeddelanden för att hindra spam.</string>
<string name="about_pow_difficulty">svårighet: %1$d bitar (~%2$s)</string>
<string name="about_pow_difficulty_attempts">svårighet %1$d kräver ~%2$s hashförsök</string>
<string name="about_pow_desc_none">inget proof of work krävs</string>
<string name="about_pow_desc_very_low">mycket låg minimal skydd</string>
<string name="about_pow_desc_low">låg grundläggande skydd</string>
<string name="about_pow_desc_medium">medel bra skydd</string>
<string name="about_pow_desc_high">hög starkt skydd</string>
<string name="about_pow_desc_very_high">mycket hög kan orsaka fördröjning</string>
<string name="about_pow_desc_extreme">extrem kräver mycket beräkning</string>
<string name="about_network">nätverk</string>
<string name="about_tor_off">tor av</string>
<string name="about_tor_on">tor på</string>
<string name="about_tor_route">routa internet via Tor för ökad integritet.</string>
<string name="about_tor_status">Torstatus: %1$s, bootstrap %2$d%%</string>
<string name="about_last">Senast: %1$s</string>
<string name="about_emergency_title">Nödradering av data</string>
<string name="about_emergency_tip">Tips: tryck tre gånger på appens titel för att radera alla data (meddelanden, nycklar, inställningar).</string>
<string name="about_debug_settings">Felsökningsinställningar</string>
<string name="about_footer">Open Source • Privacy First • Decentraliserad</string>
<string name="close_plain">Stäng</string>
<string name="cancel_lower">avbryt</string>
<string name="cd_warning">Varning</string>
<string name="cd_location_services">Plats­tjänster</string>
<string name="cd_privacy">Integritet</string>
<string name="cd_error">Fel</string>
<string name="cd_battery_optimization">Batterioptimering</string>
<string name="cd_benefits">Fördelar</string>
<string name="cd_checking_battery_optimization">Kontrollerar optimering</string>
<string name="cd_not_supported_battery_optimization">Stöds ej</string>
<string name="cd_bluetooth">Bluetooth</string>
<string name="cd_unread_message">Oläst meddelande</string>
<string name="cd_open_map">Öppna karta</string>
<string name="cd_remove_bookmark">Ta bort bokmärke</string>
<string name="cd_teleport">Teleportera</string>
<string name="cd_selected">Vald</string>
<string name="cd_leave_channel">Lämna kanal</string>
<string name="cd_reachable_via_nostr">Nås via Nostr</string>
<string name="cd_offline_favorite">Favorit (offline)</string>
<string name="cd_decrease_precision">Minska precision</string>
<string name="cd_increase_precision">Öka precision</string>
<string name="cd_select_geohash">Välj geohash</string>
<string name="cd_scroll_to_bottom">Rulla längst ned</string>
<string name="cd_file">Fil</string>
<string name="cd_image">Bild</string>
<string name="cd_cancel">Avbryt</string>
<string name="cd_link">Länk</string>
<string name="cd_pick_media">Välj media</string>
<string name="cd_record_voice">Spela in röstanteckning</string>
<string name="cd_offline_mesh_chat">Offline Meshchatt</string>
<string name="cd_online_geohash_channels">Online Geohashkanaler</string>
<string name="cd_end_to_end_encryption">Ändatill‑ändakryptering</string>
<string name="image_page_of">Bild %1$d / %2$d</string>
<string name="image_unavailable">Bild ej tillgänglig</string>
<string name="image_saved_to_downloads">Bild sparad i "Hämtade filer"</string>
<string name="image_save_failed">Kunde inte spara bild</string>
<string name="pick_file">Välj fil</string>
<string name="file_unavailable">[fil ej tillgänglig]</string>
<string name="unknown">okänd</string>
<string name="choose_action_message_or_user">välj en åtgärd för meddelandet eller användaren</string>
<string name="choose_action_user">välj en åtgärd för den här användaren</string>
<string name="action_copy_message_title">kopiera meddelande</string>
<string name="action_copy_message_subtitle">kopiera meddelandet till urklipp</string>
<string name="action_slap_title">ge %1$s en örfil</string>
<string name="action_slap_subtitle">skicka en skämtsam örfil</string>
<string name="action_hug_title">krama %1$s</string>
<string name="action_hug_subtitle">skicka en vänlig kram</string>
<string name="action_block_title">blockera %1$s</string>
<string name="action_block_subtitle">blockera alla meddelanden från den här användaren</string>
<string name="location_channels_title">#platskanaler</string>
<string name="location_channels_desc">chatta med folk nära dig via geohashkanaler. endast en grov geohash delas, aldrig exakt gps. ta inte skärmdumpar eller dela skärmen för att skydda din integritet.</string>
<string name="grant_location_permission">ge platsbehörighet</string>
<string name="location_permission_denied">platsbehörighet nekades. aktivera i inställningar för att använda platskanaler.</string>
<string name="open_settings">Öppna inställningar</string>
<string name="location_permission_granted">\u2713 platsbehörighet beviljad</string>
<string name="checking_permissions">kontrollerar behörigheter…</string>
<string name="finding_nearby_channels">söker efter kanaler i närheten…</string>
<string name="bookmarked">bokmärkt</string>
<string name="geohash_placeholder">geohash</string>
<string name="invalid_geohash">ogiltig geohash</string>
<string name="teleport">teleportera</string>
<string name="disable_location_services">inaktivera platstjänster</string>
<string name="enable_location_services">aktivera platstjänster</string>
<string name="location_bluetooth_subtitle">#bluetooth • %1$s</string>
<string name="mesh_label">mesh</string>
<string name="location_level_block">kvarter</string>
<string name="location_level_neighborhood">grannskap</string>
<string name="location_level_city">stad</string>
<string name="location_level_province">län</string>
<string name="location_level_region">region</string>
<string name="debug_tools">felsökningsverktyg</string>
<string name="debug_verbose_logging">utförlig loggning</string>
<string name="debug_bluetooth_roles">Bluetoothroller</string>
<string name="debug_gatt_server">GATTserver</string>
<string name="debug_connections_fmt">anslutningar: %1$d / %2$d</string>
<string name="debug_max_server">max server</string>
<string name="debug_gatt_client">GATTklient</string>
<string name="debug_max_client">max klient</string>
<string name="debug_overall_connections_fmt">anslutningar: %1$d / %2$d</string>
<string name="debug_max_overall">max totalt</string>
<string name="debug_packet_relay">paketrelä</string>
<string name="debug_since_start_fmt">sedan start: %1$d</string>
<string name="debug_sync_settings">synkinställningar</string>
<string name="debug_max_packets_per_sync_fmt">max paket per synk: %1$d</string>
<string name="debug_max_gcs_filter_size_fmt">max GCSfilterstorlek: %1$d byte (1281024)</string>
<string name="debug_target_fpr_fmt">målFPR: %1$.2f%%</string>
<string name="debug_connected_devices">anslutna enheter</string>
<string name="debug_our_device_id_fmt">vår enhetsID: %1$s</string>
<string name="debug_none">ingen</string>
<string name="debug_disconnect">koppla från</string>
<string name="debug_recent_scan_results">senaste skanningsresultat</string>
<string name="debug_connect">anslut</string>
<string name="debug_debug_console">felsökningskonsol</string>
<string name="debug_clear">rensa</string>
<string name="debug_relays_window_fmt">senaste 10 s: %1$d • 1 m: %2$d • 15 m: %3$d</string>
<string name="debug_derived_p_fmt">härlett P: %1$s • uppsk. max element: %2$s</string>
<string name="debug_direct_suffix"> • direkt</string>
<string name="debug_question_mark">?</string>
<string name="debug_role_server">som server (vi hostar)</string>
<string name="debug_role_client">som klient (vi ansluter)</string>
<string name="location_services_required">Platstjänster krävs</string>
<string name="privacy_first">Integritet först</string>
<string name="location_explanation">bitchat SPÅRAR INTE din plats.\n\nPlatstjänster krävs för Bluetoothskanning och Geohashchatt.</string>
<string name="location_needs_for">bitchat behöver platstjänster för:</string>
<string name="location_needs_bullets">• Bluetoothskanning av enheter\n• Hitta användare i närheten i meshnätet\n• Geohashchatt\n• Ingen spårning eller insamling</string>
<string name="open_location_settings">Öppna platsinställningar</string>
<string name="check_again">Kontrollera igen</string>
<string name="location_services_unavailable">Platstjänster inte tillgängliga</string>
<string name="location_unavailable_explanation">Platstjänster saknas på den här enheten. Det är ovanligt.\n\nAndroid kräver dem för att Bluetoothskanning ska fungera. Utan dem kan vi inte hitta användare i närheten.</string>
<string name="checking_location_services">Kontrollerar platstjänster…</string>
<string name="bluetooth_required">Bluetooth krävs</string>
<string name="bluetooth_needs_for">bitchat behöver Bluetooth för:</string>
<string name="bluetooth_needs_bullets">• Hitta användare i närheten\n• Skapa meshanslutningar\n• Skicka och ta emot meddelanden\n• Fungera utan internet/ servrar</string>
<string name="enable_bluetooth">Aktivera Bluetooth</string>
<string name="bluetooth_not_supported">Bluetooth stöds inte</string>
<string name="bluetooth_unsupported_explanation">Denna enhet stöder inte Bluetooth Low Energy (BLE), vilket krävs för bitchat.\n\nBLE behövs för att bygga mesh och kommunicera utan internet.</string>
<string name="checking_bluetooth_status">Kontrollerar Bluetoothstatus…</string>
<string name="battery_optimization_detected_title">batterioptimering upptäckt</string>
<string name="battery_optimization_enabled_title">Batterioptimering på</string>
<string name="battery_optimization_explanation_short">bitchat måste köra i bakgrunden för mesh; optimering kan bryta.</string>
<string name="benefits_of_disabling">Fördelar med inaktivering</string>
<string name="battery_benefits_short">• tillförlitlig leverans\n• håller anslutning\n• förhindrar avbrott</string>
<string name="disable_battery_optimization">Inaktivera optimering</string>
<string name="battery_optimization_disabled_title">optimering av</string>
<string name="continue_btn">Fortsätt</string>
<string name="initializing_mesh_network">Initierar meshnätverk</string>
<string name="dot">.</string>
<string name="setting_up_bluetooth">Ställer in Bluetoothmesh…</string>
<string name="should_take_seconds">Det tar bara några sekunder</string>
<string name="warning_emoji">⚠️</string>
<string name="setup_not_complete">Slutför inte inställningen</string>
<string name="try_again">Försök igen</string>
<string name="privacy_protected">Din integritet är skyddad</string>
<string name="privacy_bullets">• ingen spårning eller insamling\n• Bluetoothmeshchattar helt offline\n• geohashchattar använder internet</string>
<string name="permissions_header">behörigheter</string>
<string name="grant_permissions">Ge behörigheter</string>
<string name="location_tracking_warning">bitchat spårar INTE din plats</string>
<string name="at_symbol">@</string>
<string name="app_brand">bitchat/</string>
<string name="channel_count_prefix"> · ⧉ </string>
<string name="geohash_people_header">PERSONER</string>
<string name="nobody_around">ingen i närheten…</string>
<string name="you_suffix"> (du)</string>
<string name="pan_zoom_instruction">panorera och zooma för att välja geohash</string>
<string name="select">välj</string>
<string name="type_a_message_placeholder">skriv ett meddelande…</string>
<string name="mention_suggestion_at">@%1$s</string>
<string name="mention">nämn</string>
<string name="image_counter">%1$d / %2$d</string>
<string name="pow_time_estimate">(~%1$s)</string>
<string name="at_nickname">@%1$s</string>
<string name="version_prefix">v%1$s</string>
<string name="hash_symbol">#</string>
<string name="underscore">_</string>
<string name="progress_bar_brackets">[%1$s] %2$d%%</string>
<string name="progress_filled"></string>
<string name="progress_empty"></string>
<string name="image_star">image/*</string>
<string name="media_type_image">Bild</string>
<string name="media_type_file">Fil</string>
<string name="status_sending"></string>
<string name="status_pending"></string>
<string name="status_sent"></string>
<string name="status_delivered">✓✓</string>
<string name="status_failed"></string>
<string name="status_read"></string>
<string name="notification_sent_image">📷 skickade en bild</string>
<string name="notification_sent_voice">🎤 skickade ett röstmeddelande</string>
<string name="notification_sent_file">📎 skickade en fil</string>
<string name="notification_file_pdf">📄</string>
<string name="notification_file_zip">🗜️</string>
<string name="notification_file_doc">📄</string>
<string name="notification_file_xls">📊</string>
<string name="notification_file_ppt">📈</string>
<string name="notification_file_generic">📎</string>
<string name="cd_play_voice">Spela</string>
<string name="cd_pause_voice">Pausa</string>
<string name="perm_nearby_devices_desc">Krävs för att hitta bitchatanvändare via Bluetooth</string>
<string name="perm_nearby_devices_system">Tillåt bitchat att ansluta till enheter i närheten</string>
<string name="perm_location_desc">Krävs av Android för att hitta användare via Bluetooth</string>
<string name="perm_location_system">bitchat behöver detta för att skanna enheter</string>
<string name="perm_notifications_desc">Ta emot aviseringar vid privata meddelanden</string>
<string name="perm_notifications_system">Tillåt bitchat att skicka aviseringar</string>
<string name="perm_battery_desc">Inaktivera batterioptimering för tillförlitlig drift i bakgrunden och meshanslutning</string>
<string name="perm_battery_system">Tillåt körning utan batteribegränsningar</string>
<string name="perm_type_nearby_devices">Enheter i närheten</string>
<string name="perm_type_precise_location">Exakt plats</string>
<string name="perm_type_microphone">Mikrofon</string>
<string name="perm_type_notifications">Aviseringar</string>
<string name="perm_type_battery_optimization">Batterioptimering</string>
<string name="perm_type_other">Övrigt</string>
<string name="pwd_prompt_title">Ange kanalens lösenord</string>
<string name="pwd_prompt_message">Kanal %1$s är lösenordsskyddad. Ange lösenordet för att gå med.</string>
<string name="pwd_label">Lösenord</string>
<string name="join">Gå med</string>
<string name="cancel">Avbryt</string>
<plurals name="notification_and_more">
<item quantity="one">och %d till</item>
<item quantity="other">och %d till</item>
</plurals>
<plurals name="people_count">
<item quantity="one">1 person</item>
<item quantity="other">%d personer</item>
</plurals>
<plurals name="location_notes_title">
<item quantity="one">#%1$s ± 1 • %2$d anteckning</item>
<item quantity="other">#%1$s ± 1 • %2$d anteckningar</item>
</plurals>
<string name="location_notes_description">lägg till korta permanenta anteckningar för den här platsen så att andra besökare kan hitta dem.</string>
<string name="location_notes_relays_unavailable">geo-reläer är inte tillgängliga; anteckningar pausade</string>
<string name="location_notes_no_relays_title">inga geo-reläer i närheten</string>
<string name="location_notes_no_relays_desc">anteckningar är beroende av geo-reläer. kontrollera anslutningen och försök igen.</string>
<string name="loading_location_notes">laddar anteckningar…</string>
<string name="location_notes_empty_title">inga anteckningar ännu</string>
<string name="location_notes_empty_desc">var först med att lägga till en anteckning för den här platsen.</string>
<string name="dismiss">stäng</string>
<string name="location_notes_input_placeholder">lägg till en anteckning för den här platsen</string>
</resources>

Some files were not shown because too many files have changed in this diff Show More