diff --git a/Meshtastic.xcodeproj/project.pbxproj b/Meshtastic.xcodeproj/project.pbxproj index ce7109d7..14f1609a 100644 --- a/Meshtastic.xcodeproj/project.pbxproj +++ b/Meshtastic.xcodeproj/project.pbxproj @@ -98,6 +98,7 @@ DDC2E1A726CEB3400042C5E4 /* LocationHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC2E1A626CEB3400042C5E4 /* LocationHelper.swift */; }; DDC3B274283F411B00AC321C /* LastHeardText.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC3B273283F411B00AC321C /* LastHeardText.swift */; }; DDC4D568275499A500A4208E /* Persistence.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDC4D567275499A500A4208E /* Persistence.swift */; }; + DDCDC6CB29481FCC004C1DDA /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = DDCDC6CD29481FCC004C1DDA /* Localizable.strings */; }; DDCE4E2C2869F92900BE9F8F /* UserConfig.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */; }; DDCFF601285453A7005FA625 /* localonly.pb.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDCFF600285453A7005FA625 /* localonly.pb.swift */; }; DDD3BBD5292D763200D609B3 /* MeshtasticTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDD3BBD4292D763200D609B3 /* MeshtasticTests.swift */; }; @@ -222,6 +223,8 @@ DDC3B273283F411B00AC321C /* LastHeardText.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LastHeardText.swift; sourceTree = ""; }; DDC4D567275499A500A4208E /* Persistence.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Persistence.swift; sourceTree = ""; }; DDCDC69A29467643004C1DDA /* MeshtasticDataModelV3.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = MeshtasticDataModelV3.xcdatamodel; sourceTree = ""; }; + DDCDC6CC29481FCC004C1DDA /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = ""; }; + DDCDC6CE294821AD004C1DDA /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; DDCE4E2B2869F92900BE9F8F /* UserConfig.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserConfig.swift; sourceTree = ""; }; DDCFF600285453A7005FA625 /* localonly.pb.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = localonly.pb.swift; sourceTree = ""; }; DDD3BBD4292D763200D609B3 /* MeshtasticTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MeshtasticTests.swift; sourceTree = ""; }; @@ -401,6 +404,7 @@ DDC2E14B26CE248E0042C5E4 = { isa = PBXGroup; children = ( + DDCDC6CD29481FCC004C1DDA /* Localizable.strings */, DD3CC6BA28E366DF00FA9159 /* Meshtastic.xcdatamodeld */, DDC2E15626CE248E0042C5E4 /* Meshtastic */, DDC2E16D26CE248F0042C5E4 /* MeshtasticTests */, @@ -641,6 +645,7 @@ hasScannedForEncodings = 0; knownRegions = ( en, + de, Base, ); mainGroup = DDC2E14B26CE248E0042C5E4; @@ -665,6 +670,7 @@ buildActionMask = 2147483647; files = ( DDC2E15F26CE248F0042C5E4 /* Preview Assets.xcassets in Resources */, + DDCDC6CB29481FCC004C1DDA /* Localizable.strings in Resources */, DDC2E15C26CE248F0042C5E4 /* Assets.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -835,11 +841,24 @@ }; /* End PBXTargetDependency section */ +/* Begin PBXVariantGroup section */ + DDCDC6CD29481FCC004C1DDA /* Localizable.strings */ = { + isa = PBXVariantGroup; + children = ( + DDCDC6CC29481FCC004C1DDA /* en */, + DDCDC6CE294821AD004C1DDA /* de */, + ); + name = Localizable.strings; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + /* Begin XCBuildConfiguration section */ DDC2E17C26CE248F0042C5E4 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; @@ -901,6 +920,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; diff --git a/Meshtastic/Views/Bluetooth/Connect.swift b/Meshtastic/Views/Bluetooth/Connect.swift index f2875e5e..50757c31 100644 --- a/Meshtastic/Views/Bluetooth/Connect.swift +++ b/Meshtastic/Views/Bluetooth/Connect.swift @@ -28,7 +28,7 @@ struct Connect: View { VStack { List { if bleManager.isSwitchedOn { - Section(header: Text("Connected Radio").font(.title)) { + Section(header: Text("connected.radio").font(.title)) { if bleManager.connectedPeripheral != nil && bleManager.connectedPeripheral.peripheral.state == .connected { HStack { Image(systemName: "antenna.radiowaves.left.and.right") @@ -160,7 +160,7 @@ struct Connect: View { .textCase(nil) if !self.bleManager.isConnected { - Section(header: Text("Available Radios").font(.title)) { + Section(header: Text("available.radios").font(.title)) { ForEach(bleManager.peripherals.filter({ $0.peripheral.state == CBPeripheralState.disconnected }).sorted(by: { $0.name > $1.name })) { peripheral in HStack { Image(systemName: "circle.fill") diff --git a/Meshtastic/Views/Helpers/LastHeardText.swift b/Meshtastic/Views/Helpers/LastHeardText.swift index 36bfaa9d..eb68fd57 100644 --- a/Meshtastic/Views/Helpers/LastHeardText.swift +++ b/Meshtastic/Views/Helpers/LastHeardText.swift @@ -17,7 +17,17 @@ struct LastHeardText: View { } else { - Text("Unknown Age") + Text("unknown.age") } } } +struct LastHeardText_Previews: PreviewProvider { + static var previews: some View { + LastHeardText(lastHeard: Date()) + .previewLayout(.fixed(width: 300, height: 100)) + .environment(\.locale, .init(identifier: "en")) + LastHeardText(lastHeard: Date()) + .previewLayout(.fixed(width: 300, height: 100)) + .environment(\.locale, .init(identifier: "de")) + } +} diff --git a/Meshtastic/Views/Messages/ChannelMessageList.swift b/Meshtastic/Views/Messages/ChannelMessageList.swift index 6b61a9da..4d8094ec 100644 --- a/Meshtastic/Views/Messages/ChannelMessageList.swift +++ b/Meshtastic/Views/Messages/ChannelMessageList.swift @@ -144,7 +144,7 @@ struct ChannelMessageList: View { self.deleteMessageId = message.messageId print(deleteMessageId) }) { - Text("Delete") + Text("delete") Image(systemName: "trash") } } diff --git a/Meshtastic/Views/Messages/Contacts.swift b/Meshtastic/Views/Messages/Contacts.swift index 54b00d9e..b6705dc5 100644 --- a/Meshtastic/Views/Messages/Contacts.swift +++ b/Meshtastic/Views/Messages/Contacts.swift @@ -28,7 +28,7 @@ struct Contacts: View { NavigationSplitView { List { - Section(header: Text("Channels (groups)")) { + Section(header: Text("channels")) { // Display Contacts for the rest of the non admin channels if node != nil && node!.myInfo != nil && node!.myInfo!.channels != nil { ForEach(node!.myInfo!.channels!.array as! [ChannelEntity], id: \.self) { (channel: ChannelEntity) in @@ -128,7 +128,7 @@ struct Contacts: View { deleteChannelMessages(channelIndex: channel.index, context: context) context.refreshAllObjects() } label: { - Text("Delete") + Text("delete") } } } @@ -137,7 +137,7 @@ struct Contacts: View { } } - Section(header: Text("Direct Messages")) { + Section(header: Text("direct.messages")) { ForEach(users) { (user: UserEntity) in if user.num != bleManager.userSettings?.preferredNodeNum ?? 0 { NavigationLink(destination: UserMessageList(user: user)) { @@ -214,7 +214,7 @@ struct Contacts: View { deleteUserMessages(user: user, context: context) } label: { - Text("Delete") + Text("delete") } } } @@ -227,7 +227,7 @@ struct Contacts: View { } } } - .navigationTitle("Contacts") + .navigationTitle("contacts") .navigationBarItems(leading: MeshtasticLogo() ) @@ -260,7 +260,7 @@ struct Contacts: View { UserMessageList(user:user) } else { - Text("Select a Contact") + Text("select.contact") } } } diff --git a/Meshtastic/Views/Messages/UserMessageList.swift b/Meshtastic/Views/Messages/UserMessageList.swift index f2c4f98e..a8d87bad 100644 --- a/Meshtastic/Views/Messages/UserMessageList.swift +++ b/Meshtastic/Views/Messages/UserMessageList.swift @@ -127,7 +127,7 @@ struct UserMessageList: View { if ackDate >= sixMonthsAgo! { Text((ackDate.formattedDate(format: "h:mm:ss a"))).font(.caption2).foregroundColor(.gray) } else { - Text("Unknown Age").font(.caption2).foregroundColor(.gray) + Text("unknown.age").font(.caption2).foregroundColor(.gray) } } } @@ -145,7 +145,7 @@ struct UserMessageList: View { self.deleteMessageId = message.messageId print(deleteMessageId) }) { - Text("Delete") + Text("delete") Image(systemName: "trash") } } diff --git a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift index e8e73d5e..70ea6137 100644 --- a/Meshtastic/Views/Nodes/DeviceMetricsLog.swift +++ b/Meshtastic/Views/Nodes/DeviceMetricsLog.swift @@ -148,7 +148,7 @@ struct DeviceMetricsLog: View { exportString = TelemetryToCsvFile(telemetry: node.telemetries!.array as! [TelemetryEntity], 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 a8d2c2b3..d9795950 100644 --- a/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift +++ b/Meshtastic/Views/Nodes/EnvironmentMetricsLog.swift @@ -156,7 +156,7 @@ struct EnvironmentMetricsLog: View { } 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/PositionLog.swift b/Meshtastic/Views/Nodes/PositionLog.swift index b31e9b2a..b4de4ad2 100644 --- a/Meshtastic/Views/Nodes/PositionLog.swift +++ b/Meshtastic/Views/Nodes/PositionLog.swift @@ -137,7 +137,7 @@ struct PositionLog: View { } 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/Config/BluetoothConfig.swift b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift index 412282aa..ae2e1f93 100644 --- a/Meshtastic/Views/Settings/Config/BluetoothConfig.swift +++ b/Meshtastic/Views/Settings/Config/BluetoothConfig.swift @@ -87,7 +87,7 @@ struct BluetoothConfig: View { Button { isPresentingSaveConfirm = true } label: { - Label("Save", systemImage: "square.and.arrow.down") + Label("save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges || shortPin) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Config/DeviceConfig.swift b/Meshtastic/Views/Settings/Config/DeviceConfig.swift index 6800a117..c72a1b8a 100644 --- a/Meshtastic/Views/Settings/Config/DeviceConfig.swift +++ b/Meshtastic/Views/Settings/Config/DeviceConfig.swift @@ -143,7 +143,7 @@ struct DeviceConfig: View { } 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/Config/DisplayConfig.swift b/Meshtastic/Views/Settings/Config/DisplayConfig.swift index 318bb111..69d14a44 100644 --- a/Meshtastic/Views/Settings/Config/DisplayConfig.swift +++ b/Meshtastic/Views/Settings/Config/DisplayConfig.swift @@ -97,7 +97,7 @@ struct DisplayConfig: View { } 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/Config/LoRaConfig.swift b/Meshtastic/Views/Settings/Config/LoRaConfig.swift index e5584f3d..306cac72 100644 --- a/Meshtastic/Views/Settings/Config/LoRaConfig.swift +++ b/Meshtastic/Views/Settings/Config/LoRaConfig.swift @@ -63,7 +63,7 @@ struct LoRaConfig: 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/Config/Module/CannedMessagesConfig.swift b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift index 6d83625a..0ebe4ded 100644 --- a/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/CannedMessagesConfig.swift @@ -212,7 +212,7 @@ struct CannedMessagesConfig: View { isPresentingSaveConfirm = true } label: { - Label("Save", systemImage: "square.and.arrow.down") + Label("save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || (!hasChanges && !hasMessagesChanges)) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift index 5bceaec3..f6d3fdaa 100644 --- a/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/ExternalNotificationConfig.swift @@ -123,7 +123,7 @@ struct ExternalNotificationConfig: 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/Config/Module/MQTTConfig.swift b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift index a8b135d9..c7ea369f 100644 --- a/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/MQTTConfig.swift @@ -144,7 +144,7 @@ struct MQTTConfig: View { } 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/Config/Module/RangeTestConfig.swift b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift index 56ea350f..1e5d7f12 100644 --- a/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/RangeTestConfig.swift @@ -76,7 +76,7 @@ struct RangeTestConfig: View { Text("This device will send out range test messages on the selected interval.") .font(.caption) Toggle(isOn: $save) { - Label("Save", systemImage: "square.and.arrow.down.fill") + Label("save", systemImage: "square.and.arrow.down.fill") } .toggleStyle(SwitchToggleStyle(tint: .accentColor)) .disabled(!(node != nil && node!.myInfo?.hasWifi ?? false)) @@ -88,7 +88,7 @@ struct RangeTestConfig: View { Button { isPresentingSaveConfirm = true } label: { - Label("Save", systemImage: "square.and.arrow.down") + Label("save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges || !(node?.myInfo?.hasWifi ?? false)) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift index 16eea485..f09e8500 100644 --- a/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/SerialConfig.swift @@ -113,7 +113,7 @@ struct SerialConfig: View { } 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/Config/Module/TelemetryConfig.swift b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift index c944d987..621db50c 100644 --- a/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift +++ b/Meshtastic/Views/Settings/Config/Module/TelemetryConfig.swift @@ -125,7 +125,7 @@ struct TelemetryConfig: View { Button { isPresentingSaveConfirm = true } label: { - Label("Save", systemImage: "square.and.arrow.down") + Label("save", systemImage: "square.and.arrow.down") } .disabled(bleManager.connectedPeripheral == nil || !hasChanges || node!.telemetryConfig == nil) .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/Config/NetworkConfig.swift b/Meshtastic/Views/Settings/Config/NetworkConfig.swift index 3d3bafb9..383aac0a 100644 --- a/Meshtastic/Views/Settings/Config/NetworkConfig.swift +++ b/Meshtastic/Views/Settings/Config/NetworkConfig.swift @@ -96,7 +96,7 @@ struct NetworkConfig: 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/Config/PositionConfig.swift b/Meshtastic/Views/Settings/Config/PositionConfig.swift index 361df32d..533cad90 100644 --- a/Meshtastic/Views/Settings/Config/PositionConfig.swift +++ b/Meshtastic/Views/Settings/Config/PositionConfig.swift @@ -193,7 +193,7 @@ struct PositionConfig: View { } 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/SaveChannelQRCode.swift b/Meshtastic/Views/Settings/SaveChannelQRCode.swift index 7f375268..c556dcfa 100644 --- a/Meshtastic/Views/Settings/SaveChannelQRCode.swift +++ b/Meshtastic/Views/Settings/SaveChannelQRCode.swift @@ -32,7 +32,7 @@ struct SaveChannelQRCode: View { } } label: { - Label("Save", systemImage: "square.and.arrow.down") + Label("save", systemImage: "square.and.arrow.down") } .buttonStyle(.bordered) .buttonBorderShape(.capsule) @@ -44,7 +44,7 @@ struct SaveChannelQRCode: View { Button { dismiss() } label: { - Label("Cancel", systemImage: "xmark") + Label("cancel", systemImage: "xmark") } .buttonStyle(.bordered) diff --git a/Meshtastic/Views/Settings/UserConfig.swift b/Meshtastic/Views/Settings/UserConfig.swift index c8fe32b4..6380430b 100644 --- a/Meshtastic/Views/Settings/UserConfig.swift +++ b/Meshtastic/Views/Settings/UserConfig.swift @@ -72,7 +72,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) diff --git a/de.lproj/Localizable.strings b/de.lproj/Localizable.strings new file mode 100644 index 00000000..58c5366a --- /dev/null +++ b/de.lproj/Localizable.strings @@ -0,0 +1,13 @@ +/* + Localizable.strings + Meshtastic + + Created by Garth Vander Houwen on 12/12/22. + +*/ +//"available.radios"="Verfügbare Funkgeräte"; +//"cancel"="Absagen"; +//"connected.radio"="Verbundenes Radio"; +//"delete"="Löschen"; +//"save"="Speichern"; +//"unknown.age"="Unbekanntes Alter"; diff --git a/en.lproj/Localizable.strings b/en.lproj/Localizable.strings new file mode 100644 index 00000000..b12c646f --- /dev/null +++ b/en.lproj/Localizable.strings @@ -0,0 +1,17 @@ +/* + Localizable.strings + Meshtastic + + Copyright(c) Garth Vander Houwen on 12/12/22. + +*/ +"available.radios"="Available Radios"; +"cancel"="Cancel"; +"channels"="Channels (groups)"; +"connected.radio"="Connected Radio"; +"contacts"="Contacts"; +"delete"="Delete"; +"direct.messages"="Direct Messages"; +"save"="Save"; +"select.contact"="Select a Contact"; +"unknown.age"="Unknown Age";