Guard string tables against silent corruption

A .strings value may span several physical lines, so deleting such an
entry line by line leaves orphaned lines that the parser folds into the
preceding value. Every key behind that point then disappears at runtime
while plutil -lint still reports OK. Tab titles are looked up without a
defaultValue:, so the tab bar rendered raw keys like "tab.overview"
while the rest of the UI fell back to its English defaults.

LocalizationIntegrityTests parses each table out of the app bundle and
fails on multi-line values, on missing keys that have no fallback, and
on leftover cable.pro.* entries. LocalizedTabBarUITests launches the app
in German and asserts the tab bar is translated.
This commit is contained in:
2026-08-18 10:59:38 +02:00
parent 38183f5282
commit eb9efee9af
2 changed files with 137 additions and 0 deletions

View File

@@ -0,0 +1,62 @@
import XCTest
/// Reproduces the regression where the tab bar rendered raw keys ("tab.overview") because a
/// malformed entry in Localizable.strings hid every key behind it. The tab titles are looked up
/// without a `defaultValue:`, so a broken table is immediately visible here.
final class LocalizedTabBarUITests: XCTestCase {
override func setUpWithError() throws {
try super.setUpWithError()
continueAfterFailure = false
XCUIDevice.shared.orientation = .portrait
}
@MainActor
func testTabBarIsLocalizedInGerman() throws {
let app = XCUIApplication()
app.launchArguments = [
"--uitest-reset-data",
"--uitest-sample-data",
"-AppleLanguages", "(de)",
"-AppleLocale", "de_DE",
]
app.launch()
openFirstSystem(in: app)
let expected = ["Übersicht", "Verbraucher", "Batterien", "Ladegeräte"]
for title in expected {
XCTAssertTrue(
app.buttons[title].waitForExistence(timeout: 15),
"Tab \"\(title)\" is missing — the German string table is not being read"
)
}
for rawKey in ["tab.overview", "tab.components", "tab.batteries", "tab.chargers"] {
XCTAssertFalse(
app.buttons[rawKey].exists,
"Tab bar shows the raw key \(rawKey) instead of a translation"
)
}
}
private func openFirstSystem(in app: XCUIApplication) {
let list: XCUIElement
if app.collectionViews["systems-list"].waitForExistence(timeout: 15) {
list = app.collectionViews["systems-list"]
} else {
list = app.collectionViews.firstMatch
}
XCTAssertTrue(list.waitForExistence(timeout: 15))
let firstCell = list.cells.element(boundBy: 0)
XCTAssertTrue(firstCell.waitForExistence(timeout: 10))
let cellButton = firstCell.buttons.firstMatch
if cellButton.exists {
cellButton.tap()
} else {
firstCell.coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
}
}
}