From fb527a41f9fdab53ec3b51eb294ef59742f301b3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:34:02 +0000 Subject: [PATCH 1/2] Initial plan From 8e3537480d22bf27fbde38a31c911c74b21cc81a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 11 Mar 2026 13:40:40 +0000 Subject: [PATCH 2/2] Support integers as cell values in ValueRange decoder Co-authored-by: olejnjak <3148214+olejnjak@users.noreply.github.com> --- .../Model/ValueRange.swift | 28 ++++++++++++++++ .../ACKLocalizationTests.swift | 32 +++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/Sources/ACKLocalizationCore/Model/ValueRange.swift b/Sources/ACKLocalizationCore/Model/ValueRange.swift index 2f7096b..5885400 100644 --- a/Sources/ACKLocalizationCore/Model/ValueRange.swift +++ b/Sources/ACKLocalizationCore/Model/ValueRange.swift @@ -22,4 +22,32 @@ public struct ValueRange: Decodable { public init(values: [[String]]) { self.values = values } + + public init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + let rawValues = try container.decode([[AnyCellValue]].self, forKey: .values) + self.values = rawValues.map { $0.map(\.stringValue) } + } + + private enum CodingKeys: String, CodingKey { + case values + } +} + +/// A helper type that decodes a single sheet cell value, supporting strings and numbers. +private struct AnyCellValue: Decodable { + let stringValue: String + + init(from decoder: Decoder) throws { + let container = try decoder.singleValueContainer() + if let string = try? container.decode(String.self) { + stringValue = string + } else if let int = try? container.decode(Int.self) { + stringValue = String(int) + } else if let double = try? container.decode(Double.self) { + stringValue = String(double) + } else { + stringValue = "" + } + } } diff --git a/Tests/ACKLocalizationCoreTests/ACKLocalizationTests.swift b/Tests/ACKLocalizationCoreTests/ACKLocalizationTests.swift index f8cccf8..e1dceaa 100644 --- a/Tests/ACKLocalizationCoreTests/ACKLocalizationTests.swift +++ b/Tests/ACKLocalizationCoreTests/ACKLocalizationTests.swift @@ -45,4 +45,36 @@ final class ACKLocalizationTests: XCTestCase { let fileName = "Localizable.strings" XCTAssertEqual("Localizable", fileName.removingSuffix(".strings")) } + + func test_valueRange_decodesIntegerCellValues() throws { + let json = #"{"values":[["key","en"],["some_key",42]]}"# + let valueRange = try JSONDecoder().decode(ValueRange.self, from: Data(json.utf8)) + XCTAssertEqual(valueRange.values, [["key", "en"], ["some_key", "42"]]) + } + + func test_valueRange_decodesDoubleCellValues() throws { + let json = #"{"values":[["key","en"],["price_key",3.14]]}"# + let valueRange = try JSONDecoder().decode(ValueRange.self, from: Data(json.utf8)) + XCTAssertEqual(valueRange.values, [["key", "en"], ["price_key", "3.14"]]) + } + + func test_valueRange_decodesMixedCellValues() throws { + let json = #"{"values":[["key","en"],["str_key","hello"],["int_key",7]]}"# + let valueRange = try JSONDecoder().decode(ValueRange.self, from: Data(json.utf8)) + XCTAssertEqual(valueRange.values, [["key", "en"], ["str_key", "hello"], ["int_key", "7"]]) + } + + func test_transform_integerCellValue() throws { + let json = #"{"values":[["keys","en"],["count",42]]}"# + let valueRange = try JSONDecoder().decode(ValueRange.self, from: Data(json.utf8)) + let mappedValues = try localization.transformValues( + valueRange, + with: ["en": "en"], + keyColumnName: "keys" + ) + XCTAssertEqual( + mappedValues["en"], + [LocRow(key: "count", value: "42")] + ) + } }