From d37572fde20ba4ef3bd56b29b58a1338090e6d9d Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Fri, 2 May 2025 16:54:16 -0700 Subject: [PATCH 01/13] Reply updates --- Localizable.xcstrings | 3 + .../Views/Messages/ChannelMessageList.swift | 45 +++++-- .../TextMessageField/TextMessageField.swift | 110 ++++++++++-------- .../Views/Messages/UserMessageList.swift | 44 +++++-- 4 files changed, 135 insertions(+), 67 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index a29691fb..834f3238 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -28749,6 +28749,9 @@ } } } + }, + "Replying to a message" : { + }, "Request Legacy Admin: %@" : { "localizations" : { diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index 0696e9d8..59d68e9e 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -28,6 +28,8 @@ struct ChannelMessageList: View { @State private var hasReachedBottom = false @State private var gotFirstUnreadMessage: Bool = false + @State private var messageToHighlight: Int64 = 0 + var body: some View { VStack { ScrollViewReader { scrollView in @@ -39,16 +41,33 @@ struct ChannelMessageList: View { if message.replyID > 0 { let messageReply = channel.allPrivateMessages.first(where: { $0.messageId == message.replyID }) HStack { - Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.accentColor).font(.caption2) - .padding(10) - .overlay( - RoundedRectangle(cornerRadius: 18) - .stroke(Color.blue, lineWidth: 0.5) - ) - Image(systemName: "arrowshape.turn.up.left.fill") - .symbolRenderingMode(.hierarchical) - .imageScale(.large).foregroundColor(.accentColor) - .padding(.trailing) + Button { + if let messageNum = messageReply?.messageId { + withAnimation(.easeInOut(duration: 0.5)) { + messageToHighlight = messageNum + } + scrollView.scrollTo(messageNum, anchor: .center) + + // Reset highlight after delay + Task { + try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second + withAnimation(.easeInOut(duration: 0.5)) { + messageToHighlight = -1 + } + } + } + } label: { + Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.accentColor).font(.caption2) + .padding(10) + .overlay( + RoundedRectangle(cornerRadius: 18) + .stroke(Color.blue, lineWidth: 0.5) + ) + Image(systemName: "arrowshape.turn.up.left.fill") + .symbolRenderingMode(.hierarchical) + .imageScale(.large).foregroundColor(.accentColor) + .padding(.trailing) + } } } HStack(alignment: .bottom) { @@ -114,6 +133,12 @@ struct ChannelMessageList: View { Spacer(minLength: 50) } } + + .overlay { + RoundedRectangle(cornerRadius: 10) + .stroke(.blue, lineWidth: 2) + .opacity(((messageToHighlight == message.messageId) || (replyMessageId == message.messageId)) ? 1 : 0) + } .padding([.leading, .trailing]) .frame(maxWidth: .infinity) .id(message.messageId) diff --git a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift index c8def69b..e6d7a15b 100644 --- a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift +++ b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift @@ -28,59 +28,75 @@ struct TextMessageField: View { #endif HStack(alignment: .top) { - ZStack { - TextField("message", text: $typingMessage, axis: .vertical) - .onChange(of: typingMessage) { _, value in - totalBytes = value.utf8.count - // Only mess with the value if it is too big - while totalBytes > Self.maxbytes { - typingMessage = String(typingMessage.dropLast()) - totalBytes = typingMessage.utf8.count - } - } - .keyboardType(.default) - .toolbar { - ToolbarItemGroup(placement: .keyboard) { - Button("Dismiss") { - isFocused = false + if replyMessageId != 0 { + + HStack { + Button { + withAnimation(.easeInOut(duration: 0.2)) { + replyMessageId = 0 } - .font(.subheadline) + isFocused = false + } label : { + Image(systemName: "x.circle.fill") + } + Text("Replying to a message") - if destination.showAlertButton { + } + } + ZStack { + TextField("message", text: $typingMessage, axis: .vertical) + .onChange(of: typingMessage) { _, value in + totalBytes = value.utf8.count + // Only mess with the value if it is too big + while totalBytes > Self.maxbytes { + typingMessage = String(typingMessage.dropLast()) + totalBytes = typingMessage.utf8.count + } + } + .keyboardType(.default) + .toolbar { + ToolbarItemGroup(placement: .keyboard) { + Button("Dismiss") { + isFocused = false + } + .font(.subheadline) + + if destination.showAlertButton { + Spacer() + AlertButton { typingMessage += "🔔 Alert Bell Character! \u{7}" } + } + Spacer() - AlertButton { typingMessage += "🔔 Alert Bell Character! \u{7}" } + RequestPositionButton(action: requestPosition) + TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes) } - - Spacer() - RequestPositionButton(action: requestPosition) - TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes) } - } - .padding(.horizontal, 8) - .focused($isFocused) - .multilineTextAlignment(.leading) - .frame(minHeight: 50) - .keyboardShortcut(.defaultAction) - .onSubmit { - #if targetEnvironment(macCatalyst) - sendMessage() - #endif - } - - Text(typingMessage) - .opacity(0) - .padding(.all, 0) + .padding(.horizontal, 8) + .focused($isFocused) + .multilineTextAlignment(.leading) + .frame(minHeight: 50) + .keyboardShortcut(.defaultAction) + .onSubmit { +#if targetEnvironment(macCatalyst) + sendMessage() +#endif + } + + Text(typingMessage) + .opacity(0) + .padding(.all, 0) + } + .overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1)) + .padding(.bottom, 15) + + Button(action: sendMessage) { + Image(systemName: "arrow.up.circle.fill") + .font(.largeTitle) + .foregroundColor(.accentColor) + } } - .overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1)) - .padding(.bottom, 15) - - Button(action: sendMessage) { - Image(systemName: "arrow.up.circle.fill") - .font(.largeTitle) - .foregroundColor(.accentColor) - } - } - .padding(.all, 15) + .padding(.all, 15) + } private func requestPosition() { diff --git a/Meshtastic/Views/Messages/UserMessageList.swift b/Meshtastic/Views/Messages/UserMessageList.swift index 6f995756..e1861240 100644 --- a/Meshtastic/Views/Messages/UserMessageList.swift +++ b/Meshtastic/Views/Messages/UserMessageList.swift @@ -26,6 +26,8 @@ struct UserMessageList: View { @State private var hasReachedBottom = false @State private var gotFirstUnreadMessage: Bool = false + @State private var messageToHighlight: Int64 = 0 + var body: some View { VStack { ScrollViewReader { scrollView in @@ -39,16 +41,33 @@ struct UserMessageList: View { if message.replyID > 0 { let messageReply = user.messageList.first(where: { $0.messageId == message.replyID }) HStack { - Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.accentColor).font(.caption2) - .padding(10) - .overlay( - RoundedRectangle(cornerRadius: 18) - .stroke(Color.blue, lineWidth: 0.5) - ) - Image(systemName: "arrowshape.turn.up.left.fill") - .symbolRenderingMode(.hierarchical) - .imageScale(.large).foregroundColor(.accentColor) - .padding(.trailing) + Button { + if let messageNum = messageReply?.messageId { + withAnimation(.easeInOut(duration: 0.5)) { + messageToHighlight = messageNum + } + scrollView.scrollTo(messageNum, anchor: .center) + + // Reset highlight after delay + Task { + try? await Task.sleep(nanoseconds: 1_000_000_000) // 1 second + withAnimation(.easeInOut(duration: 0.5)) { + messageToHighlight = -1 + } + } + } + } label: { + Text(messageReply?.messagePayload ?? "EMPTY MESSAGE").foregroundColor(.accentColor).font(.caption2) + .padding(10) + .overlay( + RoundedRectangle(cornerRadius: 18) + .stroke(Color.blue, lineWidth: 0.5) + ) + Image(systemName: "arrowshape.turn.up.left.fill") + .symbolRenderingMode(.hierarchical) + .imageScale(.large).foregroundColor(.accentColor) + .padding(.trailing) + } } } HStack(alignment: .top) { @@ -101,6 +120,11 @@ struct UserMessageList: View { Spacer(minLength: 50) } } + .overlay { + RoundedRectangle(cornerRadius: 10) + .stroke(.blue, lineWidth: 2) + .opacity(((messageToHighlight == message.messageId) || (replyMessageId == message.messageId)) ? 1 : 0) + } .padding([.leading, .trailing]) .frame(maxWidth: .infinity) .id(message.messageId) From 5b64694b4f82c46f1dee5cd8027e7d2cff436e6a Mon Sep 17 00:00:00 2001 From: unojazz Date: Sat, 3 May 2025 22:54:48 -0400 Subject: [PATCH 02/13] adding missing strings for translation --- Localizable.xcstrings | 60 ++++++++++++++++++++++++++++++ Meshtastic/Enums/DeviceEnums.swift | 12 +++--- 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 95f524d2..3377b252 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -15040,6 +15040,26 @@ } } }, + "Ignores observed messages from foreign meshes like Local Only, but takes it step further by also ignoring messages from nodes not already in the node's known list." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "忽略來自其他 Mesh 的訊息(像 Local Only 那樣),並更進一步連來自不在該節點已知清單中的節點所發出的訊息也一併忽略。" + } + } + } + }, + "Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "忽略來自其他 Mesh 的訊息(例如開放的或無法解密的),只會在該節點的本地主要/次要頻道上重新轉發訊息。" + } + } + } + }, "Import Route" : { "localizations" : { "it" : { @@ -24476,6 +24496,26 @@ } } }, + "Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "僅允許用於 SENSOR、TRACKER 和 TAK_TRACKER 角色,啟用後會禁止所有訊息的重新廣播,效果類似於 CLIENT_MUTE 角色。" + } + } + } + }, + "Only rebroadcasts packets from the core portnums: NodeInfo, Text, Position, Telemetry, and Routing." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "僅會重傳來自核心 portnum 的封包:NodeInfo、Text、Position、Telemetry 和 Routing" + } + } + } + }, "Open Settings" : { "localizations" : { "de" : { @@ -27102,6 +27142,16 @@ } } }, + "Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora params." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "只要是在私人頻道上,或是來自使用相同 LoRa 參數的其他 Mesh 的訊息,都會進行重新廣播。" + } + } + } + }, "Rebroadcast Mode" : { "localizations" : { "it" : { @@ -29781,6 +29831,16 @@ } } }, + "Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior." : { + "localizations" : { + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "行為與 ALL 相同,但會略過封包解碼,直接重新廣播。僅在 Repeater 角色中可用;若設定於其他角色,則會自動採用 ALL 的行為。" + } + } + } + }, "satellite" : { "localizations" : { "de" : { diff --git a/Meshtastic/Enums/DeviceEnums.swift b/Meshtastic/Enums/DeviceEnums.swift index 5eb48564..0f132b9d 100644 --- a/Meshtastic/Enums/DeviceEnums.swift +++ b/Meshtastic/Enums/DeviceEnums.swift @@ -168,17 +168,17 @@ enum RebroadcastModes: Int, CaseIterable, Identifiable { var description: String { switch self { case .all: - return "Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora params." + return "Rebroadcast any observed message, if it was on our private channel or from another mesh with the same lora params.".localized case .allSkipDecoding: - return "Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior." + return "Same as behavior as ALL but skips packet decoding and simply rebroadcasts them. Only available in Repeater role. Setting this on any other roles will result in ALL behavior.".localized case .localOnly: - return "Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels." + return "Ignores observed messages from foreign meshes that are open or those which it cannot decrypt. Only rebroadcasts message on the nodes local primary / secondary channels.".localized case .knownOnly: - return "Ignores observed messages from foreign meshes like Local Only, but takes it step further by also ignoring messages from nodes not already in the node's known list." + return "Ignores observed messages from foreign meshes like Local Only, but takes it step further by also ignoring messages from nodes not already in the node's known list.".localized case .none: - return "Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role." + return "Only permitted for SENSOR, TRACKER and TAK_TRACKER roles, this will inhibit all rebroadcasts, not unlike CLIENT_MUTE role.".localized case .corePortnums: - return "Only rebroadcasts packets from the core portnums: NodeInfo, Text, Position, Telemetry, and Routing." + return "Only rebroadcasts packets from the core portnums: NodeInfo, Text, Position, Telemetry, and Routing.".localized } } func protoEnumValue() -> Config.DeviceConfig.RebroadcastMode { From 4b7f5d2ea679793eb38e9a59c6c15cf3f68bb352 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Sat, 3 May 2025 20:46:53 -0700 Subject: [PATCH 03/13] Move MyNodeInfo assignment before save for new nodes --- Meshtastic/Persistence/UpdateCoreData.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index b2673477..d06c0219 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -227,6 +227,7 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) let myInfoEntity = MyInfoEntity(context: context) myInfoEntity.myNodeNum = Int64(packet.from) myInfoEntity.rebootCount = 0 + newNode.myInfo = myInfoEntity do { try context.save() Logger.data.info("💾 [NodeInfo] Saved a NodeInfo for node number: \(packet.from.toHex(), privacy: .public)") @@ -236,7 +237,6 @@ func upsertNodeInfoPacket (packet: MeshPacket, context: NSManagedObjectContext) let nsError = error as NSError Logger.data.error("💥 [MyInfoEntity] Error Inserting New Core Data: \(nsError, privacy: .public)") } - newNode.myInfo = myInfoEntity } else { // Update an existing node From 3290b35317928d6b2df66698f3419a288f2a9d8c Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Sat, 3 May 2025 23:50:10 -0700 Subject: [PATCH 04/13] Fixed conflict --- .../TextMessageField/TextMessageField.swift | 60 +++++++------------ 1 file changed, 22 insertions(+), 38 deletions(-) diff --git a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift index a9e9c993..c642a9b7 100644 --- a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift +++ b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift @@ -15,54 +15,38 @@ struct TextMessageField: View { @State private var sendPositionWithMessage = false var body: some View { - #if targetEnvironment(macCatalyst) - HStack { - if destination.showAlertButton { + VStack { + #if targetEnvironment(macCatalyst) + HStack { + if destination.showAlertButton { + Spacer() + AlertButton { typingMessage += "🔔 Alert Bell! \u{7}" } + } Spacer() - AlertButton { typingMessage += "🔔 Alert Bell! \u{7}" } + RequestPositionButton(action: requestPosition) + TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes).padding(.trailing) } - Spacer() - RequestPositionButton(action: requestPosition) - TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes).padding(.trailing) - } - #endif + #endif - HStack(alignment: .top) { + HStack(alignment: .top) { if replyMessageId != 0 { - HStack { Button { withAnimation(.easeInOut(duration: 0.2)) { replyMessageId = 0 } isFocused = false - } label : { + } label: { Image(systemName: "x.circle.fill") } Text("Replying to a message") - } - } + } + ZStack { TextField("message", text: $typingMessage, axis: .vertical) .onChange(of: typingMessage) { _, value in totalBytes = value.utf8.count - // Only mess with the value if it is too big - while totalBytes > Self.maxbytes { - typingMessage = String(typingMessage.dropLast()) - totalBytes = typingMessage.utf8.count - } - } - } - Text("Replying to a message") - - } - } - ZStack { - TextField("message", text: $typingMessage, axis: .vertical) - .onChange(of: typingMessage) { _, value in - totalBytes = value.utf8.count - // Only mess with the value if it is too big while totalBytes > Self.maxbytes { typingMessage = String(typingMessage.dropLast()) totalBytes = typingMessage.utf8.count @@ -75,12 +59,12 @@ struct TextMessageField: View { isFocused = false } .font(.subheadline) - + if destination.showAlertButton { Spacer() AlertButton { typingMessage += "🔔 Alert Bell Character! \u{7}" } } - + Spacer() RequestPositionButton(action: requestPosition) TextMessageSize(maxbytes: Self.maxbytes, totalBytes: totalBytes) @@ -92,18 +76,18 @@ struct TextMessageField: View { .frame(minHeight: 50) .keyboardShortcut(.defaultAction) .onSubmit { -#if targetEnvironment(macCatalyst) + #if targetEnvironment(macCatalyst) sendMessage() -#endif + #endif } - + Text(typingMessage) .opacity(0) .padding(.all, 0) } .overlay(RoundedRectangle(cornerRadius: 20).stroke(.tertiary, lineWidth: 1)) .padding(.bottom, 15) - + Button(action: sendMessage) { Image(systemName: "arrow.up.circle.fill") .font(.largeTitle) @@ -111,13 +95,13 @@ struct TextMessageField: View { } } .padding(.all, 15) - + } } private func requestPosition() { let userLongName = bleManager.connectedPeripheral != nil ? bleManager.connectedPeripheral.longName : "Unknown" sendPositionWithMessage = true - typingMessage = "📍 " + userLongName + " \(destination.positionShareMessage)." + typingMessage = "📍 " + userLongName + " \(destination.positionShareMessage)." } private func sendMessage() { From 7bc0db35b440a7016ae5e5ab4a6530932e3144e1 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 5 May 2025 08:23:15 -0700 Subject: [PATCH 05/13] Update translation strings --- Localizable.xcstrings | 339 +++++++++--------- Meshtastic/Persistence/UpdateCoreData.swift | 2 +- .../Config/Module/PaxCounterConfig.swift | 2 +- 3 files changed, 173 insertions(+), 170 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 95f524d2..98623381 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -5721,62 +5721,7 @@ } }, "config.module.paxcounter.title" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter Config" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter Config" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter Config" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configurazione del contatore PAX" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter Config" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Räknare Konfiguration" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подешавања бројача пролазника" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX 计数器配置" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX 計數器設定" - } - } - } + }, "config.module.paxcounter.updateinterval.description" : { "localizations" : { @@ -11428,6 +11373,34 @@ } } }, + "Environment Metrics" : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metriche dei sensori" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Метрике сензора" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "传感器指标" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "傳感器數據" + } + } + } + }, "Environment Metrics Log" : { "localizations" : { "it" : { @@ -14370,34 +14343,6 @@ } } }, - "How often power metrics are sent out over the mesh. Default is 30 minutes." : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Con quale frequenza vengono inviate le metriche di potenza attraverso la rete. L'impostazione predefinita è 30 minuti." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Колико често се метрике снаге шаљу преко мреже. Подразумевано је 30 минута." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "通过网格发送功率指标的频率。默认为 30 分钟。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "電力指標透過網狀網路發送的頻率。預設為每 30 分鐘一次。" - } - } - } - }, "How often environment metrics are sent out over the mesh. Default is 30 minutes." : { "localizations" : { "it" : { @@ -14426,6 +14371,34 @@ } } }, + "How often power metrics are sent out over the mesh. Default is 30 minutes." : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Con quale frequenza vengono inviate le metriche di potenza attraverso la rete. L'impostazione predefinita è 30 minuti." + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Колико често се метрике снаге шаљу преко мреже. Подразумевано је 30 минута." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "通过网格发送功率指标的频率。默认为 30 分钟。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "電力指標透過網狀網路發送的頻率。預設為每 30 分鐘一次。" + } + } + } + }, "How often should we try to get a GPS position." : { "localizations" : { "it" : { @@ -18592,28 +18565,6 @@ } } }, - "Long Range - Fast" : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "A lungo raggio - Veloce" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дугачки домет - Брзо" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "Long Range - Fast" - } - } - } - }, "Long Name" : { "localizations" : { "de" : { @@ -18710,6 +18661,28 @@ } } }, + "Long Range - Fast" : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "A lungo raggio - Veloce" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Дугачки домет - Брзо" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "Long Range - Fast" + } + } + } + }, "Long Range - Slow" : { "localizations" : { "it" : { @@ -20878,40 +20851,6 @@ } } }, - "mesh.log.paxcounter.config %@" : { - "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter config received: %@" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configurazione del contatore PAX ricevuta: %@" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX-räknarkonfiguration mottagen: %@" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Конфигурација PAX бројача примљена: %@" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter config received: %@" - } - } - } - }, "mesh.log.position.config %@" : { "localizations" : { "de" : { @@ -25106,6 +25045,98 @@ } } }, + "PAX Counter Config" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter Config" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter Config" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter Config" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configurazione del contatore PAX" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter Config" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Räknare Konfiguration" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Подешавања бројача пролазника" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX 计数器配置" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX 計數器設定" + } + } + } + }, + "PAX Counter config received: %@" : { + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter config received: %@" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configurazione del contatore PAX ricevuta: %@" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX-räknarkonfiguration mottagen: %@" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Конфигурација PAX бројача примљена: %@" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "PAX Counter config received: %@" + } + } + } + }, "paxcounter.ble" : { "localizations" : { "en" : { @@ -31075,34 +31106,6 @@ } } }, - "Environment Metrics" : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metriche dei sensori" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Метрике сензора" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "传感器指标" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "傳感器數據" - } - } - } - }, "Sensor options" : { "localizations" : { "it" : { diff --git a/Meshtastic/Persistence/UpdateCoreData.swift b/Meshtastic/Persistence/UpdateCoreData.swift index d06c0219..d8477ee2 100644 --- a/Meshtastic/Persistence/UpdateCoreData.swift +++ b/Meshtastic/Persistence/UpdateCoreData.swift @@ -1101,7 +1101,7 @@ func upsertExternalNotificationModuleConfigPacket(config: ModuleConfig.ExternalN func upsertPaxCounterModuleConfigPacket(config: ModuleConfig.PaxcounterConfig, nodeNum: Int64, sessionPasskey: Data? = Data(), context: NSManagedObjectContext) { - let logString = String.localizedStringWithFormat("mesh.log.paxcounter.config %@".localized, String(nodeNum)) + let logString = String.localizedStringWithFormat("PAX Counter config received: %@".localized, String(nodeNum)) Logger.data.info("🧑‍🤝‍🧑 \(logString, privacy: .public)") let fetchNodeInfoRequest = NodeInfoEntity.fetchRequest() diff --git a/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift b/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift index 5ef89a17..480f4b94 100644 --- a/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/PaxCounterConfig.swift @@ -22,7 +22,7 @@ struct PaxCounterConfig: View { var body: some View { Form { - ConfigHeader(title: "config.module.paxcounter.title", config: \.powerConfig, node: node, onAppear: setPaxValues) + ConfigHeader(title: "PAX Counter Config", config: \.powerConfig, node: node, onAppear: setPaxValues) Section { Toggle(isOn: $enabled) { From 0b47abb127e91ed41cf3660a2148d3b13cd6b33e Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 5 May 2025 08:57:38 -0700 Subject: [PATCH 06/13] More translastion key updates --- Localizable.xcstrings | 322 ++++++++---------- Meshtastic/Views/Messages/ChannelList.swift | 2 +- .../Messages/MessageContextMenuItems.swift | 2 +- Meshtastic/Views/Messages/UserList.swift | 2 +- .../Nodes/Helpers/Map/PositionPopover.swift | 2 +- .../Nodes/Helpers/Map/WaypointForm.swift | 2 +- Meshtastic/Views/Nodes/TraceRouteLog.swift | 2 +- Meshtastic/Views/Settings/AppData.swift | 4 +- Meshtastic/Views/Settings/AppLog.swift | 2 +- .../Views/Settings/Logs/LogDetail.swift | 2 +- Meshtastic/Views/Settings/Routes.swift | 4 +- Meshtastic/Views/Settings/Settings.swift | 2 +- 12 files changed, 150 insertions(+), 198 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 98623381..74161211 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -685,7 +685,7 @@ }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "%@ האפליקציה תנסה אוטומטית להתחבר מחדש למכשיר המועדף אם ייראה." } }, @@ -743,7 +743,7 @@ }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "%@ שגיאה זו בדרך כלל אינה ניתנת לתיקון ללא שכחחת המכשיר בהגדרות מכשיר > בלוטוס ואז להתחבר מחדש למכשיר." } }, @@ -4440,6 +4440,70 @@ } } }, + "Category" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kategorie" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Categoria" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Категорија" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "Category" + } + } + } + }, "Ch1 Current" : { "localizations" : { "it" : { @@ -7677,7 +7741,7 @@ } } }, - "delete" : { + "Delete" : { "localizations" : { "de" : { "stringUnit" : { @@ -7685,12 +7749,6 @@ "value" : "Löschen" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Delete" - } - }, "fr" : { "stringUnit" : { "state" : "translated", @@ -8317,6 +8375,58 @@ } } }, + "Device Configuration" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Gerätekonfiguration" + } + }, + "he" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Device Configuration" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Configurazione del dispositivo" + } + }, + "pl" : { + "stringUnit" : { + "state" : "needs_review", + "value" : "Device Configuration" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enhetsinställningar" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Подешавања уређаја" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "设备配置" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "設備設定" + } + } + } + }, "Device GPS" : { "localizations" : { "de" : { @@ -8589,64 +8699,6 @@ } } }, - "device.configuration" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Gerätekonfiguration" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Device Configuration" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "Device Configuration" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Configurazione del dispositivo" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Device Configuration" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Enhetsinställningar" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подешавања уређаја" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "设备配置" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "設備設定" - } - } - } - }, "device.metrics.delete" : { "localizations" : { "en" : { @@ -9637,13 +9689,13 @@ }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Combinaison des modes ROUTER et CLIENT. Pas pour les appareils mobiles." } }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "קומבינציה של ROUTER וCLIENT. לא למכשירים ניידים." } }, @@ -11735,7 +11787,7 @@ } } }, - "export" : { + "Export" : { "localizations" : { "de" : { "stringUnit" : { @@ -13905,7 +13957,7 @@ } } }, - "heard" : { + "Heard" : { "localizations" : { "de" : { "stringUnit" : { @@ -13913,12 +13965,6 @@ "value" : "Gehört" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Heard" - } - }, "fr" : { "stringUnit" : { "state" : "translated", @@ -18125,70 +18171,6 @@ } } }, - "log.category" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kategorie" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Categoria" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Категорија" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - } - } - }, "log.level" : { "localizations" : { "de" : { @@ -22469,7 +22451,7 @@ }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Mode" } }, @@ -24535,12 +24517,6 @@ "value" : "Optionen" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Options" - } - }, "fr" : { "stringUnit" : { "state" : "translated", @@ -24815,12 +24791,6 @@ "value" : "Pairing Modus" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pairing Mode" - } - }, "fr" : { "stringUnit" : { "state" : "translated", @@ -24853,7 +24823,7 @@ }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Мод упаривања" } }, @@ -24887,7 +24857,7 @@ }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "סיסמא" } }, @@ -25015,7 +24985,7 @@ }, "pl" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "PAX Counter" } }, @@ -25049,13 +25019,7 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter Config" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "PAX Counter Config" } }, @@ -25073,7 +25037,7 @@ }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "PAX Counter Config" } }, @@ -25105,12 +25069,6 @@ }, "PAX Counter config received: %@" : { "localizations" : { - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "PAX Counter config received: %@" - } - }, "it" : { "stringUnit" : { "state" : "translated", @@ -25131,7 +25089,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "PAX Counter config received: %@" } } @@ -25709,19 +25667,13 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Position" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Position" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Position" } }, @@ -25745,7 +25697,7 @@ }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Position" } }, @@ -36900,25 +36852,25 @@ }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Tempo di attività" } }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Drifttid" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Време рада" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "已開機時間" } } diff --git a/Meshtastic/Views/Messages/ChannelList.swift b/Meshtastic/Views/Messages/ChannelList.swift index f4194dc3..1123c4ab 100644 --- a/Meshtastic/Views/Messages/ChannelList.swift +++ b/Meshtastic/Views/Messages/ChannelList.swift @@ -144,7 +144,7 @@ struct ChannelList: View { context.refresh(myInfo, mergeChanges: true) channelSelection = nil } label: { - Text("delete") + Text("Delete") } } } diff --git a/Meshtastic/Views/Messages/MessageContextMenuItems.swift b/Meshtastic/Views/Messages/MessageContextMenuItems.swift index 1d8642a0..dc55a8ce 100644 --- a/Meshtastic/Views/Messages/MessageContextMenuItems.swift +++ b/Meshtastic/Views/Messages/MessageContextMenuItems.swift @@ -104,7 +104,7 @@ struct MessageContextMenuItems: View { Button(role: .destructive) { isShowingDeleteConfirmation = true } label: { - Text("delete") + Text("Delete") Image(systemName: "trash") } } diff --git a/Meshtastic/Views/Messages/UserList.swift b/Meshtastic/Views/Messages/UserList.swift index 2888a54e..7a7193f2 100644 --- a/Meshtastic/Views/Messages/UserList.swift +++ b/Meshtastic/Views/Messages/UserList.swift @@ -187,7 +187,7 @@ struct UserList: View { deleteUserMessages(user: userSelection!, context: context) context.refresh(node!.user!, mergeChanges: true) } label: { - Text("delete") + Text("Delete") } } } diff --git a/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift b/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift index 97df2327..d3ef18a3 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/PositionPopover.swift @@ -52,7 +52,7 @@ struct PositionPopover: View { /// Time Label { if idiom != .phone { - Text("heard".localized + ":") + Text("Heard".localized + ":") } Text(position.time?.lastHeard ?? "unknown") .foregroundColor(.primary) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift index 736c2114..fbfeb764 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift @@ -235,7 +235,7 @@ struct WaypointForm: View { }) } label: { - Label("delete", systemImage: "trash") + Label("Delete", systemImage: "trash") .foregroundColor(.red) } .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Nodes/TraceRouteLog.swift b/Meshtastic/Views/Nodes/TraceRouteLog.swift index bd50f3ac..3d2df721 100644 --- a/Meshtastic/Views/Nodes/TraceRouteLog.swift +++ b/Meshtastic/Views/Nodes/TraceRouteLog.swift @@ -67,7 +67,7 @@ struct TraceRouteLog: View { Logger.data.error("\(error.localizedDescription, privacy: .public)") } } label: { - Label("delete", systemImage: "trash") + Label("Delete", systemImage: "trash") } } } diff --git a/Meshtastic/Views/Settings/AppData.swift b/Meshtastic/Views/Settings/AppData.swift index f1777989..e5535c2c 100644 --- a/Meshtastic/Views/Settings/AppData.swift +++ b/Meshtastic/Views/Settings/AppData.swift @@ -41,7 +41,7 @@ struct AppData: View { Logger.services.error("🗑️ Delete file error: \(error, privacy: .public)") } } label: { - Label("delete", systemImage: "trash") + Label("Delete", systemImage: "trash") } } } icon: { @@ -61,7 +61,7 @@ struct AppData: View { Logger.services.error("🗑️ Delete file error: \(error, privacy: .public)") } } label: { - Label("delete", systemImage: "trash") + Label("Delete", systemImage: "trash") } } } icon: { diff --git a/Meshtastic/Views/Settings/AppLog.swift b/Meshtastic/Views/Settings/AppLog.swift index 5c49f7c4..76f87388 100644 --- a/Meshtastic/Views/Settings/AppLog.swift +++ b/Meshtastic/Views/Settings/AppLog.swift @@ -84,7 +84,7 @@ struct AppLog: View { .foregroundStyle(value.level.color) } .width(min: 85, max: 110) - TableColumn("log.category", value: \.category) + TableColumn("Category", value: \.category) .width(min: 80, max: 130) TableColumn("Message", value: \.composedMessage) { value in Text(value.composedMessage) diff --git a/Meshtastic/Views/Settings/Logs/LogDetail.swift b/Meshtastic/Views/Settings/Logs/LogDetail.swift index 864e3c62..31da29d4 100644 --- a/Meshtastic/Views/Settings/Logs/LogDetail.swift +++ b/Meshtastic/Views/Settings/Logs/LogDetail.swift @@ -107,7 +107,7 @@ struct LogDetail: View { /// Category Label { HStack { - Text("log.category".localized + ":") + Text("Category".localized + ":") .font(idiom == .phone ? .caption : .title) .frame(width: idiom == .phone ? 115 : 190, alignment: .trailing) Text(log.category) diff --git a/Meshtastic/Views/Settings/Routes.swift b/Meshtastic/Views/Settings/Routes.swift index 138fab99..b7a80b31 100644 --- a/Meshtastic/Views/Settings/Routes.swift +++ b/Meshtastic/Views/Settings/Routes.swift @@ -154,7 +154,7 @@ struct Routes: View { Logger.data.error("\(error.localizedDescription, privacy: .public)") } } label: { - Label("delete", systemImage: "trash") + Label("Delete", systemImage: "trash") } } @@ -279,7 +279,7 @@ struct Routes: View { exportString = routeToCsvFile(locations: selectedRoute!.locations!.array as? [LocationEntity] ?? []) isExporting = true } label: { - Label("export", systemImage: "square.and.arrow.down") + Label("Export", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Settings/Settings.swift b/Meshtastic/Views/Settings/Settings.swift index 45c9f54a..1e9ab8a7 100644 --- a/Meshtastic/Views/Settings/Settings.swift +++ b/Meshtastic/Views/Settings/Settings.swift @@ -105,7 +105,7 @@ struct Settings: View { } var deviceConfigurationSection: some View { - Section("device.configuration") { + Section("Device Configuration") { NavigationLink(value: SettingsNavigationState.user) { Label { Text("User") From c3f23370c8047c6382a5867b956d5118fd9b295b Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Mon, 5 May 2025 09:35:30 -0700 Subject: [PATCH 07/13] Update routing error translation strings --- Localizable.xcstrings | 1592 ++++++++--------- Meshtastic/Enums/RoutingError.swift | 26 +- .../Views/Nodes/DetectionSensorLog.swift | 2 +- Meshtastic/Views/Nodes/DeviceMetricsLog.swift | 2 +- .../Views/Nodes/EnvironmentMetricsLog.swift | 2 +- Meshtastic/Views/Nodes/PaxCounterLog.swift | 2 +- Meshtastic/Views/Settings/Channels.swift | 2 +- .../Config/Module/RangeTestConfig.swift | 2 +- .../Settings/Config/SaveConfigButton.swift | 2 +- Meshtastic/Views/Settings/Routes.swift | 2 +- .../Views/Settings/SaveChannelQRCode.swift | 2 +- Meshtastic/Views/Settings/UserConfig.swift | 2 +- 12 files changed, 770 insertions(+), 868 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 74161211..d0125bad 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -1812,6 +1812,70 @@ } } }, + "Acknowledged" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bestätigt" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Acknowledged" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Confirmé" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "מאשר" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Riconosciuto" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Potwierdzono" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bekräftad" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Потврђено" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "确认" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "已確認" + } + } + } + }, "Acknowledged by another node" : { "localizations" : { "it" : { @@ -3396,6 +3460,70 @@ } } }, + "Bad Request" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bad Request" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bad Request" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Requête incorrecte" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "בקשה לא תקינה" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Richiesta negativa" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Złe żądanie" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Felaktig begäran" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Лош захтев" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "错误请求" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "錯誤請求" + } + } + } + }, "Bandwidth" : { "localizations" : { "de" : { @@ -11301,6 +11429,40 @@ } } }, + "Encrypted Send Failed" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verschlüsseltes Senden fehlgeschlagen" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Encrypted Send Failed" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Invio crittografato fallito" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Шифровано слање није успело" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "加密傳送失敗" + } + } + } + }, "Encryption Enabled" : { "localizations" : { "it" : { @@ -19587,6 +19749,70 @@ } } }, + "Max Retransmission Reached" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Maximale Wiederholungen erreicht" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max Retransmission Reached" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nombre maximum de retransmissions atteint" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הגיע למקסימום השליחות מדש" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raggiunta la massima ritrasmissione" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Osiągnięto limit retransmisji" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Max antal omsändningar nått" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Достигнут максималан број поновних слања" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已达到最大重试次数" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "已達到最大重試次數" + } + } + } + }, "medium.range.fast" : { "localizations" : { "en" : { @@ -23221,6 +23447,70 @@ } } }, + "No Channel" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kein Kanal" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Channel" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas de canal" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אין ערוץ" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nessun canale" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brak kanału" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen kanal" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нема канала" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有频道" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "没有頻道" + } + } + } + }, "No Connected Node" : { "localizations" : { "de" : { @@ -23299,6 +23589,70 @@ } } }, + "No Interface" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine Schnittstelle" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Interface" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas d'interface" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אין ממשק" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nessuna interfaccia" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brak interfejsu" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inget gränssnitt" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нема интерфејса" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无连接" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "無連接" + } + } + } + }, "No PIN (Just Works)" : { "localizations" : { "de" : { @@ -23413,6 +23767,134 @@ } } }, + "No Response" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine Antwort" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Response" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas de réponse" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אין תגובה" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nessuna risposta" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brak odpowiedzi" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inget svar" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нема одговора" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "无响应" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "無回應" + } + } + } + }, + "No Route" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Keine Route" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No Route" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pas de route" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "אין מסלול" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nessun percorso" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Brak trasy" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ingen rutt" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Нема руте" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "找不到目标" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "找不到目標" + } + } + } + }, "Node" : { "localizations" : { "de" : { @@ -23817,6 +24299,70 @@ } } }, + "Not Authorized" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nicht authorisiert" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Not Authorized" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Non autorisé" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "לא מאושר" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Non autorizzato" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nieautoryzowany" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Inte auktoriserad" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Није ауторизовано" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "未授权" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "未授權" + } + } + } + }, "Not Present" : { "localizations" : { "fr" : { @@ -27135,6 +27681,70 @@ } } }, + "Received a negative acknowledgment" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Negative Empfangsbestätigung empfangen" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Received a negative acknowledgment" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Accusé de réception négatif reçu" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "התקבל אישור מסירה שלילי" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ricevuto un riscontro negativo" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Otrzymano negatywne potwierdzenie" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mottog ett negativt kvitto" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Примљено негативно признање" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "收到否认" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "收到 NACK(否定確認)" + } + } + } + }, "received.ack" : { "localizations" : { "de" : { @@ -27347,6 +27957,70 @@ } } }, + "Regional Duty Cycle Limit Reached" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Regionale Einschaltdauergrenze erreicht" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Regional Duty Cycle Limit Reached" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Limite du cycle de service régional atteinte" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "הגיע למקסימום שימוש אזורי לשעה זו" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Raggiunto il limite del ciclo di lavoro regionale" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Osiągnięto regionalny limit cyklu pracy" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Regionala sändningsgränsen nådd" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Достигнут регионални лимит радног циклуса" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "已达到当前区域循环周期发射上限" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "已達到頻道占用循環週期發射上限" + } + } + } + }, "relativetimeofday.afternoon" : { "localizations" : { "de" : { @@ -28852,808 +29526,6 @@ } } }, - "routing.acknowledged" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bestätigt" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Acknowledged" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Confirmé" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "מאשר" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Riconosciuto" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Potwierdzono" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bekräftad" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Потврђено" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "确认" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "已確認" - } - } - } - }, - "routing.badRequest" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bad Request" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bad Request" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Requête incorrecte" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "בקשה לא תקינה" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Richiesta negativa" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Złe żądanie" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Felaktig begäran" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Лош захтев" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "错误请求" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "錯誤請求" - } - } - } - }, - "routing.dutycyclelimit" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Regionale Einschaltdauergrenze erreicht" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Regional Duty Cycle Limit Reached" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Limite du cycle de service régional atteinte" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "הגיע למקסימום שימוש אזורי לשעה זו" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Raggiunto il limite del ciclo di lavoro regionale" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Osiągnięto regionalny limit cyklu pracy" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Regionala sändningsgränsen nådd" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Достигнут регионални лимит радног циклуса" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "已达到当前区域循环周期发射上限" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "已達到頻道占用循環週期發射上限" - } - } - } - }, - "routing.gotnak" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Negative Empfangsbestätigung empfangen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Received a negative acknowledgment" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Accusé de réception négatif reçu" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "התקבל אישור מסירה שלילי" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ricevuto un riscontro negativo" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Otrzymano negatywne potwierdzenie" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Mottog ett negativt kvitto" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Примљено негативно признање" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "收到否认" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "收到 NACK(否定確認)" - } - } - } - }, - "routing.maxretransmit" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Maximale Wiederholungen erreicht" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max Retransmission Reached" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nombre maximum de retransmissions atteint" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "הגיע למקסימום השליחות מדש" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Raggiunta la massima ritrasmissione" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Osiągnięto limit retransmisji" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max antal omsändningar nått" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Достигнут максималан број поновних слања" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "已达到最大重试次数" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "已達到最大重試次數" - } - } - } - }, - "routing.nochannel" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Kein Kanal" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Channel" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pas de canal" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אין ערוץ" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nessun canale" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brak kanału" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen kanal" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нема канала" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "没有频道" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "没有頻道" - } - } - } - }, - "routing.nointerface" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Keine Schnittstelle" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Interface" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pas d'interface" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אין ממשק" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nessuna interfaccia" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brak interfejsu" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inget gränssnitt" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нема интерфејса" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "无连接" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "無連接" - } - } - } - }, - "routing.noresponse" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Keine Antwort" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Response" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pas de réponse" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אין תגובה" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nessuna risposta" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brak odpowiedzi" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inget svar" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нема одговора" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "无响应" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "無回應" - } - } - } - }, - "routing.noroute" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Keine Route" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "No Route" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pas de route" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "אין מסלול" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nessun percorso" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Brak trasy" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ingen rutt" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нема руте" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "找不到目标" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "找不到目標" - } - } - } - }, - "routing.notauthorized" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nicht authorisiert" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Not Authorized" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Non autorisé" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "לא מאושר" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Non autorizzato" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nieautoryzowany" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Inte auktoriserad" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Није ауторизовано" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "未授权" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "未授權" - } - } - } - }, - "routing.pkifailed" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Verschlüsseltes Senden fehlgeschlagen" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Encrypted Send Failed" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Invio crittografato fallito" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Шифровано слање није успело" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "加密傳送失敗" - } - } - } - }, - "routing.timeout" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Zeitlimit erreicht" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Timeout" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Délai d'expiration" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "נגמר הזמן" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Timeout" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Limit czasu" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Tidsgräns överskriden" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Време истекло" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "超时" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "逾時" - } - } - } - }, - "routing.toolarge" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Das Paket ist zu groß" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "The packet is too large" - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Le paquet est trop grand" - } - }, - "he" : { - "stringUnit" : { - "state" : "translated", - "value" : "ההודעה ארוכה/גדולה מידי" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Il pacchetto è troppo grande" - } - }, - "pl" : { - "stringUnit" : { - "state" : "translated", - "value" : "Pakiet jest zbyt duży" - } - }, - "se" : { - "stringUnit" : { - "state" : "translated", - "value" : "Paketet är för stort" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пакет је превелики" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "数据包过大" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "數據包過大" - } - } - } - }, "RSSI %@ dBm" : { "localizations" : { "it" : { @@ -29976,53 +29848,47 @@ } } }, - "save" : { + "Save" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Speichern" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Save" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Sauvegarder" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "שמור" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Risparmiare" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Zapisz" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Spara" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Сачувај" } }, @@ -30034,35 +29900,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", - "value" : "儲存" - } - } - } - }, - "Save" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Speichern" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Risparmiare" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сачувај" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "儲存" } } @@ -34606,6 +34444,70 @@ } } }, + "The packet is too large" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Das Paket ist zu groß" + } + }, + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The packet is too large" + } + }, + "fr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Le paquet est trop grand" + } + }, + "he" : { + "stringUnit" : { + "state" : "translated", + "value" : "ההודעה ארוכה/גדולה מידי" + } + }, + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Il pacchetto è troppo grande" + } + }, + "pl" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pakiet jest zbyt duży" + } + }, + "se" : { + "stringUnit" : { + "state" : "translated", + "value" : "Paketet är för stort" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Пакет је превелики" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "数据包过大" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "數據包過大" + } + } + } + }, "The primary public key authorized to send admin messages to this node." : { "localizations" : { "de" : { diff --git a/Meshtastic/Enums/RoutingError.swift b/Meshtastic/Enums/RoutingError.swift index 628e1b3f..985794b3 100644 --- a/Meshtastic/Enums/RoutingError.swift +++ b/Meshtastic/Enums/RoutingError.swift @@ -32,31 +32,31 @@ enum RoutingError: Int, CaseIterable, Identifiable { switch self { case .none: - return "routing.acknowledged".localized + return "Acknowledged".localized case .noRoute: - return "routing.noroute".localized + return "No Route".localized case .gotNak: - return "routing.gotnak".localized + return "Received a negative acknowledgment".localized case .timeout: - return "routing.timeout".localized + return "Timeout".localized case .noInterface: - return "routing.nointerface".localized + return "No Interface".localized case .maxRetransmit: - return "routing.maxretransmit".localized + return "Max Retransmission Reached".localized case .noChannel: - return "routing.nochannel".localized + return "No Channel".localized case .tooLarge: - return "routing.toolarge".localized + return "The packet is too large".localized case .noResponse: - return "routing.noresponse".localized + return "No Response".localized case .dutyCycleLimit: - return "routing.dutycyclelimit".localized + return "Regional Duty Cycle Limit Reached".localized case .badRequest: - return "routing.badRequest".localized + return "Bad Request".localized case .notAuthorized: - return "routing.notauthorized".localized + return "Not Authorized".localized case .pkiFailed: - return "routing.pkifailed".localized + return "Encrypted Send Failed".localized case .pkiUnknownPubkey: return "Unknown public key".localized case .adminBadSessionKey: diff --git a/Meshtastic/Views/Nodes/DetectionSensorLog.swift b/Meshtastic/Views/Nodes/DetectionSensorLog.swift index 89c62be3..af07b9e7 100644 --- a/Meshtastic/Views/Nodes/DetectionSensorLog.swift +++ b/Meshtastic/Views/Nodes/DetectionSensorLog.swift @@ -110,7 +110,7 @@ struct DetectionSensorLog: View { exportString = detectionsToCsv(detections: chartData) isExporting = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift index 0d739c49..c958d1ae 100644 --- a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift +++ b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift @@ -222,7 +222,7 @@ struct DeviceMetricsLog: View { exportString = telemetryToCsvFile(telemetry: deviceMetrics, metricsType: 0) isExporting = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift b/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift index 7ae9bc50..160f3ef7 100644 --- a/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift +++ b/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift @@ -145,7 +145,7 @@ struct EnvironmentMetricsLog: View { exportString = telemetryToCsvFile(telemetry: environmentMetrics, metricsType: 1) isExporting = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") .imageScale(imageScale) } .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Nodes/PaxCounterLog.swift b/Meshtastic/Views/Nodes/PaxCounterLog.swift index ff579eca..58d68bb1 100644 --- a/Meshtastic/Views/Nodes/PaxCounterLog.swift +++ b/Meshtastic/Views/Nodes/PaxCounterLog.swift @@ -187,7 +187,7 @@ struct PaxCounterLog: View { exportString = paxToCsvFile(pax: pax) isExporting = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Settings/Channels.swift b/Meshtastic/Views/Settings/Channels.swift index 861f0cb3..bff2dbb7 100644 --- a/Meshtastic/Views/Settings/Channels.swift +++ b/Meshtastic/Views/Settings/Channels.swift @@ -219,7 +219,7 @@ struct Channels: View { hasChanges = false } } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil)// || !hasChanges)// !hasValidKey) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 7ac35423..f1f56e1a 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -45,7 +45,7 @@ struct RangeTestConfig: View { .font(.callout) Toggle(isOn: $save) { - Label("save", systemImage: "square.and.arrow.down.fill") + Label("Save", systemImage: "square.and.arrow.down.fill") Text("Saves a CSV with the range test message details, currently only available on ESP32 devices with a web server.") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) diff --git a/Meshtastic/Views/Settings/Config/SaveConfigButton.swift b/Meshtastic/Views/Settings/Config/SaveConfigButton.swift index 0c948a28..36b92443 100644 --- a/Meshtastic/Views/Settings/Config/SaveConfigButton.swift +++ b/Meshtastic/Views/Settings/Config/SaveConfigButton.swift @@ -12,7 +12,7 @@ struct SaveConfigButton: View { Button { isPresentingSaveConfirm = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Routes.swift b/Meshtastic/Views/Settings/Routes.swift index b7a80b31..23c4fa18 100644 --- a/Meshtastic/Views/Settings/Routes.swift +++ b/Meshtastic/Views/Settings/Routes.swift @@ -215,7 +215,7 @@ struct Routes: View { .buttonBorderShape(.capsule) .controlSize(.large) - Button("save") { + Button("Save") { selectedRoute?.name = name selectedRoute?.notes = notes selectedRoute?.enabled = enabled diff --git a/Meshtastic/Views/Settings/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index 0e8e13f1..892df6eb 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -43,7 +43,7 @@ struct SaveChannelQRCode: View { showError = true } } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) diff --git a/Meshtastic/Views/Settings/UserConfig.swift b/Meshtastic/Views/Settings/UserConfig.swift index 644c0077..51f55dbe 100644 --- a/Meshtastic/Views/Settings/UserConfig.swift +++ b/Meshtastic/Views/Settings/UserConfig.swift @@ -141,7 +141,7 @@ struct UserConfig: View { Button { isPresentingSaveConfirm = true } label: { - Label("save", systemImage: "square.and.arrow.down") + Label("Save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges) .buttonStyle(.bordered) From bb4cd7b0b208072f2106ef70ec62411fe20b7829 Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Mon, 5 May 2025 17:21:08 -0700 Subject: [PATCH 08/13] Fixed waypoints --- Meshtastic/Extensions/UserDefaults.swift | 2 +- .../Map/MapContent/MeshMapContent.swift | 2 +- .../Map/MapContent/NodeMapContent.swift | 2 +- .../Nodes/Helpers/Map/WaypointForm.swift | 88 ++++++++++++------- 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/Meshtastic/Extensions/UserDefaults.swift b/Meshtastic/Extensions/UserDefaults.swift index e1ca67f9..87bfe3f2 100644 --- a/Meshtastic/Extensions/UserDefaults.swift +++ b/Meshtastic/Extensions/UserDefaults.swift @@ -98,7 +98,7 @@ extension UserDefaults { @UserDefault(.meshMapDistance, defaultValue: 800000) static var meshMapDistance: Double - @UserDefault(.enableMapWaypoints, defaultValue: false) + @UserDefault(.enableMapWaypoints, defaultValue: true) static var enableMapWaypoints: Bool @UserDefault(.enableMapRecentering, defaultValue: false) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift index 6a0374f2..2ca86652 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift @@ -20,7 +20,7 @@ struct MeshMapContent: MapContent { @Binding var selectedMapLayer: MapLayer // Map Configuration @Binding var selectedPosition: PositionEntity? - @AppStorage("enableMapWaypoints") private var showWaypoints = false + @AppStorage("enableMapWaypoints") private var showWaypoints = true @Binding var selectedWaypoint: WaypointEntity? @FetchRequest(fetchRequest: PositionEntity.allPositionsFetchRequest(), animation: .easeIn) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift index c9fbf95a..2d157979 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/NodeMapContent.swift @@ -16,7 +16,7 @@ struct NodeMapContent: MapContent { /// Map State User Defaults @AppStorage("meshMapShowNodeHistory") private var showNodeHistory = false @AppStorage("meshMapShowRouteLines") private var showRouteLines = false - @AppStorage("enableMapWaypoints") private var showWaypoints = false + @AppStorage("enableMapWaypoints") private var showWaypoints = true @AppStorage("enableMapConvexHull") private var showConvexHull = false @AppStorage("enableMapTraffic") private var showTraffic: Bool = false @AppStorage("enableMapPointsOfInterest") private var showPointsOfInterest: Bool = false diff --git a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift index 736c2114..9eb42c23 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift @@ -134,40 +134,44 @@ struct WaypointForm: View { .scrollDismissesKeyboard(.immediately) HStack { Button { - /// Send a new or exiting waypoint - var newWaypoint = Waypoint() - if waypoint.id == 0 { - newWaypoint.id = UInt32.random(in: UInt32(UInt8.max).. 0 ? name : "Dropped Pin" - newWaypoint.description_p = description - // Unicode scalar value for the icon emoji string - let unicodeScalers = icon.unicodeScalars - // First element as an UInt32 - let unicode = unicodeScalers[unicodeScalers.startIndex].value - newWaypoint.icon = unicode - if locked { - if lockedTo == 0 { - newWaypoint.lockedTo = UInt32(bleManager.connectedPeripheral!.num) + if bleManager.isConnected { + /// Send a new or exiting waypoint + var newWaypoint = Waypoint() + if waypoint.id == 0 { + newWaypoint.id = UInt32.random(in: UInt32(UInt8.max).. 0 ? name : "Dropped Pin" + newWaypoint.description_p = description + // Unicode scalar value for the icon emoji string + let unicodeScalers = icon.unicodeScalars + // First element as an UInt32 + let unicode = unicodeScalers[unicodeScalers.startIndex].value + newWaypoint.icon = unicode + if locked { + if lockedTo == 0 { + newWaypoint.lockedTo = UInt32(bleManager.connectedPeripheral!.num) + } else { + newWaypoint.lockedTo = UInt32(lockedTo) + } + } + if expires { + newWaypoint.expire = UInt32(expire.timeIntervalSince1970) + } else { + newWaypoint.expire = 0 + } + if bleManager.sendWaypoint(waypoint: newWaypoint) { + dismiss() + } else { + dismiss() + Logger.mesh.warning("Send waypoint failed") } - } - if expires { - newWaypoint.expire = UInt32(expire.timeIntervalSince1970) } else { - newWaypoint.expire = 0 - } - if bleManager.sendWaypoint(waypoint: newWaypoint) { - dismiss() - } else { - dismiss() - Logger.mesh.warning("Send waypoint failed") + Logger.mesh.warning("Send waypoint failed, node not connected") } } label: { Label("Send", systemImage: "arrow.up") @@ -179,6 +183,16 @@ struct WaypointForm: View { .padding(.bottom) Button(role: .cancel) { + if waypoint.id == 0 { + // New, unsent waypoint created by the user: delete it + bleManager.context.delete(waypoint) + do { + try bleManager.context.save() + } catch { + bleManager.context.rollback() + Logger.mesh.error("Failed to save context on waypoint deletion: \(error)") + } + } dismiss() } label: { Label("Cancel", systemImage: "x.circle") @@ -364,6 +378,18 @@ struct WaypointForm: View { } } } + .onDisappear { + if waypoint.id == 0 { + // New, unsent waypoint created by the user: delete it + bleManager.context.delete(waypoint) + do { + try bleManager.context.save() + } catch { + bleManager.context.rollback() + Logger.mesh.error("Failed to save context on waypoint deletion: \(error)") + } + } + } .onAppear { if waypoint.id > 0 { let waypoint = getWaypoint(id: Int64(waypoint.id), context: bleManager.context) From afa5789fdfcc4ba6f7226c63d6e7783718c42688 Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Mon, 5 May 2025 22:06:08 -0700 Subject: [PATCH 09/13] Fix taping node circles and waypoints --- .../Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift index 2ca86652..4bce572c 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/MapContent/MeshMapContent.swift @@ -74,9 +74,9 @@ struct MeshMapContent: MapContent { } } } - .onTapGesture { _ in + .highPriorityGesture(TapGesture().onEnded { _ in selectedPosition = (selectedPosition == position ? nil : position) - } + }) } /// Node History and Route Lines for favorites if let nodePosition = position.nodePosition, @@ -186,7 +186,7 @@ struct MeshMapContent: MapContent { LazyVStack { ZStack { CircleText(text: String(UnicodeScalar(Int(waypoint.icon)) ?? "📍"), color: Color.orange, circleSize: 40) - .onTapGesture(perform: { _ in + .highPriorityGesture(TapGesture().onEnded { _ in selectedWaypoint = (selectedWaypoint == waypoint ? nil : waypoint) }) } From 46e0757f0368a6b0efaaff68b935bec6a040460f Mon Sep 17 00:00:00 2001 From: Benjamin Faershtein <119711889+RCGV1@users.noreply.github.com> Date: Mon, 5 May 2025 22:40:14 -0700 Subject: [PATCH 10/13] Only put delete if not sent logic in one place --- Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift index 9eb42c23..4f39a448 100644 --- a/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift +++ b/Meshtastic/Views/Nodes/Helpers/Map/WaypointForm.swift @@ -183,16 +183,6 @@ struct WaypointForm: View { .padding(.bottom) Button(role: .cancel) { - if waypoint.id == 0 { - // New, unsent waypoint created by the user: delete it - bleManager.context.delete(waypoint) - do { - try bleManager.context.save() - } catch { - bleManager.context.rollback() - Logger.mesh.error("Failed to save context on waypoint deletion: \(error)") - } - } dismiss() } label: { Label("Cancel", systemImage: "x.circle") From cf59865fce54ccb1db467aa50e8d6b3e45491a3d Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 6 May 2025 10:11:32 -0700 Subject: [PATCH 11/13] Additional translation key updates --- Localizable.xcstrings | 222 ++++++++--------------- Meshtastic/Enums/AppSettingsEnums.swift | 10 +- Meshtastic/Views/Messages/Messages.swift | 2 +- protobufs | 2 +- 4 files changed, 80 insertions(+), 156 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index d0125bad..9c32dc09 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -1816,61 +1816,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bestätigt" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Acknowledged" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Confirmé" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "מאשר" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Riconosciuto" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Potwierdzono" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bekräftad" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Потврђено" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "确认" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "已確認" } } @@ -3464,61 +3458,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Bad Request" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Bad Request" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Requête incorrecte" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "בקשה לא תקינה" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Richiesta negativa" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Złe żądanie" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Felaktig begäran" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Лош захтев" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "错误请求" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "錯誤請求" } } @@ -4572,61 +4560,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Kategorie" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Category" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Categoria" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Категорија" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Category" } } @@ -11433,31 +11415,25 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Verschlüsseltes Senden fehlgeschlagen" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Encrypted Send Failed" - } - }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Invio crittografato fallito" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Шифровано слање није успело" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "加密傳送失敗" } } @@ -11953,61 +11929,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", - "value" : "Export" - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Esportazione" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Извоз" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Export" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "匯出" } } @@ -14747,7 +14717,7 @@ } } }, - "hybrid" : { + "Hybrid" : { "localizations" : { "de" : { "stringUnit" : { @@ -14811,7 +14781,7 @@ } } }, - "hybrid.flyover" : { + "Hybrid Flyover" : { "localizations" : { "de" : { "stringUnit" : { @@ -15311,61 +15281,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Unvollständig" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Incomplete" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incomplete" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incomplete" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incompleto" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incomplete" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incomplete" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Недовршен" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Incomplete" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "尚未完成" } } @@ -19753,61 +19717,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Maximale Wiederholungen erreicht" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Max Retransmission Reached" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Nombre maximum de retransmissions atteint" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הגיע למקסימום השליחות מדש" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Raggiunta la massima ritrasmissione" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Osiągnięto limit retransmisji" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Max antal omsändningar nått" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Достигнут максималан број поновних слања" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "已达到最大重试次数" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "已達到最大重試次數" } } @@ -22425,93 +22383,59 @@ } } }, - "messages" : { + "Messages" : { "localizations" : { "de" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Nachrichten" } }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Messages" - } - }, "fr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Messages" } }, "he" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "הודעות" } }, "it" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Messaggi" } }, "pl" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Wiadomości" } }, "se" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Meddelanden" } }, "sr" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "Поруке" } }, "zh-Hans" : { "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "消息" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "translated", - "value" : "訊息" - } - } - } - }, - "Messages" : { - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Nachrichten" - } - }, - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Messaggi" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Поруке" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", + "state" : "needs_review", "value" : "訊息" } } @@ -29636,7 +29560,7 @@ } } }, - "satellite" : { + "Satellite" : { "localizations" : { "de" : { "stringUnit" : { @@ -29700,7 +29624,7 @@ } } }, - "satellite.flyover" : { + "Satellite Flyover" : { "localizations" : { "de" : { "stringUnit" : { @@ -32706,7 +32630,7 @@ } } }, - "standard.muted" : { + "Standard Muted" : { "localizations" : { "de" : { "stringUnit" : { diff --git a/Meshtastic/Enums/AppSettingsEnums.swift b/Meshtastic/Enums/AppSettingsEnums.swift index 0d84269a..5ddcaad7 100644 --- a/Meshtastic/Enums/AppSettingsEnums.swift +++ b/Meshtastic/Enums/AppSettingsEnums.swift @@ -21,15 +21,15 @@ enum MeshMapTypes: Int, CaseIterable, Identifiable { case .standard: return "Standard".localized case .mutedStandard: - return "standard.muted".localized + return "Standard Muted".localized case .hybrid: - return "hybrid".localized + return "Hybrid".localized case .hybridFlyover: - return "hybrid.flyover".localized + return "Hybrid Flyover".localized case .satellite: - return "satellite".localized + return "Satellite".localized case .satelliteFlyover: - return "satellite.flyover".localized + return "Satellite Flyover".localized } } func MKMapTypeValue() -> MKMapType { diff --git a/Meshtastic/Views/Messages/Messages.swift b/Meshtastic/Views/Messages/Messages.swift index 6142617b..7580079b 100644 --- a/Meshtastic/Views/Messages/Messages.swift +++ b/Meshtastic/Views/Messages/Messages.swift @@ -65,7 +65,7 @@ struct Messages: View { TipView(MessagesTip(), arrowEdge: .top) } - .navigationTitle("messages") + .navigationTitle("Messages") .navigationBarTitleDisplayMode(.large) .navigationBarItems(leading: MeshtasticLogo()) } content: { diff --git a/protobufs b/protobufs index 27fac391..06864665 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 27fac39141d99fe727a0a1824c5397409b1aea75 +Subproject commit 068646653e8375fc145988026ad242a3cf70f7ab From 8b48c6783099417f19b28f2fc0b025f70a321e13 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 6 May 2025 10:18:20 -0700 Subject: [PATCH 12/13] Mark updated keys as reviewed --- Localizable.xcstrings | 108 +++++++++++++++++++++--------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index 9c32dc09..1d2cc028 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -1816,25 +1816,25 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Bestätigt" } }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Confirmé" } }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "מאשר" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Riconosciuto" } }, @@ -1846,13 +1846,13 @@ }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Bekräftad" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Потврђено" } }, @@ -1864,7 +1864,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "已確認" } } @@ -3464,49 +3464,49 @@ }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Requête incorrecte" } }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "בקשה לא תקינה" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Richiesta negativa" } }, "pl" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Złe żądanie" } }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Felaktig begäran" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Лош захтев" } }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "错误请求" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "錯誤請求" } } @@ -4560,7 +4560,7 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Kategorie" } }, @@ -4578,7 +4578,7 @@ }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Categoria" } }, @@ -4596,7 +4596,7 @@ }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Категорија" } }, @@ -11415,19 +11415,19 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Verschlüsseltes Senden fehlgeschlagen" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Invio crittografato fallito" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Шифровано слање није успело" } }, @@ -11947,7 +11947,7 @@ }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Esportazione" } }, @@ -11965,7 +11965,7 @@ }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Извоз" } }, @@ -11977,7 +11977,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "匯出" } } @@ -15281,13 +15281,13 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Unvollständig" } }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Incomplete" } }, @@ -15317,7 +15317,7 @@ }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Недовршен" } }, @@ -15329,7 +15329,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "尚未完成" } } @@ -19717,55 +19717,55 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Maximale Wiederholungen erreicht" } }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Nombre maximum de retransmissions atteint" } }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "הגיע למקסימום השליחות מדש" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Raggiunta la massima ritrasmissione" } }, "pl" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Osiągnięto limit retransmisji" } }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Max antal omsändningar nått" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Достигнут максималан број поновних слања" } }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "已达到最大重试次数" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "已達到最大重試次數" } } @@ -22387,7 +22387,7 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Nachrichten" } }, @@ -22399,43 +22399,43 @@ }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "הודעות" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Messaggi" } }, "pl" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Wiadomości" } }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Meddelanden" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Поруке" } }, "zh-Hans" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "消息" } }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "訊息" } } @@ -25293,7 +25293,7 @@ }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Мод упаривања" } }, @@ -29776,43 +29776,43 @@ "localizations" : { "de" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Speichern" } }, "fr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Sauvegarder" } }, "he" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "שמור" } }, "it" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Risparmiare" } }, "pl" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Zapisz" } }, "se" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Spara" } }, "sr" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "Сачувај" } }, @@ -29824,7 +29824,7 @@ }, "zh-Hant-TW" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "儲存" } } From bad7e7da914543a11cd9ea000a3bd6cca9105db9 Mon Sep 17 00:00:00 2001 From: Garth Vander Houwen Date: Tue, 6 May 2025 12:13:12 -0700 Subject: [PATCH 13/13] Fix message localization --- Localizable.xcstrings | 159 +++++++++--------- .../TextMessageField/TextMessageField.swift | 2 +- protobufs | 2 +- 3 files changed, 83 insertions(+), 80 deletions(-) diff --git a/Localizable.xcstrings b/Localizable.xcstrings index de4df376..99d00c53 100644 --- a/Localizable.xcstrings +++ b/Localizable.xcstrings @@ -11428,6 +11428,34 @@ } } }, + "Environment Metrics" : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Metriche dei sensori" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Метрике сензора" + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "传感器指标" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "傳感器數據" + } + } + } + }, "Environment Metrics Log" : { "localizations" : { "it" : { @@ -14370,34 +14398,6 @@ } } }, - "How often power metrics are sent out over the mesh. Default is 30 minutes." : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Con quale frequenza vengono inviate le metriche di potenza attraverso la rete. L'impostazione predefinita è 30 minuti." - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Колико често се метрике снаге шаљу преко мреже. Подразумевано је 30 минута." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "通过网格发送功率指标的频率。默认为 30 分钟。" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "電力指標透過網狀網路發送的頻率。預設為每 30 分鐘一次。" - } - } - } - }, "How often environment metrics are sent out over the mesh. Default is 30 minutes." : { "localizations" : { "it" : { @@ -14426,6 +14426,34 @@ } } }, + "How often power metrics are sent out over the mesh. Default is 30 minutes." : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "Con quale frequenza vengono inviate le metriche di potenza attraverso la rete. L'impostazione predefinita è 30 minuti." + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Колико често се метрике снаге шаљу преко мреже. Подразумевано је 30 минута." + } + }, + "zh-Hans" : { + "stringUnit" : { + "state" : "translated", + "value" : "通过网格发送功率指标的频率。默认为 30 分钟。" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "電力指標透過網狀網路發送的頻率。預設為每 30 分鐘一次。" + } + } + } + }, "How often should we try to get a GPS position." : { "localizations" : { "it" : { @@ -18592,28 +18620,6 @@ } } }, - "Long Range - Fast" : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "A lungo raggio - Veloce" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дугачки домет - Брзо" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "Long Range - Fast" - } - } - } - }, "Long Name" : { "localizations" : { "de" : { @@ -18710,6 +18716,28 @@ } } }, + "Long Range - Fast" : { + "localizations" : { + "it" : { + "stringUnit" : { + "state" : "translated", + "value" : "A lungo raggio - Veloce" + } + }, + "sr" : { + "stringUnit" : { + "state" : "translated", + "value" : "Дугачки домет - Брзо" + } + }, + "zh-Hant-TW" : { + "stringUnit" : { + "state" : "translated", + "value" : "Long Range - Fast" + } + } + } + }, "Long Range - Slow" : { "localizations" : { "it" : { @@ -22135,6 +22163,9 @@ } } } + }, + "message" : { + }, "Message" : { "localizations" : { @@ -31078,34 +31109,6 @@ } } }, - "Environment Metrics" : { - "localizations" : { - "it" : { - "stringUnit" : { - "state" : "translated", - "value" : "Metriche dei sensori" - } - }, - "sr" : { - "stringUnit" : { - "state" : "translated", - "value" : "Метрике сензора" - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "传感器指标" - } - }, - "zh-Hant-TW" : { - "stringUnit" : { - "state" : "translated", - "value" : "傳感器數據" - } - } - } - }, "Sensor options" : { "localizations" : { "it" : { diff --git a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift index c642a9b7..d60a0381 100644 --- a/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift +++ b/Meshtastic/Views/Messages/TextMessageField/TextMessageField.swift @@ -44,7 +44,7 @@ struct TextMessageField: View { } ZStack { - TextField("message", text: $typingMessage, axis: .vertical) + TextField("Message", text: $typingMessage, axis: .vertical) .onChange(of: typingMessage) { _, value in totalBytes = value.utf8.count while totalBytes > Self.maxbytes { diff --git a/protobufs b/protobufs index 27fac391..06864665 160000 --- a/protobufs +++ b/protobufs @@ -1 +1 @@ -Subproject commit 27fac39141d99fe727a0a1824c5397409b1aea75 +Subproject commit 068646653e8375fc145988026ad242a3cf70f7ab