# I set the font to the largest size and found the same bug eleven times

> Source: <https://dev.to/renga154/i-set-the-font-to-the-largest-size-and-found-the-same-bug-eleven-times-496m>
> Published: 2026-08-16 00:01:23+00:00

I was cleaning up the UI on a side-project iOS app and did one thing: **set Dynamic Type to XXXL and screenshot every screen.**

**Reading the code had turned up nothing. The screenshots showed problems immediately.**

Eleven of them, in the end. **All the same cause.**

Here's the conclusion first. **"A parent that pins things side by side" × "text that grows" is not a bug, it's a pattern.** And in Japanese it breaks reliably worse than in English.

Same layout, different failure depending on language.

**English** wraps at word boundaries and, failing that, ends in `…`

. You can't read it, but you can tell something was cut.

**Japanese doesn't do that.** It can break between almost any two characters, so once a column is squeezed to one character wide, you get **one character per line, stacked downward.**

Actual output:

| Rendered | Intended |
|---|---|
`Paire / d / Macs` |
Paired Macs (broken mid-word) |
`Claud / e / Code` |
Claude Code |
| One character per line | "実行中のセッション" (Running sessions) |
| Three step labels stacked vertically | A three-step horizontal stepper |
`De / mo` , turning the capsule into a circle |
A "Demo" badge |

`Paire / d / Macs`

is English breaking mid-word. Once the column has only a few characters left, even English gets there. **Japanese gets there much earlier.**

Nearly all eleven were this:

```
HStack {
  Image(systemName: icon).frame(width: 44)   // fixed
  Text(label)
  Spacer()
  Text(value)                                 // pinned right
}
```

**The 44pt icon and the trailing value claim their width first, leaving the label column a few characters.**

The fix: rows that carry a value drop the value to the line below — but **affordances like chevrons and toggles stay on the right.**

That row component was shared across the whole settings tree, so **fixing one place fixed the entire settings screen.** Which also means one decision inside a shared component was breaking eleven screens.

`ViewThatFits`

is not a general answer
I used `ViewThatFits`

to switch to a stacked layout. **It broke the standard size.**

`ViewThatFits`

decides using each child's **ideal width**. A title that wraps reports **its unwrapped full length** as its ideal width. So the side-by-side candidate was judged "doesn't fit" and the badge dropped below the title *at the standard size.*

**I could not have reasoned my way to this. I found it by screenshotting the standard size.**

Where each one belongs:

`ViewThatFits`

`isAccessibilitySize`

branchI reversed one of my own calls partway through.

I'd classified a `.menu`

Picker with Toggle, as something that belongs pinned right. **A screenshot of the audit-log screen disproved that** — the filter label came out as `絞り… / 込み`

.

The rule I ended up with:

`.menu`

Picker, chevron)I had a `UITEST_FORCE_ACCESSIBILITY_XXXL`

env var for UI tests. It applies `.dynamicTypeSize`

to the root view.

**That does not propagate into a .sheet's environment.**

So the paywall and the setup guide had **never once been rendered at the largest text size.** What was passing was "the tests are green," not "the modals were checked."

Now it's applied from the system side:

```
xcrun simctl ui <udid> content_size accessibility-extra-extra-extra-large
```

After fixing six, I wrote that the pattern had converged. **It hadn't.**

There were simply screens I hadn't looked at. When I did, four more appeared — numbers seven through ten. Then I went through the QR scanner, host-add and pairing flows in Japanese at XXXL, confirmed **zero new findings**, and only then called it converged at eleven.

**The lesson is: don't declare convergence until you've actually looked at the screens.** Judge by how many screens you looked at, not by how many you fixed.

While reading the audit log, `1 items need attention`

caught my eye. I swept the strings: of **38 English strings with a quantity placeholder, zero had plural variants.**

`1 items need attention`

`1 saved Macs`

`1 days free`

(on the paywall)`1 sessions, 1 active…`

— Thirteen keys got variants. Japanese has no plural agreement, so nothing changed there. Strings like `%d of %d Macs`

, where the number doesn't agree with the noun, were deliberately left alone.

The verification order mattered. Add one key, build, confirm `1 item needs attention`

on a real screen, *then* roll out the rest. Finally, **read en.lproj/Localizable.stringsdict out of the build product** and confirm

`NSStringPluralRuleType`

was generated correctly.Recorded honestly, on the principle of not manufacturing work:

`ScrollView`

behaviour)`.large`

navigation title layout — the same as Apple's own apps`ViewThatFits`

judges on ideal width.Reading the code found zero of the eleven.

Separately from this, I build a desktop AI agent called [Wisp](https://rengaworks.gumroad.com/l/wisp?utm_source=devto&utm_medium=article&utm_campaign=xxxl-broke-japanese-worse).

It stands on your desktop, answers when you talk to it, and runs commands when you ask — always showing you what it's about to do first.
