VoiceOver reads out decimal numbers incorrectly

VoiceOver sometimes reads decimal numbers in the US locale with a "dot" instead of "point".


e.g. 4.29 out of 5 stars -> "four dot twenty nine out of five stars"


Is there a way to force it to interpret it as a decimal number?

Replies

Wow, no reply in 7 years! Maybe I can help :)

Rather than rely on VoiceOver to interpret your strings, what if you rely on explicitly spelling out the period so an accessibility label would comprise "four point twenty nine out of five stars"? One way to do this is explicitly set a MeasurementFormatter's numberFormatter property with a new NumberFormatter instance whose numberStyle property is set to .spellOut:

class UnitRating: Dimension {
    override static func baseUnit() -> Self {
        return UnitRating.star as! Self
    }

    static let star = UnitRating(
      symbol: "star",
      converter: UnitConverterLinear(coefficient: 1.0)
    )
}

final class VoiceOverSeparatorAnnouncementWorkaroundTest: XCTestCase {
  func testVoiceOverAnnouncingPoint() {
    let measurementFormatter = MeasurementFormatter()
    measurementFormatter.unitOptions = .providedUnit
    measurementFormatter.numberFormatter = {
      let formatter = NumberFormatter()
      formatter.numberStyle = .spellOut
      return formatter
    }()
    measurementFormatter.unitStyle = .long

    XCTAssertEqual(
      measurementFormatter.string(
        from: .init(value: 0.0, unit: UnitRating.star)
      ),
      "zero star"
    )

    XCTAssertEqual(
      measurementFormatter.string(
        from: .init(value: 1.0, unit: UnitRating.star)
      ),
      "one star"
    )

    XCTAssertEqual(
      measurementFormatter.string(
        from: .init(value: 0.1, unit: UnitRating.star)
      ),
      "zero point one star"
    )

    XCTAssertEqual(
      measurementFormatter.string(
        from: .init(value: 5.1, unit: UnitRating.star)
      ),
      "five point one star"
    )
  }
}

While the example above does not take localization into account, I imagine this can be a starting point (assuming this is still a problem for you LOL)