From e01935e4be598b36c62a441f4d5fe54db1b3d74b Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Fri, 24 Jul 2026 18:23:55 -0700 Subject: [PATCH 1/4] Add ./xcstrings, a String Catalog normalizer matching Xcode's serializer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Xcode rewrites a `.xcstrings` in place during an IDE build whenever string extraction finds a key the catalog doesn't have yet, and it writes the *whole* file with its own serializer. That serializer is Foundation's pretty-printed JSON — two-space indent, `"key" : value` with a space before the colon, keys sorted by code point, no trailing newline — so a catalog written by anything else parses identically but differs on every line, and the next IDE build buries the one entry it actually added under thousands of lines of whitespace churn. `./xcstrings` rewrites catalogs in that exact serialization, and `--lint` reports any that have drifted. It deliberately touches formatting only: which keys exist, their values, comments, and extraction state are Xcode's and the translators', so a normalization pass can never add, drop, or edit an entry (it re-parses its own output and refuses to write if the content moved). Reproducing Foundation byte-for-byte needs one deviation: its `.sortedKeys` compares case-insensitively while Xcode sorts by code point, which shows up as soon as a catalog holds an auto-extracted capitalized literal next to a lowercase key. Keys are therefore sorted here and only leaf values go through JSONSerialization, which keeps string escaping identical. Verified by round-tripping two catalogs Xcode itself had rewritten (WhereUI's 4,200-line one included) to byte-identical output. --- AGENTS.md | 12 ++- Where/AGENTS.md | 10 +++ xcstrings | 197 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 217 insertions(+), 2 deletions(-) create mode 100755 xcstrings diff --git a/AGENTS.md b/AGENTS.md index b90764e2e..5823e9c40 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -47,8 +47,8 @@ Xcode project](#generating-the-xcode-project)). A fresh machine needs `./ide generating; plain `./ide` fails fast pointing at it. The executables in the repo root are the dev scripts — `ide`, `swiftformat`, -`sync-agents`, `profile`, `icons`, `flaky`, `simulator` — and each takes -`--help`. Reach for one rather than hand-rolling its job: `icons` and +`sync-agents`, `profile`, `icons`, `flaky`, `simulator`, `xcstrings` — and each +takes `--help`. Reach for one rather than hand-rolling its job: `icons` and `simulator` in particular own state that is easy to corrupt by hand (see [Managing app icons](#managing-app-icons) and [Selecting a simulator](#selecting-a-simulator--address-it-by-udid-not-name)). @@ -66,6 +66,14 @@ Run `./ide --no-open` after adding one. format the tree, or `./swiftformat --lint` to check only (as in CI). - The pre-commit hook (enabled by `./ide` via `core.hooksPath`) formats staged `*.swift` files in place and re-stages them. +- **String Catalogs are stored exactly as Xcode serializes them**, and + `./xcstrings` (`--lint` in CI) enforces it. Xcode rewrites a `.xcstrings` in + place during an *IDE* build whenever extraction finds a key the catalog + lacks — writing the entire file with its own serializer — so a catalog + written by anything else (a migration script's `json.dump`, a hand edit) + parses fine but turns the next build into thousands of lines of whitespace + churn around the one real entry. Write a catalog through Xcode, or normalize + it afterwards; the script only touches formatting, never content. ## Agent instructions sync diff --git a/Where/AGENTS.md b/Where/AGENTS.md index a9dec034a..bf59c192a 100644 --- a/Where/AGENTS.md +++ b/Where/AGENTS.md @@ -139,6 +139,16 @@ Add the key to the catalog as a **manual** entry first (so its symbol generates), then reference `.thatSymbol` — never ship English literals in SwiftUI `Text` or `errorDescription`, and never reintroduce a raw-key facade. +The catalogs also carry a few **auto-extracted** entries with no +`extractionState` and no value — `""`, `%lld`, an English literal from a +`#Preview`. Those are Xcode's, not ours: extraction picks up every string +literal that could be a key (`Marker("", …)`, `Text("\(count)")`), and an IDE +build re-adds any that's missing, so deleting one by hand just brings it back +with a full reserialization behind it. Remove the *source* literal if you want +the entry gone — interpolating an `Int` into `Text` is worth fixing anyway (it +skips `WhereFormat`'s number styling). Catalog files stay byte-identical to +Xcode's own serialization; see [Formatting](../AGENTS.md#formatting). + ## Dates & presentation - **A logical day is a `CalendarDay` (Y-M-D), not a `Date`.** It is the diff --git a/xcstrings b/xcstrings new file mode 100755 index 000000000..f6129437a --- /dev/null +++ b/xcstrings @@ -0,0 +1,197 @@ +#!/usr/bin/swift + +// xcstrings — rewrite every String Catalog in the tree the way Xcode itself +// serializes one, and (with --lint) check that they already are. +// +// Why this exists: Xcode rewrites a `.xcstrings` in place during an IDE build +// whenever string extraction finds something the catalog doesn't have yet, and +// it writes the whole file with its own serializer (Foundation's pretty-printed +// JSON: two-space indent, `"key" : value` with a space before the colon, keys +// sorted by code point, no trailing newline). A catalog written by anything else +// — a migration script's `json.dump`, a hand edit — parses fine but differs on +// every line, so the next build in Xcode lands thousands of lines of pure +// serialization noise on top of the one entry it actually added. Keeping the +// checked-in files byte-identical to Xcode's output keeps that diff honest. +// +// This only touches *formatting*. Catalog content — which keys exist, their +// values, comments, and extraction state — belongs to Xcode and the translators; +// normalizing never adds, drops, or edits an entry. See the Localization section +// in Where/AGENTS.md. + +import Foundation + +let usage = """ +Usage: ./xcstrings [options] [path ...] + +Rewrites String Catalogs in Xcode's own serialization (content untouched). +With no paths, walks the repository for every `.xcstrings`. + +Options: + --lint Report catalogs that aren't normalized; write nothing. Exits 1 if any differ. + -h, --help Show this help + +Examples: + ./xcstrings + ./xcstrings --lint + ./xcstrings Where/WhereUI/Sources/Resources/Localizable.xcstrings +""" + +// MARK: - Xcode's serializer + +/// Serializes a parsed catalog the way Xcode's String Catalog writer does. +/// +/// Foundation's `.prettyPrinted` output is the format, with one deviation that +/// matters: `JSONSerialization.WritingOptions.sortedKeys` compares keys +/// case-insensitively, while Xcode sorts them by code point — so a catalog with +/// an auto-extracted `"Log today here"` alongside `"appIcon.title"` orders the +/// capital first. Keys are sorted here and only leaf values are handed to +/// Foundation, which keeps string escaping byte-identical to Xcode's. +struct CatalogSerializer { + enum Failure: Error, CustomStringConvertible { + case unsupportedValue(Any) + + var description: String { + switch self { + case let .unsupportedValue(value): + "unsupported JSON value in catalog: \(type(of: value)) (\(value))" + } + } + } + + func data(from object: Any) throws -> Data { + var output = "" + try write(object, indent: 0, into: &output) + return Data(output.utf8) + } + + private func write(_ value: Any, indent: Int, into output: inout String) throws { + switch value { + case let dictionary as [String: Any]: + try write(dictionary: dictionary, indent: indent, into: &output) + case let array as [Any]: + try write(array: array, indent: indent, into: &output) + default: + output += try fragment(for: value) + } + } + + private func write(dictionary: [String: Any], indent: Int, into output: inout String) throws { + // Foundation renders an empty container as an open brace, a blank line, + // and the closing brace back at the container's own indent. + guard dictionary.isEmpty == false else { + output += "{\n\n\(pad(indent))}" + return + } + output += "{\n" + let keys = dictionary.keys.sorted { $0.utf8.lexicographicallyPrecedes($1.utf8) } + for (offset, key) in keys.enumerated() { + output += "\(pad(indent + 1))\(try fragment(for: key)) : " + try write(dictionary[key]!, indent: indent + 1, into: &output) + output += offset == keys.count - 1 ? "\n" : ",\n" + } + output += "\(pad(indent))}" + } + + private func write(array: [Any], indent: Int, into output: inout String) throws { + guard array.isEmpty == false else { + output += "[\n\n\(pad(indent))]" + return + } + output += "[\n" + for (offset, element) in array.enumerated() { + output += pad(indent + 1) + try write(element, indent: indent + 1, into: &output) + output += offset == array.count - 1 ? "\n" : ",\n" + } + output += "\(pad(indent))]" + } + + /// Renders a leaf through Foundation so escaping matches Xcode exactly: + /// serializing `[value]` and dropping the brackets is the shortest way to + /// reach the same encoder without reimplementing its escape rules. + private func fragment(for value: Any) throws -> String { + guard JSONSerialization.isValidJSONObject([value]) else { + throw Failure.unsupportedValue(value) + } + let data = try JSONSerialization.data(withJSONObject: [value], options: [.withoutEscapingSlashes]) + return String(decoding: data.dropFirst().dropLast(), as: UTF8.self) + } + + private func pad(_ indent: Int) -> String { + String(repeating: " ", count: indent) + } +} + +// MARK: - Command + +func normalized(_ url: URL) throws -> Data { + let original = try Data(contentsOf: url) + let object = try JSONSerialization.jsonObject(with: original, options: []) + let rewritten = try CatalogSerializer().data(from: object) + // A round-trip must preserve content exactly; anything else is a bug here + // rather than something to quietly write over a translator's work. + let reparsed = try JSONSerialization.jsonObject(with: rewritten, options: []) + guard NSDictionary(dictionary: object as? [String: Any] ?? [:]) + .isEqual(to: reparsed as? [String: Any] ?? [:]) + else { + throw CatalogSerializer.Failure.unsupportedValue(object) + } + return rewritten +} + +func catalogs(under root: URL) throws -> [URL] { + let skipped: Set = ["Derived", ".build", ".git", "build"] + var found: [URL] = [] + let enumerator = FileManager.default.enumerator( + at: root, + includingPropertiesForKeys: nil, + options: [.skipsHiddenFiles], + ) + while let url = enumerator?.nextObject() as? URL { + if url.hasDirectoryPath, skipped.contains(url.lastPathComponent) || url.pathExtension == "xcodeproj" { + enumerator?.skipDescendants() + continue + } + if url.pathExtension == "xcstrings" { found.append(url) } + } + return found.sorted { $0.path < $1.path } +} + +var lintOnly = false +var paths: [String] = [] +for argument in CommandLine.arguments.dropFirst() { + switch argument { + case "--lint": lintOnly = true + case "-h", "--help": print(usage); exit(0) + default: + guard argument.hasPrefix("-") == false else { + FileHandle.standardError.write(Data("error: unknown option '\(argument)' (see ./xcstrings --help)\n".utf8)) + exit(1) + } + paths.append(argument) + } +} + +let root = URL(fileURLWithPath: FileManager.default.currentDirectoryPath) +let targets = try paths.isEmpty ? catalogs(under: root) : paths.map { URL(fileURLWithPath: $0) } +var offenders: [String] = [] + +for url in targets { + let display = url.path.replacingOccurrences(of: root.path + "/", with: "") + let rewritten = try normalized(url) + guard try rewritten != Data(contentsOf: url) else { continue } + offenders.append(display) + if lintOnly { + print("not normalized: \(display)") + } else { + try rewritten.write(to: url) + print("normalized: \(display)") + } +} + +if offenders.isEmpty { + print("\(targets.count) catalog\(targets.count == 1 ? "" : "s") already match Xcode's serialization.") +} else if lintOnly { + FileHandle.standardError.write(Data("\(offenders.count) catalog(s) not normalized — run ./xcstrings\n".utf8)) + exit(1) +} From 214334c63803eb8ce2b9dd940c73cda18d777cc9 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Fri, 24 Jul 2026 18:24:12 -0700 Subject: [PATCH 2/4] Store the String Catalogs as Xcode writes them, and lint that in CI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Every catalog is now byte-identical to Xcode's own output, so an IDE build has nothing to rewrite and leaves the working tree clean. Building the Where app used to reserialize WhereUI's catalog into ~5,500 changed lines — noise that hides real changes in `git status` and is easy to commit by accident. The four catalogs adopted in #124 were written by that migration's script rather than by Xcode (`"key": value`, trailing newline); the other three were already in Xcode's style apart from the trailing newline. Two things had to be true, not just the formatting: - **Formatting** — all seven now round-trip through `./xcstrings` unchanged. - **Content** — the reason Xcode rewrote anything at all is that extraction found four keys the catalogs lacked: `""` (`Marker("", …)` in RecordedPointsMap), `%lld` (`Text("\(count)")` in RegionMapView and CalendarContentView), `Log today here` (a `#Preview` literal in IntentSnippets), and `App content` (a `#Preview` literal in LifecycleContainer). Xcode re-adds them on every build, so they're committed as the empty auto-extracted entries it writes. The source literals behind them are left alone here; they're noted in Where/AGENTS.md as the way to remove an entry for good. The entries were derived from the `.stringsdata` a clean `tuist build Where` produced, then cross-checked: the result is byte-identical to what Xcode wrote into WhereUI's and LifecycleKit's catalogs on its own. No key, value, comment, state, or `extractionState` changed anywhere — verified by comparing the parsed JSON against HEAD. CI lints catalogs in the existing format job (branch protection pins the check names, so this rides along rather than adding a job). --- .github/workflows/ci.yml | 7 + .../Sources/Resources/Localizable.xcstrings | 5 +- .../Sources/Resources/Localizable.xcstrings | 2 +- .../Sources/Resources/Localizable.xcstrings | 2 +- .../Sources/Resources/Localizable.xcstrings | 550 +- .../Resources/Localizable.xcstrings | 248 +- .../Sources/Resources/Localizable.xcstrings | 5483 +++++++++-------- .../Resources/Localizable.xcstrings | 72 +- 8 files changed, 3197 insertions(+), 3172 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 73cc63840..5509e6a40 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,13 @@ jobs: - uses: actions/checkout@v4 - uses: jdx/mise-action@v3 - run: ./swiftformat --lint + # Catalogs drift out of Xcode's serialization the moment one is written by + # anything but Xcode, and the cost lands on whoever next builds in the IDE + # (see "Formatting" in AGENTS.md). This rides along in the format job + # rather than a job of its own because branch protection pins the two + # check names. + - name: String Catalog lint + run: ./xcstrings --lint test: name: Build & Test (iOS) diff --git a/Shared/LifecycleKit/Sources/Resources/Localizable.xcstrings b/Shared/LifecycleKit/Sources/Resources/Localizable.xcstrings index c67990272..6a93d9136 100644 --- a/Shared/LifecycleKit/Sources/Resources/Localizable.xcstrings +++ b/Shared/LifecycleKit/Sources/Resources/Localizable.xcstrings @@ -1,6 +1,9 @@ { "sourceLanguage" : "en", "strings" : { + "App content" : { + + }, "failure.launch.retry" : { "extractionState" : "manual", "localizations" : { @@ -25,4 +28,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Where/RegionKit/Sources/Resources/Localizable.xcstrings b/Where/RegionKit/Sources/Resources/Localizable.xcstrings index 826da5c00..062c220ab 100644 --- a/Where/RegionKit/Sources/Resources/Localizable.xcstrings +++ b/Where/RegionKit/Sources/Resources/Localizable.xcstrings @@ -58,4 +58,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Where/WhereCore/Sources/Resources/Localizable.xcstrings b/Where/WhereCore/Sources/Resources/Localizable.xcstrings index 2d1818696..be757567b 100644 --- a/Where/WhereCore/Sources/Resources/Localizable.xcstrings +++ b/Where/WhereCore/Sources/Resources/Localizable.xcstrings @@ -137,4 +137,4 @@ } }, "version" : "1.0" -} +} \ No newline at end of file diff --git a/Where/WhereIntents/Sources/Resources/Localizable.xcstrings b/Where/WhereIntents/Sources/Resources/Localizable.xcstrings index 16879f671..8a8be3f34 100644 --- a/Where/WhereIntents/Sources/Resources/Localizable.xcstrings +++ b/Where/WhereIntents/Sources/Resources/Localizable.xcstrings @@ -1,366 +1,372 @@ { - "sourceLanguage": "en", - "strings": { - "%@": { - "comment": "A spoken dialog response for the \"Count days in a region\" intent. The argument is the region name, the second is the number of days, and the third is the year.", - "isCommentAutoGenerated": true - }, - "Backfill a range of days with the regions you were in.": { - "comment": "Description of the Log Trip intent.", - "isCommentAutoGenerated": true - }, - "Count Days in a Region": { - "comment": "Intent name for the \"Count Days in a Region\" action.", - "isCommentAutoGenerated": true - }, - "Date": { - "comment": "Label for the date parameter in the RegionOnDateIntent.", - "isCommentAutoGenerated": true - }, - "Day": { - "comment": "The name of the parameter for the day of the week.", - "isCommentAutoGenerated": true - }, - "Days in a Region": { - "comment": "Title of the Days in a Region snippet.", - "isCommentAutoGenerated": true - }, - "End Date": { - "comment": "Label for the end date parameter in the Log a Trip intent.", - "isCommentAutoGenerated": true - }, - "Find Regions on a Date": { - "comment": "Title of the intent.", - "isCommentAutoGenerated": true - }, - "Find out how many days you've spent in a region so far this year.": { - "comment": "Description of the \"Count Days in a Region\" intent.", - "isCommentAutoGenerated": true - }, - "Get an on-device summary of where you've been over a recent window.": { - "comment": "Description of the intent to get an on-device summary of where the user has been over a recent window.", - "isCommentAutoGenerated": true - }, - "Last 24 Hours": { - "comment": "Display name for the \"Last 24 Hours\" option in the Siri-resolved menu.", - "isCommentAutoGenerated": true - }, - "Log a Day's Regions": { - "comment": "Intent title.", - "isCommentAutoGenerated": true - }, - "Log a Trip": {}, - "Look up which regions a particular day counted for.": { - "comment": "Description of the \"Find Regions on a Date\" intent.", - "isCommentAutoGenerated": true - }, - "Past Month": { - "comment": "Display name for the past month option in the recent-activity summary intent.", - "isCommentAutoGenerated": true - }, - "Past Week": { - "comment": "Displayed title for the \"Past Week\" option in the Siri-resolved menu.", - "isCommentAutoGenerated": true - }, - "Record which regions you were in on a day.": { - "comment": "Description of the \"Log a Day's Regions\" intent.", - "isCommentAutoGenerated": true - }, - "Region": { - "comment": "The parameter name for the region parameter in the DaysInRegionIntent.", - "isCommentAutoGenerated": true - }, - "Regions": { - "comment": "The parameter title for the regions parameter in the Log Day intent.", - "isCommentAutoGenerated": true - }, - "See which regions today counts for so far.": { - "comment": "Description of the \"Show Today's Regions\" intent.", - "isCommentAutoGenerated": true - }, - "Show Today's Regions": { - "comment": "Title of the \"Where am I today?\" intent.", - "isCommentAutoGenerated": true - }, - "Start Date": {}, - "Summarize Recent Activity": { - "comment": "Intent to summarize recent activity.", - "isCommentAutoGenerated": true - }, - "Time Range": {}, - "Year": { - "comment": "Label for the year parameter in the \"Count Days in a Region\" intent.", - "isCommentAutoGenerated": true - }, - "Year So Far": { - "comment": "Display name for the \"Year So Far\" option in the", - "isCommentAutoGenerated": true - }, - "audit.note.siri": { - "comment": "Note stored on a manual day entry made through an intent.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logged with Siri" + "sourceLanguage" : "en", + "strings" : { + "%@" : { + "comment" : "A spoken dialog response for the \"Count days in a region\" intent. The argument is the region name, the second is the number of days, and the third is the year.", + "isCommentAutoGenerated" : true + }, + "Backfill a range of days with the regions you were in." : { + "comment" : "Description of the Log Trip intent.", + "isCommentAutoGenerated" : true + }, + "Count Days in a Region" : { + "comment" : "Intent name for the \"Count Days in a Region\" action.", + "isCommentAutoGenerated" : true + }, + "Date" : { + "comment" : "Label for the date parameter in the RegionOnDateIntent.", + "isCommentAutoGenerated" : true + }, + "Day" : { + "comment" : "The name of the parameter for the day of the week.", + "isCommentAutoGenerated" : true + }, + "Days in a Region" : { + "comment" : "Title of the Days in a Region snippet.", + "isCommentAutoGenerated" : true + }, + "End Date" : { + "comment" : "Label for the end date parameter in the Log a Trip intent.", + "isCommentAutoGenerated" : true + }, + "Find Regions on a Date" : { + "comment" : "Title of the intent.", + "isCommentAutoGenerated" : true + }, + "Find out how many days you've spent in a region so far this year." : { + "comment" : "Description of the \"Count Days in a Region\" intent.", + "isCommentAutoGenerated" : true + }, + "Get an on-device summary of where you've been over a recent window." : { + "comment" : "Description of the intent to get an on-device summary of where the user has been over a recent window.", + "isCommentAutoGenerated" : true + }, + "Last 24 Hours" : { + "comment" : "Display name for the \"Last 24 Hours\" option in the Siri-resolved menu.", + "isCommentAutoGenerated" : true + }, + "Log a Day's Regions" : { + "comment" : "Intent title.", + "isCommentAutoGenerated" : true + }, + "Log a Trip" : { + + }, + "Look up which regions a particular day counted for." : { + "comment" : "Description of the \"Find Regions on a Date\" intent.", + "isCommentAutoGenerated" : true + }, + "Past Month" : { + "comment" : "Display name for the past month option in the recent-activity summary intent.", + "isCommentAutoGenerated" : true + }, + "Past Week" : { + "comment" : "Displayed title for the \"Past Week\" option in the Siri-resolved menu.", + "isCommentAutoGenerated" : true + }, + "Record which regions you were in on a day." : { + "comment" : "Description of the \"Log a Day's Regions\" intent.", + "isCommentAutoGenerated" : true + }, + "Region" : { + "comment" : "The parameter name for the region parameter in the DaysInRegionIntent.", + "isCommentAutoGenerated" : true + }, + "Regions" : { + "comment" : "The parameter title for the regions parameter in the Log Day intent.", + "isCommentAutoGenerated" : true + }, + "See which regions today counts for so far." : { + "comment" : "Description of the \"Show Today's Regions\" intent.", + "isCommentAutoGenerated" : true + }, + "Show Today's Regions" : { + "comment" : "Title of the \"Where am I today?\" intent.", + "isCommentAutoGenerated" : true + }, + "Start Date" : { + + }, + "Summarize Recent Activity" : { + "comment" : "Intent to summarize recent activity.", + "isCommentAutoGenerated" : true + }, + "Time Range" : { + + }, + "Year" : { + "comment" : "Label for the year parameter in the \"Count Days in a Region\" intent.", + "isCommentAutoGenerated" : true + }, + "Year So Far" : { + "comment" : "Display name for the \"Year So Far\" option in the", + "isCommentAutoGenerated" : true + }, + "audit.note.siri" : { + "comment" : "Note stored on a manual day entry made through an intent.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logged with Siri" } } } }, - "dialog.daysInRegion.none": { - "comment": "Spoken result when a region has no logged days this year. %1$@ region name, %2$@ year.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "You have no days logged in %1$@ so far in %2$@." + "dialog.daysInRegion.none" : { + "comment" : "Spoken result when a region has no logged days this year. %1$@ region name, %2$@ year.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You have no days logged in %1$@ so far in %2$@." } } } }, - "dialog.daysInRegion.one": { - "comment": "Spoken result for exactly one day in a region. %1$@ region name, %2$@ year.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "You have 1 day in %1$@ so far in %2$@." + "dialog.daysInRegion.one" : { + "comment" : "Spoken result for exactly one day in a region. %1$@ region name, %2$@ year.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You have 1 day in %1$@ so far in %2$@." } } } }, - "dialog.daysInRegion.other": { - "comment": "Spoken result for a day count in a region. %1$lld count, %2$@ region name, %3$@ year.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "You have %1$lld days in %2$@ so far in %3$@." + "dialog.daysInRegion.other" : { + "comment" : "Spoken result for a day count in a region. %1$lld count, %2$@ region name, %3$@ year.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "You have %1$lld days in %2$@ so far in %3$@." } } } }, - "dialog.logged.chooseRegions": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tell me which regions to log." + "dialog.logged.chooseRegions" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tell me which regions to log." } } } }, - "dialog.logged.day": { - "comment": "Confirmation after logging a day. %1$@ region list, %2$@ date.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logged %1$@ for %2$@." + "dialog.logged.day" : { + "comment" : "Confirmation after logging a day. %1$@ region list, %2$@ date.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logged %1$@ for %2$@." } } } }, - "dialog.logged.emptyRange": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "That date range doesn't include any days." + "dialog.logged.emptyRange" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "That date range doesn't include any days." } } } }, - "dialog.logged.trip.one": { - "comment": "Confirmation after backfilling exactly one day. %1$@ region list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logged %1$@ for 1 day." + "dialog.logged.trip.one" : { + "comment" : "Confirmation after backfilling exactly one day. %1$@ region list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logged %1$@ for 1 day." } } } }, - "dialog.logged.trip.other": { - "comment": "Confirmation after backfilling a trip. %1$@ region list, %2$lld day count.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logged %1$@ for %2$lld days." + "dialog.logged.trip.other" : { + "comment" : "Confirmation after backfilling a trip. %1$@ region list, %2$lld day count.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logged %1$@ for %2$lld days." } } } }, - "dialog.recentActivity.empty": { - "comment": "Spoken result when a window has no tracked activity. %1$@ window phrase.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing was tracked in %1$@." + "dialog.recentActivity.empty" : { + "comment" : "Spoken result when a window has no tracked activity. %1$@ window phrase.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing was tracked in %1$@." } } } }, - "dialog.recentActivity.unavailable.appleIntelligenceNotEnabled": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Turn on Apple Intelligence in Settings to summarize where you've been." + "dialog.recentActivity.unavailable.appleIntelligenceNotEnabled" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Turn on Apple Intelligence in Settings to summarize where you've been." } } } }, - "dialog.recentActivity.unavailable.deviceNotEligible": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This device doesn't support on-device summaries." + "dialog.recentActivity.unavailable.deviceNotEligible" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This device doesn't support on-device summaries." } } } }, - "dialog.recentActivity.unavailable.modelNotReady": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The on-device model is still getting ready. Try again shortly." + "dialog.recentActivity.unavailable.modelNotReady" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The on-device model is still getting ready. Try again shortly." } } } }, - "dialog.recentActivity.unavailable.unknown": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "On-device summaries aren't available right now." + "dialog.recentActivity.unavailable.unknown" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "On-device summaries aren't available right now." } } } }, - "dialog.regionOnDate.none": { - "comment": "Spoken result when a date has nothing logged. %1$@ formatted date.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing is logged for %1$@." + "dialog.regionOnDate.none" : { + "comment" : "Spoken result when a date has nothing logged. %1$@ formatted date.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing is logged for %1$@." } } } }, - "dialog.regionOnDate.some": { - "comment": "Spoken result naming the regions a date counted for. %1$@ date, %2$@ region list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "On %1$@ you were in %2$@." + "dialog.regionOnDate.some" : { + "comment" : "Spoken result naming the regions a date counted for. %1$@ date, %2$@ region list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "On %1$@ you were in %2$@." } } } }, - "dialog.today.none": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing is logged for today yet." + "dialog.today.none" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing is logged for today yet." } } } }, - "dialog.today.some": { - "comment": "Spoken result naming today's regions. %1$@ region list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Today you've been in %1$@." + "dialog.today.some" : { + "comment" : "Spoken result naming today's regions. %1$@ region list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Today you've been in %1$@." } } } }, - "dialog.window.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "the last 24 hours" + "dialog.window.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "the last 24 hours" } } } }, - "dialog.window.month": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "the past month" + "dialog.window.month" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "the past month" } } } }, - "dialog.window.week": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "the past week" + "dialog.window.week" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "the past week" } } } }, - "dialog.window.yearToDate": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "the year so far" + "dialog.window.yearToDate" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "the year so far" } } } }, - "snippet.logTodayHere": { - "comment": "Button in the day-count snippet that logs today for the shown region.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Log today here" + "snippet.logTodayHere" : { + "comment" : "Button in the day-count snippet that logs today for the shown region.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Log today here" } } } } }, - "version": "1.1" -} + "version" : "1.1" +} \ No newline at end of file diff --git a/Where/WhereShareExtension/Resources/Localizable.xcstrings b/Where/WhereShareExtension/Resources/Localizable.xcstrings index b4ec91b81..553e0edac 100644 --- a/Where/WhereShareExtension/Resources/Localizable.xcstrings +++ b/Where/WhereShareExtension/Resources/Localizable.xcstrings @@ -1,186 +1,186 @@ { - "sourceLanguage": "en", - "strings": { - "share.attachment.fallbackName": { - "comment": "Stand-in name for a shared attachment the provider gave no filename for.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Attachment" + "sourceLanguage" : "en", + "strings" : { + "share.attachment.fallbackName" : { + "comment" : "Stand-in name for a shared attachment the provider gave no filename for.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attachment" } } } }, - "share.attachment.header": { - "comment": "Section header above the shared attachment summary (one item).", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Attachment" + "share.attachment.header" : { + "comment" : "Section header above the shared attachment summary (one item).", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attachment" } } } }, - "share.attachment.headerPlural": { - "comment": "Section header above the shared attachments (more than one item).", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Attachments" + "share.attachment.headerPlural" : { + "comment" : "Section header above the shared attachments (more than one item).", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attachments" } } } }, - "share.attachment.none": { - "comment": "Shown when the share carried nothing loadable, so only metadata is saved.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No attachment — this will save a note only." + "share.attachment.none" : { + "comment" : "Shown when the share carried nothing loadable, so only metadata is saved.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No attachment — this will save a note only." } } } }, - "share.cancel": { - "comment": "Cancel button dismissing the share sheet without saving.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancel" + "share.cancel" : { + "comment" : "Cancel button dismissing the share sheet without saving.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancel" } } } }, - "share.form.date": { - "comment": "Date picker label for when the evidence was captured.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Date" + "share.form.date" : { + "comment" : "Date picker label for when the evidence was captured.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Date" } } } }, - "share.form.kind": { - "comment": "Picker label for the evidence kind.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Kind" + "share.form.kind" : { + "comment" : "Picker label for the evidence kind.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kind" } } } }, - "share.form.noteHeader": { - "comment": "Section header above the optional note field.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Note" + "share.form.noteHeader" : { + "comment" : "Section header above the optional note field.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Note" } } } }, - "share.form.notePlaceholder": { - "comment": "Placeholder for the optional note text field.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add a note (optional)" + "share.form.notePlaceholder" : { + "comment" : "Placeholder for the optional note text field.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add a note (optional)" } } } }, - "share.form.otherLabel": { - "comment": "Placeholder for the free-text label shown when the kind is Other.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Label" + "share.form.otherLabel" : { + "comment" : "Placeholder for the free-text label shown when the kind is Other.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Label" } } } }, - "share.loading": { - "comment": "Progress label while the shared attachment is being read.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Preparing…" + "share.loading" : { + "comment" : "Progress label while the shared attachment is being read.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Preparing…" } } } }, - "share.ok": { - "comment": "Dismiss button on the save-failure alert.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "OK" + "share.ok" : { + "comment" : "Dismiss button on the save-failure alert.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" } } } }, - "share.save": { - "comment": "Save button persisting the shared evidence.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Save" + "share.save" : { + "comment" : "Save button persisting the shared evidence.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Save" } } } }, - "share.saveError.title": { - "comment": "Title of the alert shown when saving the shared evidence fails.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't save" + "share.saveError.title" : { + "comment" : "Title of the alert shown when saving the shared evidence fails.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't save" } } } }, - "share.title": { - "comment": "Navigation title of the share compose sheet.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Save to Where" + "share.title" : { + "comment" : "Navigation title of the share compose sheet.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Save to Where" } } } } }, - "version": "1.0" -} + "version" : "1.0" +} \ No newline at end of file diff --git a/Where/WhereUI/Sources/Resources/Localizable.xcstrings b/Where/WhereUI/Sources/Resources/Localizable.xcstrings index 61058231a..55786dd36 100644 --- a/Where/WhereUI/Sources/Resources/Localizable.xcstrings +++ b/Where/WhereUI/Sources/Resources/Localizable.xcstrings @@ -1,267 +1,276 @@ { - "sourceLanguage": "en", - "strings": { - "appIcon.appearance.dark": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Dark" + "sourceLanguage" : "en", + "strings" : { + "" : { + + }, + "%lld" : { + + }, + "Log today here" : { + + }, + "appIcon.appearance.dark" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Dark" } } } }, - "appIcon.appearance.hint": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tap the icon to preview light and dark." + "appIcon.appearance.hint" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tap the icon to preview light and dark." } } } }, - "appIcon.appearance.light": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Light" + "appIcon.appearance.light" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Light" } } } }, - "appIcon.current": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Current" + "appIcon.current" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Current" } } } }, - "appIcon.error.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't Change Icon" + "appIcon.error.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't Change Icon" } } } }, - "appIcon.set": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Set as App Icon" + "appIcon.set" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Set as App Icon" } } } }, - "appIcon.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "App Icon" + "appIcon.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "App Icon" } } } }, - "audit.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Entry record" + "audit.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entry record" } } } }, - "audit.location": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Made at" + "audit.location" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Made at" } } } }, - "audit.location.unavailable": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Not captured" + "audit.location.unavailable" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Not captured" } } } }, - "audit.note": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Note" + "audit.note" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Note" } } } }, - "audit.recordedAt": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Recorded" + "audit.recordedAt" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recorded" } } } }, - "calendar.day.accessibility": { - "comment": "Accessibility label for a calendar day, including the day of the week and the names of the regions that day.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%1$@, %2$@" + "calendar.day.accessibility" : { + "comment" : "Accessibility label for a calendar day, including the day of the week and the names of the regions that day.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@, %2$@" } } } }, - "calendar.day.empty.accessibility": { - "comment": "Accessibility label for a calendar day when no regions have been logged.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%@, nothing logged" + "calendar.day.empty.accessibility" : { + "comment" : "Accessibility label for a calendar day when no regions have been logged.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%@, nothing logged" } } } }, - "calendar.day.hasEvidence.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%@, has evidence" + "calendar.day.hasEvidence.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%@, has evidence" } } } }, - "calendar.day.needsAttention.accessibility": { - "comment": "Accessibility label for a calendar day that needs attention.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%@, needs a location" + "calendar.day.needsAttention.accessibility" : { + "comment" : "Accessibility label for a calendar day that needs attention.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%@, needs a location" } } } }, - "calendar.region.title": { - "comment": "Title for the calendar when it's focused on a single region, e.g. \"California · 2026\".", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%1$@ · %2$@" + "calendar.region.title" : { + "comment" : "Title for the calendar when it's focused on a single region, e.g. \"California · 2026\".", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@ · %2$@" } } } }, - "calendar.title": { - "comment": "Title of the calendar screen, including the year.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Calendar · %@" + "calendar.title" : { + "comment" : "Title of the calendar screen, including the year.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Calendar · %@" } } } }, - "calendar.unavailable.description": { - "comment": "Description of the calendar when the user's year data isn't available.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Your year data isn't available right now." + "calendar.unavailable.description" : { + "comment" : "Description of the calendar when the user's year data isn't available.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Your year data isn't available right now." } } } }, - "common.cancel": { - "comment": "Cancel button text.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Cancel" + "common.cancel" : { + "comment" : "Cancel button text.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Cancel" } } } }, - "common.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "day" + "common.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "day" } } } }, - "common.dayCount": { - "extractionState": "manual", - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld day" + "common.dayCount" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld day" } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%lld days" + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld days" } } } @@ -269,973 +278,973 @@ } } }, - "common.days": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "days" + "common.days" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "days" } } } }, - "common.done": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Done" + "common.done" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Done" } } } }, - "common.loadError.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't load your year" + "common.loadError.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't load your year" } } } }, - "common.ok": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "OK" + "common.ok" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "OK" } } } }, - "common.regionDays.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%1$@: %2$@" + "common.regionDays.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@: %2$@" } } } }, - "common.save": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Save" + "common.save" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Save" } } } }, - "developer.button.label": { - "comment": "Accessibility label for the floating developer button.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Developer tools" + "developer.button.label" : { + "comment" : "Accessibility label for the floating developer button.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Developer tools" } } } }, - "developer.close": { - "comment": "Accessibility label for closing the developer panel.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Close" + "developer.close" : { + "comment" : "Accessibility label for closing the developer panel.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Close" } } } }, - "developer.collapse": { - "comment": "Accessibility label for shrinking the developer panel back to a floating window.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Exit full screen" + "developer.collapse" : { + "comment" : "Accessibility label for shrinking the developer panel back to a floating window.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exit full screen" } } } }, - "developer.dragHandle": { - "comment": "Accessibility label for the handle that drags the floating developer window.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Move developer window" + "developer.dragHandle" : { + "comment" : "Accessibility label for the handle that drags the floating developer window.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Move developer window" } } } }, - "developer.expand": { - "comment": "Accessibility label for growing the developer panel to full screen.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Enter full screen" + "developer.expand" : { + "comment" : "Accessibility label for growing the developer panel to full screen.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Enter full screen" } } } }, - "developer.footer": { - "comment": "Footer for the developer tools list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "On-device logs and data tools. Debug builds only." + "developer.footer" : { + "comment" : "Footer for the developer tools list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "On-device logs and data tools. Debug builds only." } } } }, - "developer.inspectorLink": { - "comment": "Label for the navigation link that opens the SwiftData inspector.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "SwiftData Inspector" + "developer.inspectorLink" : { + "comment" : "Label for the navigation link that opens the SwiftData inspector.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "SwiftData Inspector" } } } }, - "developer.inspectorTitle": { - "comment": "Navigation title for the SwiftData inspector screen.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "SwiftData" + "developer.inspectorTitle" : { + "comment" : "Navigation title for the SwiftData inspector screen.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "SwiftData" } } } }, - "developer.logViewMode": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Log View Mode" + "developer.logViewMode" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Log View Mode" } } } }, - "developer.logViewMode.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Reveal an inspect badge on tagged views to open their recent logs." + "developer.logViewMode.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Reveal an inspect badge on tagged views to open their recent logs." } } } }, - "developer.logsLink": { - "comment": "Label for the button that opens the logs screen.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logs" + "developer.logsLink" : { + "comment" : "Label for the button that opens the logs screen.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logs" } } } }, - "developer.logsTitle": { - "comment": "Title of the screen that shows the user's logs.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logs" + "developer.logsTitle" : { + "comment" : "Title of the screen that shows the user's logs.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logs" } } } }, - "developer.openSpansLink": { - "comment": "Label for a button that opens the developer's spans.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Open spans" + "developer.openSpansLink" : { + "comment" : "Label for a button that opens the developer's spans.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Open spans" } } } }, - "developer.regionMapLink": { - "comment": "Label for the navigation link that opens the region map.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Region map" + "developer.regionMapLink" : { + "comment" : "Label for the navigation link that opens the region map.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Region map" } } } }, - "developer.resizeHandle": { - "comment": "Accessibility label for the grip that resizes the floating developer window.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Resize developer window" + "developer.resizeHandle" : { + "comment" : "Accessibility label for the grip that resizes the floating developer window.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resize developer window" } } } }, - "developer.title": { - "comment": "Navigation title of the developer tools list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Developer" + "developer.title" : { + "comment" : "Navigation title of the developer tools list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Developer" } } } }, - "evidence.add": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Add evidence" + "evidence.add" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Add evidence" } } } }, - "evidence.detail.noAttachment": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No attachment" + "evidence.detail.noAttachment" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No attachment" } } } }, - "evidence.detail.noPreview.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "This attachment can't be previewed here." + "evidence.detail.noPreview.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "This attachment can't be previewed here." } } } }, - "evidence.detail.noPreview.title": { - "comment": "Title of an alert when an evidence doesn't have a preview.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No preview" + "evidence.detail.noPreview.title" : { + "comment" : "Title of an alert when an evidence doesn't have a preview.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No preview" } } } }, - "evidence.detail.noteHeader": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Note" + "evidence.detail.noteHeader" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Note" } } } }, - "evidence.detail.previewFailed": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't load this attachment." + "evidence.detail.previewFailed" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't load this attachment." } } } }, - "evidence.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Attach a boarding pass, receipt, or screenshot to back up where you were. Add one here, or share it into Where from another app." + "evidence.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Attach a boarding pass, receipt, or screenshot to back up where you were. Add one here, or share it into Where from another app." } } } }, - "evidence.empty.title": { - "comment": "Title of the empty state when there is no evidence.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No evidence yet" + "evidence.empty.title" : { + "comment" : "Title of the empty state when there is no evidence.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No evidence yet" } } } }, - "evidence.failed.title": { - "comment": "Title of an alert when loading evidence fails.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't load evidence" + "evidence.failed.title" : { + "comment" : "Title of an alert when loading evidence fails.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't load evidence" } } } }, - "evidence.form.attachmentHeader": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Attachment" + "evidence.form.attachmentHeader" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Attachment" } } } }, - "evidence.form.chooseFile": { - "comment": "Label for choosing a file from the file picker in the evidence form.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Choose file" + "evidence.form.chooseFile" : { + "comment" : "Label for choosing a file from the file picker in the evidence form.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Choose file" } } } }, - "evidence.form.choosePhoto": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Choose photo" + "evidence.form.choosePhoto" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Choose photo" } } } }, - "evidence.form.date": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Date" + "evidence.form.date" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Date" } } } }, - "evidence.form.kind": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Kind" + "evidence.form.kind" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Kind" } } } }, - "evidence.form.note": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Note" + "evidence.form.note" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Note" } } } }, - "evidence.form.notePlaceholder": { - "comment": "Placeholder text for the note field in the evidence form.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Add a note (optional)" + "evidence.form.notePlaceholder" : { + "comment" : "Placeholder text for the note field in the evidence form.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Add a note (optional)" } } } }, - "evidence.form.otherLabel": { - "comment": "Label for the \"Other\" field in the evidence form.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Label" + "evidence.form.otherLabel" : { + "comment" : "Label for the \"Other\" field in the evidence form.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Label" } } } }, - "evidence.form.remove": { - "comment": "Label for removing an attached file or photo.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Remove attachment" + "evidence.form.remove" : { + "comment" : "Label for removing an attached file or photo.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Remove attachment" } } } }, - "evidence.form.save": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Save" + "evidence.form.save" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Save" } } } }, - "evidence.form.saveError.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't save evidence" + "evidence.form.saveError.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't save evidence" } } } }, - "evidence.kind.boardingPass": { - "comment": "\"Boarding pass\" is a generic term for a travel document that shows a passenger's name, destination, and departure/arrival times.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Boarding pass" + "evidence.kind.boardingPass" : { + "comment" : "\"Boarding pass\" is a generic term for a travel document that shows a passenger's name, destination, and departure/arrival times.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Boarding pass" } } } }, - "evidence.kind.carRental": { - "comment": "The display name for a \"car rental\" evidence kind.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Car rental" + "evidence.kind.carRental" : { + "comment" : "The display name for a \"car rental\" evidence kind.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Car rental" } } } }, - "evidence.kind.document": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Document" + "evidence.kind.document" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Document" } } } }, - "evidence.kind.email": { - "comment": "\"Email\" is a generic term for an", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Email" + "evidence.kind.email" : { + "comment" : "\"Email\" is a generic term for an", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Email" } } } }, - "evidence.kind.hotelReceipt": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Hotel receipt" + "evidence.kind.hotelReceipt" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Hotel receipt" } } } }, - "evidence.kind.other": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Other" + "evidence.kind.other" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Other" } } } }, - "evidence.kind.photo": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Photo" + "evidence.kind.photo" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Photo" } } } }, - "evidence.kind.planeTicket": { - "comment": "\"Plane ticket\"", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Plane ticket" + "evidence.kind.planeTicket" : { + "comment" : "\"Plane ticket\"", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Plane ticket" } } } }, - "evidence.kind.rideshare": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Rideshare" + "evidence.kind.rideshare" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Rideshare" } } } }, - "evidence.list.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Evidence · %@" + "evidence.list.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Evidence · %@" } } } }, - "evidence.row.accessibility": { - "comment": "Accessibility summary for a single evidence row: its kind and captured date, e.g. \"Plane ticket, March 4, 2026\".", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%1$@, %2$@" + "evidence.row.accessibility" : { + "comment" : "Accessibility summary for a single evidence row: its kind and captured date, e.g. \"Plane ticket, March 4, 2026\".", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@, %2$@" } } } }, - "launch.accessibilityLabel": { - "comment": "Spoken by VoiceOver while the launch splash is on screen (the icon and radar animation are decorative and hidden from accessibility).", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Loading" + "launch.accessibilityLabel" : { + "comment" : "Spoken by VoiceOver while the launch splash is on screen (the icon and radar animation are decorative and hidden from accessibility).", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Loading" } } } }, - "launch.caption.subtitle": { - "comment": "Subtitle of the splash's slow-launch caption.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "This only takes a moment." + "launch.caption.subtitle" : { + "comment" : "Subtitle of the splash's slow-launch caption.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "This only takes a moment." } } } }, - "launch.caption.title": { - "comment": "Title of the splash's slow-launch caption; deliberately launch-neutral (a migration, a first install's store creation, or plain slowness).", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Getting things ready…" + "launch.caption.title" : { + "comment" : "Title of the splash's slow-launch caption; deliberately launch-neutral (a migration, a first install's store creation, or plain slowness).", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Getting things ready…" } } } }, - "locations.elsewhere.subtitle": { - "comment": "Subtitle on the Locations tab's Elsewhere entry card: region count.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "^[%lld region](inflect: true)" + "locations.elsewhere.subtitle" : { + "comment" : "Subtitle on the Locations tab's Elsewhere entry card: region count.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "^[%lld region](inflect: true)" } } } }, - "loggedDays.add": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Log a day" + "loggedDays.add" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Log a day" } } } }, - "loggedDays.delete": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Delete entry" + "loggedDays.delete" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Delete entry" } } } }, - "loggedDays.delete.footer": { - "comment": "Explanation of what deleting a logged day does.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Removes this manual entry and restores the day's GPS-detected location." + "loggedDays.delete.footer" : { + "comment" : "Explanation of what deleting a logged day does.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Removes this manual entry and restores the day's GPS-detected location." } } } }, - "loggedDays.deleteError.title": { - "comment": "Title of an alert when a logged-day deletion fails.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't delete entry" + "loggedDays.deleteError.title" : { + "comment" : "Title of an alert when a logged-day deletion fails.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't delete entry" } } } }, - "loggedDays.edit.date": { - "comment": "Label for the date row in the logged-day editor.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Day" + "loggedDays.edit.date" : { + "comment" : "Label for the date row in the logged-day editor.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Day" } } } }, - "loggedDays.edit.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Edit day" + "loggedDays.edit.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Edit day" } } } }, - "loggedDays.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Backfill a trip the GPS missed, or correct a day by hand — your manual entries for this year show up here." + "loggedDays.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Backfill a trip the GPS missed, or correct a day by hand — your manual entries for this year show up here." } } } }, - "loggedDays.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No logged days" + "loggedDays.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No logged days" } } } }, - "loggedDays.failed.title": { - "comment": "Title of the alert when loading logged days fails.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't load logged days" + "loggedDays.failed.title" : { + "comment" : "Title of the alert when loading logged days fails.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't load logged days" } } } }, - "loggedDays.filter.all": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "All" + "loggedDays.filter.all" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "All" } } } }, - "loggedDays.filter.label": { - "comment": "Accessibility label for the Logged/Overridden/All segmented filter.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Filter" + "loggedDays.filter.label" : { + "comment" : "Accessibility label for the Logged/Overridden/All segmented filter.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Filter" } } } }, - "loggedDays.kind.logged": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Logged" + "loggedDays.kind.logged" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Logged" } } } }, - "loggedDays.kind.overridden": { - "comment": "Label for a logged-day row that's been manually overridden.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Overridden" + "loggedDays.kind.overridden" : { + "comment" : "Label for a logged-day row that's been manually overridden.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Overridden" } } } }, - "loggedDays.noMatches.description": { - "comment": "Description of a message that appears when there are no logged days that match the current filter.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No days match this filter." + "loggedDays.noMatches.description" : { + "comment" : "Description of a message that appears when there are no logged days that match the current filter.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No days match this filter." } } } }, - "loggedDays.noMatches.title": { - "comment": "Title of a screen that shows when there are no logged days that match the filter.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No matching days" + "loggedDays.noMatches.title" : { + "comment" : "Title of a screen that shows when there are no logged days that match the filter.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No matching days" } } } }, - "loggedDays.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Logged Days · %@" + "loggedDays.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Logged Days · %@" } } } }, - "manual.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Day" + "manual.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Day" } } } }, - "manual.entry.pickerLabel": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Entry" + "manual.entry.pickerLabel" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Entry" } } } }, - "manual.from": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "From" + "manual.from" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "From" } } } }, - "manual.mode.range": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Date range" + "manual.mode.range" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Date range" } } } }, - "manual.mode.singleDay": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Single day" + "manual.mode.singleDay" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Single day" } } } }, - "manual.note.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Saved with this entry for auditing — explain why you made this change." + "manual.note.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saved with this entry for auditing — explain why you made this change." } } } }, - "manual.note.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reason" + "manual.note.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reason" } } } }, - "manual.note.placeholder": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Add a note (optional)" + "manual.note.placeholder" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add a note (optional)" } } } }, - "manual.range.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "Backfilling %lld day." + "manual.range.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "Backfilling %lld day." } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "Backfilling %lld days." + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "Backfilling %lld days." } } } @@ -1243,444 +1252,444 @@ } } }, - "manual.regions.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Saving replaces any manual regions you previously set for those days." + "manual.regions.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Saving replaces any manual regions you previously set for those days." } } } }, - "manual.regions.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Regions" + "manual.regions.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Regions" } } } }, - "manual.save": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Save" + "manual.save" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Save" } } } }, - "manual.saveError.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't save that day" + "manual.saveError.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't save that day" } } } }, - "manual.saving.status": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Capturing location…" + "manual.saving.status" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Capturing location…" } } } }, - "manual.singleDay.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Time travel: tell Where where you really were." + "manual.singleDay.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Time travel: tell Where where you really were." } } } }, - "manual.through": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Through" + "manual.through" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Through" } } } }, - "manual.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Log a Day" + "manual.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Log a Day" } } } }, - "missing.banner.accessibilityHint": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Opens the list of days that still need logging." + "missing.banner.accessibilityHint" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Opens the list of days that still need logging." } } } }, - "missing.banner.compact.one": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "1 day needs a location" + "missing.banner.compact.one" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 day needs a location" } } } }, - "missing.banner.compact.other": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%lld days need a location" + "missing.banner.compact.other" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld days need a location" } } } }, - "missingDays.done": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Done" + "missingDays.done" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Done" } } } }, - "missingDays.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Every day this year has something logged." + "missingDays.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Every day this year has something logged." } } } }, - "missingDays.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "All caught up" + "missingDays.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All caught up" } } } }, - "missingDays.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tap a stretch to record where you were. Today is included until something logs it." + "missingDays.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tap a stretch to record where you were. Today is included until something logs it." } } } }, - "missingDays.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Days to backfill" + "missingDays.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Days to backfill" } } } }, - "missingDays.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Missing days" + "missingDays.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Missing days" } } } }, - "onboarding.automatic.description": { - "comment": "Description of the automatic location logging feature in the onboarding flow.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "With background location, Where quietly notes the regions you pass through. You can always add or correct days by hand." + "onboarding.automatic.description" : { + "comment" : "Description of the automatic location logging feature in the onboarding flow.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "With background location, Where quietly notes the regions you pass through. You can always add or correct days by hand." } } } }, - "onboarding.automatic.title": { - "comment": "Title of the first onboarding screen, describing how Where automatically logs your location.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "It logs itself" + "onboarding.automatic.title" : { + "comment" : "Title of the first onboarding screen, describing how Where automatically logs your location.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "It logs itself" } } } }, - "onboarding.back": { - "comment": "Back button label in the onboarding flow.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Back" + "onboarding.back" : { + "comment" : "Back button label in the onboarding flow.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Back" } } } }, - "onboarding.continue": { - "comment": "Button text for continuing to the next onboarding step.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Continue" + "onboarding.continue" : { + "comment" : "Button text for continuing to the next onboarding step.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Continue" } } } }, - "onboarding.enableLocation": { - "comment": "Button text to prompt the user to enable location services.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Enable Location" + "onboarding.enableLocation" : { + "comment" : "Button text to prompt the user to enable location services.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Enable Location" } } } }, - "onboarding.location.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Where uses background location to log the regions you pass through. You can change this anytime in Settings." + "onboarding.location.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Where uses background location to log the regions you pass through. You can change this anytime in Settings." } } } }, - "onboarding.location.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Turn on location" + "onboarding.location.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Turn on location" } } } }, - "onboarding.next": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Next" + "onboarding.next" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Next" } } } }, - "onboarding.notNow": { - "comment": "Button title for skipping the onboarding flow.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Not Now" + "onboarding.notNow" : { + "comment" : "Button title for skipping the onboarding flow.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Not Now" } } } }, - "onboarding.privacy.description": { - "comment": "Description of the privacy policy of the app.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Your location stays on your device and in your own iCloud. Turn on background location to start your passport." + "onboarding.privacy.description" : { + "comment" : "Description of the privacy policy of the app.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Your location stays on your device and in your own iCloud. Turn on background location to start your passport." } } } }, - "onboarding.privacy.title": { - "comment": "Title of the privacy section of the onboarding flow.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Private by design" + "onboarding.privacy.title" : { + "comment" : "Title of the privacy section of the onboarding flow.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Private by design" } } } }, - "onboarding.regions.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Where do you spend your time?" + "onboarding.regions.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Where do you spend your time?" } } } }, - "onboarding.restoreBackup": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Restore from a backup" + "onboarding.restoreBackup" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Restore from a backup" } } } }, - "onboarding.restoreError.title": { - "comment": "Title of an alert that appears when a backup can't be restored.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't restore backup" + "onboarding.restoreError.title" : { + "comment" : "Title of an alert that appears when a backup can't be restored.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't restore backup" } } } }, - "onboarding.restoring": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Restoring…" + "onboarding.restoring" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Restoring…" } } } }, - "onboarding.welcome.description": { - "comment": "A longer description of Where, for the onboarding welcome screen.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Where keeps a private passport of which regions you spend your days in — built for residency and day-count questions." + "onboarding.welcome.description" : { + "comment" : "A longer description of Where, for the onboarding welcome screen.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Where keeps a private passport of which regions you spend your days in — built for residency and day-count questions." } } } }, - "onboarding.welcome.title": { - "comment": "Title of the onboarding welcome screen.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Where have you been?" + "onboarding.welcome.title" : { + "comment" : "Title of the onboarding welcome screen.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Where have you been?" } } } }, - "primary.calendar": { - "comment": "Label for the primary calendar.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Calendar" + "primary.calendar" : { + "comment" : "Label for the primary calendar.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Calendar" } } } }, - "primary.card.calendarHint": { - "comment": "Accessibility hint on a Primary region card: tapping it opens that region's calendar, filtered to the days spent there.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Opens the calendar of days spent here." + "primary.card.calendarHint" : { + "comment" : "Accessibility hint on a Primary region card: tapping it opens that region's calendar, filtered to the days spent there.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Opens the calendar of days spent here." } } } }, - "primary.elsewhereOnly.description": { - "extractionState": "manual", - "localizations": { - "en": { - "variations": { - "plural": { - "one": { - "stringUnit": { - "state": "translated", - "value": "%lld day logged this year, but none in a headline spot yet." + "primary.elsewhereOnly.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "variations" : { + "plural" : { + "one" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld day logged this year, but none in a headline spot yet." } }, - "other": { - "stringUnit": { - "state": "translated", - "value": "%lld days logged this year, but none in a headline spot yet." + "other" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld days logged this year, but none in a headline spot yet." } } } @@ -1688,2511 +1697,2511 @@ } } }, - "primary.elsewhereOnly.open": { - "comment": "Button on the Locations elsewhere-only state that opens the Elsewhere list.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "See Elsewhere" + "primary.elsewhereOnly.open" : { + "comment" : "Button on the Locations elsewhere-only state that opens the Elsewhere list.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "See Elsewhere" } } } }, - "primary.elsewhereOnly.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing in your headline spots" + "primary.elsewhereOnly.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing in your headline spots" } } } }, - "primary.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Turn on tracking or add a day in Settings and your top spots will land here." + "primary.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Turn on tracking or add a day in Settings and your top spots will land here." } } } }, - "primary.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No travels logged for %@" + "primary.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No travels logged for %@" } } } }, - "primary.evidence": { - "comment": "Label for the \"Evidence\" tab in the primary view.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Evidence" + "primary.evidence" : { + "comment" : "Label for the \"Evidence\" tab in the primary view.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Evidence" } } } }, - "primary.loading": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Charting your year…" + "primary.loading" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Charting your year…" } } } }, - "primary.loggedDays": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Logged days" + "primary.loggedDays" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Logged days" } } } }, - "primary.recentActivity": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Recent activity" + "primary.recentActivity" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Recent activity" } } } }, - "primary.timeline": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Timeline" + "primary.timeline" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Timeline" } } } }, - "recentActivity.empty.description.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No locations were recorded in the last 24 hours." + "recentActivity.empty.description.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No locations were recorded in the last 24 hours." } } } }, - "recentActivity.empty.description.month": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No locations were recorded in the past month." + "recentActivity.empty.description.month" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No locations were recorded in the past month." } } } }, - "recentActivity.empty.description.week": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No locations were recorded in the past week." + "recentActivity.empty.description.week" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No locations were recorded in the past week." } } } }, - "recentActivity.empty.description.yearToDate": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No locations were recorded so far this year." + "recentActivity.empty.description.yearToDate" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No locations were recorded so far this year." } } } }, - "recentActivity.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing tracked" + "recentActivity.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing tracked" } } } }, - "recentActivity.failed.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't summarize" + "recentActivity.failed.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't summarize" } } } }, - "recentActivity.footer.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An on-device summary of where you've been in the last 24 hours. Your location never leaves your device." + "recentActivity.footer.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An on-device summary of where you've been in the last 24 hours. Your location never leaves your device." } } } }, - "recentActivity.footer.month": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An on-device summary of where you've been over the past month. Your location never leaves your device." + "recentActivity.footer.month" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An on-device summary of where you've been over the past month. Your location never leaves your device." } } } }, - "recentActivity.footer.week": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An on-device summary of where you've been over the past week. Your location never leaves your device." + "recentActivity.footer.week" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An on-device summary of where you've been over the past week. Your location never leaves your device." } } } }, - "recentActivity.footer.yearToDate": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "An on-device summary of where you've been so far this year. Your location never leaves your device." + "recentActivity.footer.yearToDate" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "An on-device summary of where you've been so far this year. Your location never leaves your device." } } } }, - "recentActivity.loading": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Summarizing…" + "recentActivity.loading" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Summarizing…" } } } }, - "recentActivity.refresh": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Refresh" + "recentActivity.refresh" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Refresh" } } } }, - "recentActivity.title.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Last 24 hours" + "recentActivity.title.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Last 24 hours" } } } }, - "recentActivity.title.month": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Past month" + "recentActivity.title.month" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Past month" } } } }, - "recentActivity.title.week": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Past week" + "recentActivity.title.week" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Past week" } } } }, - "recentActivity.title.yearToDate": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Year so far" + "recentActivity.title.yearToDate" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Year so far" } } } }, - "recentActivity.unavailable.appleIntelligenceNotEnabled": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Turn on Apple Intelligence in Settings to generate summaries." + "recentActivity.unavailable.appleIntelligenceNotEnabled" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Turn on Apple Intelligence in Settings to generate summaries." } } } }, - "recentActivity.unavailable.deviceNotEligible": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This device doesn't support on-device summaries." + "recentActivity.unavailable.deviceNotEligible" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This device doesn't support on-device summaries." } } } }, - "recentActivity.unavailable.modelNotReady": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The on-device model is still getting ready. Try again shortly." + "recentActivity.unavailable.modelNotReady" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The on-device model is still getting ready. Try again shortly." } } } }, - "recentActivity.unavailable.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Summaries unavailable" + "recentActivity.unavailable.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Summaries unavailable" } } } }, - "recentActivity.unavailable.unknown": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "On-device summaries aren't available right now." + "recentActivity.unavailable.unknown" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "On-device summaries aren't available right now." } } } }, - "recentActivity.window.day": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "24 Hours" + "recentActivity.window.day" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "24 Hours" } } } }, - "recentActivity.window.month": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Month" + "recentActivity.window.month" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Month" } } } }, - "recentActivity.window.pickerLabel": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Summary range" + "recentActivity.window.pickerLabel" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Summary range" } } } }, - "recentActivity.window.week": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Week" + "recentActivity.window.week" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Week" } } } }, - "recentActivity.window.yearToDate": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Year" + "recentActivity.window.yearToDate" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Year" } } } }, - "regionCustomize.color": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Color" + "regionCustomize.color" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Color" } } } }, - "regionCustomize.color.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Color %@" + "regionCustomize.color.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Color %@" } } } }, - "regionCustomize.emoji": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Emoji" + "regionCustomize.emoji" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Emoji" } } } }, - "regionCustomize.step": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Region %1$lld of %2$lld" + "regionCustomize.step" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Region %1$lld of %2$lld" } } } }, - "regionCustomize.subtitle": { - "comment": "Subtitle for the region customization screen.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Choose a look for %@" + "regionCustomize.subtitle" : { + "comment" : "Subtitle for the region customization screen.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Choose a look for %@" } } } }, - "regionCustomize.symbol": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Icon" + "regionCustomize.symbol" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Icon" } } } }, - "regionCustomize.title": { - "comment": "Title of the screen that lets the user customize a region.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Make it yours" + "regionCustomize.title" : { + "comment" : "Title of the screen that lets the user customize a region.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Make it yours" } } } }, - "regionGroup.more": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "More regions" + "regionGroup.more" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "More regions" } } } }, - "regionGroup.usedThisYear": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Used this year" + "regionGroup.usedThisYear" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Used this year" } } } }, - "regionGroup.yours": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Your regions" + "regionGroup.yours" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Your regions" } } } }, - "regionMap.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No region geometry was found in the bundle." + "regionMap.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No region geometry was found in the bundle." } } } }, - "regionMap.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No regions" + "regionMap.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No regions" } } } }, - "regionMap.kind.attribution": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Attribution" + "regionMap.kind.attribution" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attribution" } } } }, - "regionMap.kind.attribution.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "The simplified polygons the app uses to attribute coordinates today." + "regionMap.kind.attribution.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The simplified polygons the app uses to attribute coordinates today." } } } }, - "regionMap.kind.picker": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Geometry" + "regionMap.kind.picker" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Geometry" } } } }, - "regionMap.kind.source": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Source" + "regionMap.kind.source" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Source" } } } }, - "regionMap.kind.source.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Every feature decoded straight from the bundled GeoJSON, at full authored fidelity." + "regionMap.kind.source.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Every feature decoded straight from the bundled GeoJSON, at full authored fidelity." } } } }, - "regionMap.legend.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Features" + "regionMap.legend.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Features" } } } }, - "regionMap.loadError.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Couldn't load regions" + "regionMap.loadError.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Couldn't load regions" } } } }, - "regionMap.map.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Map of region boundaries" + "regionMap.map.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Map of region boundaries" } } } }, - "regionMap.showAll": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Show all" + "regionMap.showAll" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show all" } } } }, - "regionMap.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Region Map" + "regionMap.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Region Map" } } } }, - "regionPicker.atCapacity": { - "comment": "Shown when the selection is full, so an ignored tap on a new region reads \"at capacity\" rather than \"unresponsive\".", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "That's the maximum of %lld — deselect one to choose another." + "regionPicker.atCapacity" : { + "comment" : "Shown when the selection is full, so an ignored tap on a new region reads \"at capacity\" rather than \"unresponsive\".", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "That's the maximum of %lld — deselect one to choose another." } } } }, - "regionPicker.empty.title": { - "comment": "Title of the empty state when there are no matching regions.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No matching regions" + "regionPicker.empty.title" : { + "comment" : "Title of the empty state when there are no matching regions.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No matching regions" } } } }, - "regionPicker.loadError.title": { - "comment": "Title of an alert when the map fails to load.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Couldn't load the map" + "regionPicker.loadError.title" : { + "comment" : "Title of an alert when the map fails to load.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Couldn't load the map" } } } }, - "regionPicker.map.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Map for picking your regions" + "regionPicker.map.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Map for picking your regions" } } } }, - "regionPicker.mode.list": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "List" + "regionPicker.mode.list" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "List" } } } }, - "regionPicker.mode.map": { - "comment": "Title of the \"Map\" tab in the region picker.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Map" + "regionPicker.mode.map" : { + "comment" : "Title of the \"Map\" tab in the region picker.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Map" } } } }, - "regionPicker.mode.picker": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "View" + "regionPicker.mode.picker" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "View" } } } }, - "regionPicker.search.prompt": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Search regions" + "regionPicker.search.prompt" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Search regions" } } } }, - "regionPicker.selectionCount": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%1$lld of %2$lld selected" + "regionPicker.selectionCount" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$lld of %2$lld selected" } } } }, - "regionPicker.subtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Pick up to 5 regions where you spend your time." + "regionPicker.subtitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Pick up to 5 regions where you spend your time." } } } }, - "regionPicker.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Your regions" + "regionPicker.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Your regions" } } } }, - "regions.manage.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Your regions" + "regions.manage.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Your regions" } } } }, - "relabel.reason.borderDrift": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Some points look like GPS drift near the %@ border." + "relabel.reason.borderDrift" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Some points look like GPS drift near the %@ border." } } } }, - "relabel.reason.borderDrift.distance": { - "comment": "Reason for relabeling a day as a border drift, including a distance.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Some points sit about %1$@ outside %2$@ — likely GPS drift near the border." + "relabel.reason.borderDrift.distance" : { + "comment" : "Reason for relabeling a day as a border drift, including a distance.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Some points sit about %1$@ outside %2$@ — likely GPS drift near the border." } } } }, - "relabel.reason.flight": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "This looked like a flight — high-speed points added %@. Set where you actually were." + "relabel.reason.flight" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "This looked like a flight — high-speed points added %@. Set where you actually were." } } } }, - "relabel.reason.title": { - "comment": "Title of a banner that appears when a day's regions need to be re-labeled.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Why this needs a look" + "relabel.reason.title" : { + "comment" : "Title of a banner that appears when a day's regions need to be re-labeled.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Why this needs a look" } } } }, - "relabel.reason.travelDay": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "The days around this one don't overlap — set where you were if you were traveling." + "relabel.reason.travelDay" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "The days around this one don't overlap — set where you were if you were traveling." } } } }, - "relabel.regions.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This replaces what was recorded for this day, overriding GPS. Your raw location data is kept, so you can change it back." + "relabel.regions.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This replaces what was recorded for this day, overriding GPS. Your raw location data is kept, so you can change it back." } } } }, - "relabel.regions.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Where were you?" + "relabel.regions.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Where were you?" } } } }, - "relabel.reset": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reset to GPS-detected location" + "relabel.reset" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reset to GPS-detected location" } } } }, - "relabel.reset.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Removes any manual correction for this day and restores the regions detected from GPS. Your raw location data is untouched." + "relabel.reset.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Removes any manual correction for this day and restores the regions detected from GPS. Your raw location data is untouched." } } } }, - "relabel.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Fix this day" + "relabel.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fix this day" } } } }, - "resolution.abrupt.detail.bothRight": { - "comment": "Label for a button that marks both days as travel days.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "These are both right" + "resolution.abrupt.detail.bothRight" : { + "comment" : "Label for a button that marks both days as travel days.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "These are both right" } } } }, - "resolution.abrupt.detail.earlier": { - "comment": "Label for the earlier day in the \"Sudden location change\" detail view.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Earlier day" + "resolution.abrupt.detail.earlier" : { + "comment" : "Label for the earlier day in the \"Sudden location change\" detail view.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Earlier day" } } } }, - "resolution.abrupt.detail.explanation": { - "comment": "Explanation of the abrupt location change detail.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "These back-to-back days don't overlap at all — you were probably traveling and one day wasn't logged in both places." + "resolution.abrupt.detail.explanation" : { + "comment" : "Explanation of the abrupt location change detail.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "These back-to-back days don't overlap at all — you were probably traveling and one day wasn't logged in both places." } } } }, - "resolution.abrupt.detail.later": { - "comment": "Label for the column of a row in the \"Sudden location change\" detail view.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Later day" + "resolution.abrupt.detail.later" : { + "comment" : "Label for the column of a row in the \"Sudden location change\" detail view.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Later day" } } } }, - "resolution.abrupt.detail.relabelEarlier": { - "comment": "Label for a button that lets the user mark a day as a travel day when it was previously marked as a non-travel day.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Mark as a travel day" + "resolution.abrupt.detail.relabelEarlier" : { + "comment" : "Label for a button that lets the user mark a day as a travel day when it was previously marked as a non-travel day.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Mark as a travel day" } } } }, - "resolution.abrupt.detail.relabelLater": { - "comment": "Label for a button that relabels a day as a travel day.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Mark as a travel day" + "resolution.abrupt.detail.relabelLater" : { + "comment" : "Label for a button that relabels a day as a travel day.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Mark as a travel day" } } } }, - "resolution.abrupt.detail.title": { - "comment": "Title of a screen that shows a list of abrupt location changes.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Sudden location change" + "resolution.abrupt.detail.title" : { + "comment" : "Title of a screen that shows a list of abrupt location changes.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sudden location change" } } } }, - "resolution.abrupt.rowTitle": { - "comment": "Title of a row in the resolution screen that shows the regions that the user has been in and the regions that they were in before.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%1$@ → %2$@" + "resolution.abrupt.rowTitle" : { + "comment" : "Title of a row in the resolution screen that shows the regions that the user has been in and the regions that they were in before.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%1$@ → %2$@" } } } }, - "resolution.dismiss": { - "comment": "Label for a button that dismisses a resolution.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Dismiss" + "resolution.dismiss" : { + "comment" : "Label for a button that dismisses a resolution.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Dismiss" } } } }, - "resolution.drift.subtitle": { - "comment": "Subtitle for a row in the resolution screen that describes a location that is near the border.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Looks like %1$@, ~%2$@ over the border" + "resolution.drift.subtitle" : { + "comment" : "Subtitle for a row in the resolution screen that describes a location that is near the border.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Looks like %1$@, ~%2$@ over the border" } } } }, - "resolution.empty.description": { - "comment": "Description of an empty state when there are no resolution issues.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No data issues need your attention right now." + "resolution.empty.description" : { + "comment" : "Description of an empty state when there are no resolution issues.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No data issues need your attention right now." } } } }, - "resolution.empty.title": { - "comment": "Title of the resolution screen when all missing days have been resolved.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "All clear" + "resolution.empty.title" : { + "comment" : "Title of the resolution screen when all missing days have been resolved.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "All clear" } } } }, - "resolution.flight.apply": { - "comment": "Label for a button that applies a resolution that keeps a set of regions.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Keep %@" + "resolution.flight.apply" : { + "comment" : "Label for a button that applies a resolution that keeps a set of regions.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Keep %@" } } } }, - "resolution.flight.bothRight": { - "comment": "Label for a button that lets the user keep all the regions.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "These are all correct" + "resolution.flight.bothRight" : { + "comment" : "Label for a button that lets the user keep all the regions.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "These are all correct" } } } }, - "resolution.flight.detail.explanation": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Some GPS points crossed the map at about %1$@ — that usually means a flight, not somewhere you actually stopped. Applying this keeps where you took off and landed and drops %2$@." + "resolution.flight.detail.explanation" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Some GPS points crossed the map at about %1$@ — that usually means a flight, not somewhere you actually stopped. Applying this keeps where you took off and landed and drops %2$@." } } } }, - "resolution.flight.detail.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Looks like a flight" + "resolution.flight.detail.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Looks like a flight" } } } }, - "resolution.flight.manualFix": { - "comment": "Label for a button that lets the user manually fix a \"looks like a flight\" resolution.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Not what you expected?" + "resolution.flight.manualFix" : { + "comment" : "Label for a button that lets the user manually fix a \"looks like a flight\" resolution.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Not what you expected?" } } } }, - "resolution.flight.manualFix.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "If this wasn't a flight, or you'd rather set the regions yourself, fix the day by hand." + "resolution.flight.manualFix.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "If this wasn't a flight, or you'd rather set the regions yourself, fix the day by hand." } } } }, - "resolution.flight.rowSubtitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Looks like a flight" + "resolution.flight.rowSubtitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Looks like a flight" } } } }, - "resolution.section.abruptChange": { - "comment": "Label for a section of the resolution screen that lists days with abrupt location changes.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Sudden moves" + "resolution.section.abruptChange" : { + "comment" : "Label for a section of the resolution screen that lists days with abrupt location changes.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Sudden moves" } } } }, - "resolution.section.borderDrift": { - "comment": "Label for a section of the resolution screen that lists days that are near the border.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Near the border" + "resolution.section.borderDrift" : { + "comment" : "Label for a section of the resolution screen that lists days that are near the border.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Near the border" } } } }, - "resolution.section.flightDay": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Flights" + "resolution.section.flightDay" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Flights" } } } }, - "resolution.section.missingDays": { - "comment": "Label for a section of the resolution screen that lists missing days.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Missing days" + "resolution.section.missingDays" : { + "comment" : "Label for a section of the resolution screen that lists missing days.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Missing days" } } } }, - "resolution.title": { - "comment": "Title of a screen that lets the user resolve a missing day.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Resolve" + "resolution.title" : { + "comment" : "Title of a screen that lets the user resolve a missing day.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Resolve" } } } }, - "secondary.caption.passingThrough": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Just passing through" + "secondary.caption.passingThrough" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Just passing through" } } } }, - "secondary.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Spend a day outside your top spots — or log a trip in Settings — and it'll appear here." + "secondary.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Spend a day outside your top spots — or log a trip in Settings — and it'll appear here." } } } }, - "secondary.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nowhere else logged" + "secondary.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nowhere else logged" } } } }, - "secondary.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Everywhere else you turned up in %@." + "secondary.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Everywhere else you turned up in %@." } } } }, - "secondary.loading": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Retracing your steps…" + "secondary.loading" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Retracing your steps…" } } } }, - "secondary.region.current": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Counts as %@" + "secondary.region.current" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Counts as %@" } } } }, - "secondary.region.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No days counted for this region." + "secondary.region.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No days counted for this region." } } } }, - "secondary.region.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Nothing to fix" + "secondary.region.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nothing to fix" } } } }, - "secondary.region.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tap a day to fix where it counted. Your GPS data stays untouched." + "secondary.region.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tap a day to fix where it counted. Your GPS data stays untouched." } } } }, - "secondary.region.map.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Map of where you were" + "secondary.region.map.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Map of where you were" } } } }, - "secondary.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Elsewhere" + "secondary.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Elsewhere" } } } }, - "settings.alerts.group": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Alerts & Data Resolution" + "settings.alerts.group" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alerts & Data Resolution" } } } }, - "settings.appIcon.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Pick the icon Where shows on your Home Screen." + "settings.appIcon.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Pick the icon Where shows on your Home Screen." } } } }, - "settings.appIcon.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Appearance" + "settings.appIcon.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appearance" } } } }, - "settings.appIcon.link": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "App icon" + "settings.appIcon.link" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "App icon" } } } }, - "settings.appearance.group": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Appearance" + "settings.appearance.group" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Appearance" } } } }, - "settings.attachments.row": { - "comment": "Row title for the attachments (evidence) screen in the Settings Data group.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Attachments" + "settings.attachments.row" : { + "comment" : "Row title for the attachments (evidence) screen in the Settings Data group.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Attachments" } } } }, - "settings.backup.errorTitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Backup failed" + "settings.backup.errorTitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Backup failed" } } } }, - "settings.backup.export": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Export data" + "settings.backup.export" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Export data" } } } }, - "settings.backup.exporting": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Exporting…" + "settings.backup.exporting" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Exporting…" } } } }, - "settings.backup.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Export your whole history as a .zip you can email or save to Files, then import it on another device to restore everything." + "settings.backup.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Export your whole history as a .zip you can email or save to Files, then import it on another device to restore everything." } } } }, - "settings.backup.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Backup" + "settings.backup.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Backup" } } } }, - "settings.backup.import": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import data" + "settings.backup.import" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import data" } } } }, - "settings.backup.importStrategy.message": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Merge keeps everything already on this device and adds the file's records. Replace erases this device first, then restores only what's in the file." + "settings.backup.importStrategy.message" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Merge keeps everything already on this device and adds the file's records. Replace erases this device first, then restores only what's in the file." } } } }, - "settings.backup.importStrategy.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Import backup" + "settings.backup.importStrategy.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Import backup" } } } }, - "settings.backup.imported.message": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Imported %lld location samples, %lld pieces of evidence, %lld manual days, %lld dismissed issues, and %lld tracked regions." + "settings.backup.imported.message" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Imported %lld location samples, %lld pieces of evidence, %lld manual days, %lld dismissed issues, and %lld tracked regions." } } } }, - "settings.backup.imported.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Backup imported" + "settings.backup.imported.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Backup imported" } } } }, - "settings.backup.importing": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Importing…" + "settings.backup.importing" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Importing…" } } } }, - "settings.backup.merge": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Merge" + "settings.backup.merge" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Merge" } } } }, - "settings.backup.replace": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Replace all" + "settings.backup.replace" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Replace all" } } } }, - "settings.backup.share": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Share backup" + "settings.backup.share" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Share backup" } } } }, - "settings.backup.shareTitle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Where Backup" + "settings.backup.shareTitle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Where Backup" } } } }, - "settings.data.cancel": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Cancel" + "settings.data.cancel" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Cancel" } } } }, - "settings.data.confirmMessage": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "This removes every sample, manual day, and piece of evidence in %@. It can't be undone." + "settings.data.confirmMessage" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "This removes every sample, manual day, and piece of evidence in %@. It can't be undone." } } } }, - "settings.data.erase": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Erase %@ data" + "settings.data.erase" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erase %@ data" } } } }, - "settings.data.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Acts on the year selected on the Primary tab (%@)." + "settings.data.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Acts on the year selected on the Primary tab (%@)." } } } }, - "settings.data.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Data" + "settings.data.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Data" } } } }, - "settings.eraseYear.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Erase year data" + "settings.eraseYear.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erase year data" } } } }, - "settings.findIssues": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Find issues now" + "settings.findIssues" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Find issues now" } } } }, - "settings.findIssues.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Scan the selected year for data issues right now — such as GPS drift or missed days — instead of waiting for the periodic check. Anything found appears in the Resolve tab." + "settings.findIssues.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Scan the selected year for data issues right now — such as GPS drift or missed days — instead of waiting for the periodic check. Anything found appears in the Resolve tab." } } } }, - "settings.findIssues.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Find issues" + "settings.findIssues.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Find issues" } } } }, - "settings.findIssues.result.many": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "%lld issues to resolve" + "settings.findIssues.result.many" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "%lld issues to resolve" } } } }, - "settings.findIssues.result.none": { - "comment": "Result of a manual \"Find issues now\" scan — the current unresolved count for the year, worded as present state.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No issues to resolve" + "settings.findIssues.result.none" : { + "comment" : "Result of a manual \"Find issues now\" scan — the current unresolved count for the year, worded as present state.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No issues to resolve" } } } }, - "settings.findIssues.result.one": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "1 issue to resolve" + "settings.findIssues.result.one" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "1 issue to resolve" } } } }, - "settings.findIssues.scanning": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Scanning…" + "settings.findIssues.scanning" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Scanning…" } } } }, - "settings.issueAlerts.deniedFooter": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications are turned off for Where, so issue alerts can't appear. Turn them on in Settings." + "settings.issueAlerts.deniedFooter" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications are turned off for Where, so issue alerts can't appear. Turn them on in Settings." } } } }, - "settings.issueAlerts.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Badge the app icon and send a reminder when there are data issues waiting in the Resolve tab." + "settings.issueAlerts.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Badge the app icon and send a reminder when there are data issues waiting in the Resolve tab." } } } }, - "settings.issueAlerts.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Issue alerts" + "settings.issueAlerts.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Issue alerts" } } } }, - "settings.issueAlerts.toggle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Issue alerts" + "settings.issueAlerts.toggle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Issue alerts" } } } }, - "settings.keywords.appIcon": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "app icon, icon, home screen, appearance" + "settings.keywords.appIcon" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "app icon, icon, home screen, appearance" } } } }, - "settings.keywords.attachments": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "attachments, evidence, receipt, boarding pass, ticket, photo" + "settings.keywords.attachments" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "attachments, evidence, receipt, boarding pass, ticket, photo" } } } }, - "settings.keywords.dataResolution": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "drift, gps, border, threshold, resolution, distance" + "settings.keywords.dataResolution" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "drift, gps, border, threshold, resolution, distance" } } } }, - "settings.keywords.eraseYear": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "erase, delete, clear, year, data" + "settings.keywords.eraseYear" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "erase, delete, clear, year, data" } } } }, - "settings.keywords.export": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "backup, export, save, share, archive" + "settings.keywords.export" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "backup, export, save, share, archive" } } } }, - "settings.keywords.findIssues": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "scan, find, issues, check, resolve" + "settings.keywords.findIssues" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "scan, find, issues, check, resolve" } } } }, - "settings.keywords.import": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "backup, import, restore, load, archive" + "settings.keywords.import" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "backup, import, restore, load, archive" } } } }, - "settings.keywords.issueAlerts": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "issue, alerts, notification, badge, resolve" + "settings.keywords.issueAlerts" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "issue, alerts, notification, badge, resolve" } } } }, - "settings.keywords.loggedDays": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "logged days, manual, override, entry, backfill" + "settings.keywords.loggedDays" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "logged days, manual, override, entry, backfill" } } } }, - "settings.keywords.regions": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "regions, states, countries, places, primary" + "settings.keywords.regions" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "regions, states, countries, places, primary" } } } }, - "settings.keywords.reminder": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "reminder, notification, nudge, daily, log" + "settings.keywords.reminder" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "reminder, notification, nudge, daily, log" } } } }, - "settings.keywords.reset": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "reset, erase, delete, wipe, start over" + "settings.keywords.reset" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "reset, erase, delete, wipe, start over" } } } }, - "settings.keywords.summary": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "summary, recap, notification, morning, digest" + "settings.keywords.summary" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "summary, recap, notification, morning, digest" } } } }, - "settings.keywords.tracking": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "location, gps, tracking, background, permission" + "settings.keywords.tracking" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "location, gps, tracking, background, permission" } } } }, - "settings.keywords.year": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "year, report, calendar" + "settings.keywords.year" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "year, report, calendar" } } } }, - "settings.location.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Where watches for visits and big moves to figure out which region you're in. It needs Always access and a little patience." + "settings.location.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Where watches for visits and big moves to figure out which region you're in. It needs Always access and a little patience." } } } }, - "settings.location.grant": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Grant location access" + "settings.location.grant" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Grant location access" } } } }, - "settings.location.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Location" + "settings.location.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location" } } } }, - "settings.location.toggle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Track in the background" + "settings.location.toggle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Track in the background" } } } }, - "settings.loggedDays.row": { - "comment": "Row title for the hand-logged-days screen in the Settings Data group.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Logged Days" + "settings.loggedDays.row" : { + "comment" : "Row title for the hand-logged-days screen in the Settings Data group.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Logged Days" } } } }, - "settings.permissionAlert.message": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Where needs Always location access to log which region you're in. You can grant it in the Settings app." + "settings.permissionAlert.message" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Where needs Always location access to log which region you're in. You can grant it in the Settings app." } } } }, - "settings.permissionAlert.notNow": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Not now" + "settings.permissionAlert.notNow" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Not now" } } } }, - "settings.permissionAlert.openSettings": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Open Settings" + "settings.permissionAlert.openSettings" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open Settings" } } } }, - "settings.permissionAlert.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Location access needed" + "settings.permissionAlert.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location access needed" } } } }, - "settings.regions.empty": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "None yet" + "settings.regions.empty" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "None yet" } } } }, - "settings.regions.row": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Primary regions" + "settings.regions.row" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Primary regions" } } } }, - "settings.regions.section": { - "comment": "Label for the settings option to manage your regions.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Regions" + "settings.regions.section" : { + "comment" : "Label for the settings option to manage your regions.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Regions" } } } }, - "settings.reminders.deniedFooter": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications are turned off for Where, so reminders and the badge can't appear. Turn them on in Settings." + "settings.reminders.deniedFooter" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications are turned off for Where, so reminders and the badge can't appear. Turn them on in Settings." } } } }, - "settings.reminders.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "If a day hasn't been logged, we'll nudge you before it ends and badge the app. The reminder clears itself once the day is recorded." + "settings.reminders.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "If a day hasn't been logged, we'll nudge you before it ends and badge the app. The reminder clears itself once the day is recorded." } } } }, - "settings.reminders.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Reminders" + "settings.reminders.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Reminders" } } } }, - "settings.reminders.openSettings": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Allow notifications" + "settings.reminders.openSettings" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allow notifications" } } } }, - "settings.reminders.time": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Remind me at" + "settings.reminders.time" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remind me at" } } } }, - "settings.reminders.toggle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Daily logging reminder" + "settings.reminders.toggle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Daily logging reminder" } } } }, - "settings.reset.confirm": { - "comment": "Button text for erasing all data and resetting the app.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Erase Everything & Reset" + "settings.reset.confirm" : { + "comment" : "Button text for erasing all data and resetting the app.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Erase Everything & Reset" } } } }, - "settings.reset.erase": { - "comment": "Label for the button to erase all data and reset the app.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Erase all data & reset" + "settings.reset.erase" : { + "comment" : "Label for the button to erase all data and reset the app.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Erase all data & reset" } } } }, - "settings.reset.footer": { - "comment": "Footer for the reset confirmation dialog.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Starts over from scratch, as if you'd just installed Where." + "settings.reset.footer" : { + "comment" : "Footer for the reset confirmation dialog.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Starts over from scratch, as if you'd just installed Where." } } } }, - "settings.reset.message": { - "comment": "Confirmation message for the reset action.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "This erases every sample, manual day, and piece of evidence on this device and returns you to first-run setup. It can't be undone." + "settings.reset.message" : { + "comment" : "Confirmation message for the reset action.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "This erases every sample, manual day, and piece of evidence on this device and returns you to first-run setup. It can't be undone." } } } }, - "settings.resolution.footer": { - "comment": "Footer for the settings screen that explains the meaning of the resolution distance.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Days logged just outside a primary region within this distance are flagged as possible GPS drift." + "settings.resolution.footer" : { + "comment" : "Footer for the settings screen that explains the meaning of the resolution distance.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Days logged just outside a primary region within this distance are flagged as possible GPS drift." } } } }, - "settings.resolution.header": { - "comment": "Title of the settings screen for data resolution.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Data resolution" + "settings.resolution.header" : { + "comment" : "Title of the settings screen for data resolution.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Data resolution" } } } }, - "settings.resolution.threshold": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Drift threshold" + "settings.resolution.threshold" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Drift threshold" } } } }, - "settings.search.prompt": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Search settings" + "settings.search.prompt" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Search settings" } } } }, - "settings.status.alwaysPaused": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Always allowed (paused)" + "settings.status.alwaysPaused" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Always allowed (paused)" } } } }, - "settings.status.denied": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Location access denied" + "settings.status.denied" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location access denied" } } } }, - "settings.status.notDetermined": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Location access not set up" + "settings.status.notDetermined" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location access not set up" } } } }, - "settings.status.restricted": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Location access restricted" + "settings.status.restricted" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location access restricted" } } } }, - "settings.status.tracking": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Tracking in the background" + "settings.status.tracking" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Tracking in the background" } } } }, - "settings.status.whenInUse": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "While Using only — needs Always" + "settings.status.whenInUse" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "While Using only — needs Always" } } } }, - "settings.summary.deniedFooter": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Notifications are turned off for Where, so the daily summary can't appear. Turn them on in Settings." + "settings.summary.deniedFooter" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Notifications are turned off for Where, so the daily summary can't appear. Turn them on in Settings." } } } }, - "settings.summary.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Get a morning recap of how many days you've logged in each region so far this year." + "settings.summary.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Get a morning recap of how many days you've logged in each region so far this year." } } } }, - "settings.summary.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Daily summary" + "settings.summary.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Daily summary" } } } }, - "settings.summary.time": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Send at" + "settings.summary.time" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Send at" } } } }, - "settings.summary.toggle": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Daily summary" + "settings.summary.toggle" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Daily summary" } } } }, - "settings.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Settings" + "settings.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings" } } } }, - "settings.year.footer": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Choose which year your reports, calendar, and logged days cover." + "settings.year.footer" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Choose which year your reports, calendar, and logged days cover." } } } }, - "settings.year.header": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Report year" + "settings.year.header" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Report year" } } } }, - "settings.year.label": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Year" + "settings.year.label" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Year" } } } }, - "tab.locations": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Locations" + "tab.locations" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Locations" } } } }, - "tab.resolution": { - "comment": "Label for the tab that shows data issues to resolve.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Resolve" + "tab.resolution" : { + "comment" : "Label for the tab that shows data issues to resolve.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Resolve" } } } }, - "tab.settings": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Settings" + "tab.settings" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings" } } } }, - "tab.year": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Your Year" + "tab.year" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Your Year" } } } }, - "timeline.empty.description": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Once Where has a run of days in a region, your stays will appear here." + "timeline.empty.description" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Once Where has a run of days in a region, your stays will appear here." } } } }, - "timeline.empty.title": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "No stays yet" + "timeline.empty.title" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No stays yet" } } } }, - "timeline.row.accessibility": { - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "%1$@, %2$@, %3$@" + "timeline.row.accessibility" : { + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@, %2$@, %3$@" } } } }, - "widget.today.empty": { - "comment": "Text displayed in the widget when no data is available for the current day.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Nothing logged yet" + "widget.today.empty" : { + "comment" : "Text displayed in the widget when no data is available for the current day.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Nothing logged yet" } } } }, - "widget.today.title": { - "comment": "Title of the \"Today\" section in a widget.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Today" + "widget.today.title" : { + "comment" : "Title of the \"Today\" section in a widget.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Today" } } } }, - "widget.year.empty": { - "comment": "Text displayed in a widget when there are no days logged in a year.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "No days logged" + "widget.year.empty" : { + "comment" : "Text displayed in a widget when there are no days logged in a year.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "No days logged" } } } }, - "widget.year.title": { - "comment": "Title of a year widget.", - "extractionState": "manual", - "isCommentAutoGenerated": true, - "localizations": { - "en": { - "stringUnit": { - "state": "new", - "value": "Days in %@" + "widget.year.title" : { + "comment" : "Title of a year widget.", + "extractionState" : "manual", + "isCommentAutoGenerated" : true, + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "new", + "value" : "Days in %@" } } } }, - "year.segmentPicker": { - "comment": "Accessibility label for the Your Year tab's segmented control.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Year view" + "year.segmentPicker" : { + "comment" : "Accessibility label for the Your Year tab's segmented control.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Year view" } } } } }, - "version": "1.1" -} + "version" : "1.1" +} \ No newline at end of file diff --git a/Where/WhereWidgets/Resources/Localizable.xcstrings b/Where/WhereWidgets/Resources/Localizable.xcstrings index 3a16296ae..2acc1aea5 100644 --- a/Where/WhereWidgets/Resources/Localizable.xcstrings +++ b/Where/WhereWidgets/Resources/Localizable.xcstrings @@ -1,54 +1,54 @@ { - "sourceLanguage": "en", - "strings": { - "widget.gallery.today.description": { - "comment": "Widget gallery description for the Today widget.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Which region today counts for." + "sourceLanguage" : "en", + "strings" : { + "widget.gallery.today.description" : { + "comment" : "Widget gallery description for the Today widget.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Which region today counts for." } } } }, - "widget.gallery.today.name": { - "comment": "Widget gallery name for the Today widget.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Today" + "widget.gallery.today.name" : { + "comment" : "Widget gallery name for the Today widget.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Today" } } } }, - "widget.gallery.yearTotals.description": { - "comment": "Widget gallery description for the year totals widget.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Days spent in each region this year." + "widget.gallery.yearTotals.description" : { + "comment" : "Widget gallery description for the year totals widget.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Days spent in each region this year." } } } }, - "widget.gallery.yearTotals.name": { - "comment": "Widget gallery name for the year totals widget.", - "extractionState": "manual", - "localizations": { - "en": { - "stringUnit": { - "state": "translated", - "value": "Day Counts" + "widget.gallery.yearTotals.name" : { + "comment" : "Widget gallery name for the year totals widget.", + "extractionState" : "manual", + "localizations" : { + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Day Counts" } } } } }, - "version": "1.1" -} + "version" : "1.1" +} \ No newline at end of file From 18dc5b423f3c6068042d141ede0ec9cc784f37d4 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Fri, 24 Jul 2026 18:29:19 -0700 Subject: [PATCH 3/4] File the four source literals behind the auto-extracted catalog entries They're the reason an IDE build had a write-back to do; the entries themselves are Xcode's and stay, so the follow-up is at the source. Filed rather than fixed here to keep this change to serialization. --- Where/TODOs.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Where/TODOs.md b/Where/TODOs.md index c1fbc5c8b..ef897b29d 100644 --- a/Where/TODOs.md +++ b/Where/TODOs.md @@ -51,6 +51,7 @@ This feels like it might result in a cleaner "pipeline-esque" code layout, and a - Move `let calendar = Calendar.current` into a var on the controller? There’s a few of these - Move test only code behind @_spi - Add comments to strings in xcstrings files +- fix: Four literals in source get auto-extracted into the catalogs as value-less entries, which is why an IDE build had anything to write back at all (see the serialization normalization PR). They're committed as Xcode writes them; removing an entry for good means removing the literal. `Marker("", coordinate:)` in `RecordedPointsMap` produces the empty `""` key (an unlabeled dev-map pin — `Annotation` with an explicit accessibility label would say what it means); `Text("\(group.outlineCount)")` in `RegionMapView` and `Text("\(day.dayOfMonth)")` in `CalendarContentView` produce `%lld` and bypass `WhereFormat`'s number styling; and a `Button("Log today here")` in an `IntentSnippets` `#Preview` hardcodes copy the `snippet.logTodayHere` symbol already owns. `App content` comes from a `LifecycleContainer` `#Preview` in LifecycleKit. # Completed issues From 1a01f0b314fb5e812b3899f549a8a3a756cc1d69 Mon Sep 17 00:00:00 2001 From: Kyle Van Essen Date: Fri, 24 Jul 2026 18:33:05 -0700 Subject: [PATCH 4/4] Fix ./xcstrings summary wording and ordering Subject/verb agreement in both summaries, and flush stdout first so the lint count prints below the files it's counting rather than above them. --- xcstrings | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/xcstrings b/xcstrings index f6129437a..968fa5655 100755 --- a/xcstrings +++ b/xcstrings @@ -190,8 +190,11 @@ for url in targets { } if offenders.isEmpty { - print("\(targets.count) catalog\(targets.count == 1 ? "" : "s") already match Xcode's serialization.") + let subject = targets.count == 1 ? "catalog already matches" : "catalogs already match" + print("\(targets.count) \(subject) Xcode's serialization.") } else if lintOnly { - FileHandle.standardError.write(Data("\(offenders.count) catalog(s) not normalized — run ./xcstrings\n".utf8)) + let subject = offenders.count == 1 ? "catalog isn't" : "catalogs aren't" + fflush(stdout) // Keep the summary below the files it counts. + FileHandle.standardError.write(Data("\(offenders.count) \(subject) normalized — run ./xcstrings\n".utf8)) exit(1) }