feat: UX polish, localization, advert relocation, and map filter fixes

- i18n: translate connection screen + chat tab keys into 13 locales;
  add "Send my contact" (advert) strings in all locales
- feat: move self-advert from home header into composer "+" action menu
  (new lib/utils/advert_helper.dart, always shows Flood/Direct sheet)
- fix: hide-repeaters map toggle was bypassed in simple mode
- fix: simple mode map now shows only favourite chat contacts
- fix: wrap ListTiles in Material (contact_tile secondary actions,
  inferred contact group card) to satisfy Flutter ink assertions
- device-authoritative contact/channel sync and UX review fixes

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Janez T
2026-06-12 10:01:10 +02:00
parent 3e1113035d
commit ba27843166
62 changed files with 12546 additions and 2521 deletions

View File

@@ -908,5 +908,125 @@
"enterRegionName": "Naziv regije (npr. auckland)",
"noRegionsFound": "Nema pronađenih regija na ovom repetitoru.",
"regionScopeSet": "Opseg regije postavljen na {name}",
"regionScopeCleared": "Opseg regije obrisan"
"regionScopeCleared": "Opseg regije obrisan",
"simpleMode": "Jednostavni način",
"simpleModeDescription": "Samo razgovor i karta s omiljenim kontaktima",
"simpleModeRequiresLockedDestination": "Za korištenje jednostavnog načina najprije omogućite „Zaključaj odredište” s kanalom",
"noFavouriteContacts": "Nema omiljenih kontakata",
"selectDestinationFirst": "Najprije odaberite kanal, kontakt ili sobu",
"recipientNoLongerAvailable": "Primatelj više nije dostupan",
"failedToSendMessage": "Slanje nije uspjelo: {error}",
"tictactoeDirectOnly": "Križić-kružić radi samo u izravnim porukama. Najprije odaberite kontakt.",
"deviceKeyUnavailable": "Ključ uređaja nije dostupan",
"imageCompressionFailed": "Komprimiranje slike nije uspjelo",
"imageFragmentationFailed": "Fragmentiranje slike nije uspjelo",
"failedToAnnounceImage": "Najava slike nije uspjela",
"noRecipientSelected": "Primatelj nije odabran",
"imageSendFailed": "Slanje slike nije uspjelo",
"microphonePermissionRequiredForVoice": "Za glasovne poruke potrebna je dozvola za mikrofon",
"recordingDiscarded": "Snimka je odbačena",
"publicChannelMediaWarning": "Upravo ćete poslati {mediaType} na javni kanal. To se ne preporučuje jer sadržaj mogu primiti svi na mesh mreži. Odaberite privatni ili označeni kanal, osim ako je to baš ono što želite.",
"selectPrivateChannelToShareLocation": "Odaberite privatni kanal za dijeljenje lokacije.",
"stopSharingMyLocation": "Prestani dijeliti moju lokaciju",
"shareMyLocation": "Dijeli moju lokaciju",
"stopRecording": "Zaustavi snimanje",
"recordVoice": "Snimi glasovnu poruku",
"moreActions": "Više radnji",
"noMessagesInFilter": "Nema poruka u ovom filtru",
"noMatchesInFilter": "Nema rezultata u ovom filtru",
"syncFailed": "Sinkronizacija nije uspjela: {error}",
"invalidLink": "Nevažeća poveznica",
"cannotOpenLink": "Poveznicu nije moguće otvoriti",
"failedToOpenLink": "Otvaranje poveznice nije uspjelo",
"failedToResendMessage": "Ponovno slanje poruke nije uspjelo",
"retryFailed": "Ponovni pokušaj nije uspio: {error}",
"deleteDrawingAndMessage": "Izbriši crtež i poruku",
"lastEchoRelay": "Zadnji odjek relej",
"lastEchoPath": "Zadnji odjek putanja",
"lastEchoBytesReport": "Zadnji odjek izvještaj o bajtovima",
"noGpsCoordinatesAvailable": "GPS koordinate nisu dostupne",
"notASarMarker": "Nije SAR marker",
"failedToSaveTemplate": "Spremanje predloška nije uspjelo: {error}",
"drawingNotFound": "Crtež nije pronađen",
"unknownDrawingType": "Nepoznata vrsta crteža",
"customMapMarker": "Prilagođeni marker karte",
"customMapPointLabel": "Točka: {point}",
"mapIdLabel": "ID karte: {id}",
"cannotFetchVoice": "Glasovnu poruku nije moguće dohvatiti",
"senderContactUnknown": "Kontakt pošiljatelja nije poznat. Najprije sinkronizirajte kontakte.",
"senderRouteUnknown": "Ruta pošiljatelja nije poznata. Najprije sinkronizirajte kontakte/putanju.",
"messageTooFar": "Poruka je predaleko ({hops} skokova, najviše {maxHops}).",
"senderRouteNoPathResponse": "Ruta pošiljatelja nije odgovorila na provjeru putanje. Sinkronizirajte kontakte/putanju i pokušajte ponovno.",
"senderRouteNoRawResponse": "Ruta pošiljatelja nije odgovorila na izravnoj prijenosnoj putanji.",
"voiceFetchOverHops": "Dohvaćanje glasa preko {hops} skokova može potrajati.",
"voiceReceiveCanceled": "Primanje glasa je otkazano",
"fetchingMissingVoiceFragments": "Dohvaćanje nedostajućih glasovnih fragmenata",
"receivingVoice": "Primanje glasa",
"cannotFetchImage": "Sliku nije moguće dohvatiti",
"imageFetchOverHops": "Dohvaćanje slike preko {hops} skokova može potrajati.",
"imageAlreadyBeingReceived": "Slika se već prima",
"loadImage": "Učitaj sliku",
"imageFetchFailedToSendRequest": "Zahtjev za dohvaćanje slike nije poslan",
"imageUnavailable": "Slika trenutačno nije dostupna",
"imageFetchTimedOut": "Dohvaćanje slike je isteklo",
"imageReceiveCanceled": "Primanje slike je otkazano",
"closeImagePreview": "Zatvori pregled slike",
"recordingReleaseToSend": "Snimanje... otpustite za slanje glasa",
"sendingVoice": "Slanje glasa...",
"sendLongPressToRecordVoice": "Pošalji (dugi pritisak za snimanje glasa)",
"discardRecording": "Odbaci snimku",
"hopCount": "{count, plural, one{{count} skok} few{{count} skoka} other{{count} skokova}}",
"channelsSectionDescription": "Kanali za emitiranje mesh prometa u blizini",
"roomsSectionDescription": "Zajednički prostori za stalnu koordinaciju tima",
"contactsSectionDescription": "Osobe i uređaji koje možete izravno dosegnuti",
"noRecentChatters": "Nema nedavnih sudionika",
"public": "Javno",
"failedToSendTicTacToeMove": "Potez križić-kružić nije poslan",
"youWon": "Pobijedili ste",
"opponentWon": "Protivnik je pobijedio",
"gameDraw": "Neriješeno",
"yourTurn": "Vi ste na potezu",
"opponentTurn": "Protivnik je na potezu",
"pleaseEnterValidCoordinates": "Unesite valjane koordinate",
"locationNotAvailable": "Lokacija nije dostupna",
"customCaveMapPoint": "Prilagođena točka karte špilje",
"mapPoint": "Točka karte",
"fetchingMissingImageFragments": "Dohvaćanje nedostajućih fragmenata…",
"loadingImage": "Učitavanje…",
"receivingImage": "Primanje…",
"tapToLoad": "Dodirnite za učitavanje",
"connectDevice": "Poveži uređaj",
"chooseTransportSubtitle": "Odaberite način povezivanja: Bluetooth, WiFi ili serijski",
"ble": "BLE",
"network": "Mreža",
"serial": "Serijski",
"scan": "Skeniraj",
"pressScanToSearchForDevices": "Pritisnite Skeniraj za traženje uređaja u blizini",
"failedToConnectToDevice": "Povezivanje s uređajem {name} nije uspjelo",
"unknownDevice": "Nepoznat uređaj",
"showingCachedResultsTapRefresh": "Prikazani su predmemorirani rezultati. Dodirnite osvježi za ponovno skeniranje.",
"scanningLocalNetworkOnPort": "Skeniranje lokalne mreže za MeshCore WiFi uređaje na portu {port}",
"cancelScanAndAddServer": "Otkaži skeniranje i dodaj poslužitelj",
"addServer": "Dodaj poslužitelj",
"scanningProgressIps": "Skeniranje... {scanned}/{total} IP adresa",
"cancelAndEnterManually": "Otkaži i unesi ručno",
"noRecentOrDiscoveredServers": "Još nema nedavnih ili otkrivenih poslužitelja",
"recentlyUsed": "Nedavno korišteno",
"connecting": "Povezivanje...",
"discoveredOnThisNetwork": "Otkriveno na ovoj mreži",
"serverNoLongerAvailable": "Poslužitelj na {host}:{port} više nije dostupan. Skenirajte ponovno da pronađete aktivne poslužitelje.",
"failedToConnectToHost": "Povezivanje s {host}:{port} nije uspjelo",
"enterValidIpAddress": "Unesite valjanu IP adresu",
"enterValidTcpPort": "Unesite valjani TCP port",
"ipAddress": "IP adresa",
"tcpPort": "TCP port",
"customServerPort": "Prilagođeni port poslužitelja",
"chat": "Razgovor",
"restoringPreviousLink": "Obnavljanje prethodne veze",
"noDeviceConnected": "Nijedan uređaj nije povezan",
"sendAdvert": "Pošalji moj kontakt",
"advertMode": "Pošalji moj kontakt",
"advertModeSubtitle": "Odaberite koliko daleko trebaju putovati vaši kontaktni podaci.",
"floodAdvertSent": "Kontakt poslan preplavljanjem kroz mrežu",
"directAdvertSent": "Kontakt poslan izravno obližnjim uređajima"
}