Write the store copy ahead of the release, and translate the app again - #593
Merged
Conversation
Every listing but the English one in this repository was a translation of an older, shorter English listing: six of the fifteen were around 1700 characters against the 3500 the console serves, and the Japanese and Chinese ones under 1000. The console has had a full translation of the current English in all fifteen locales for some time; none of it was ever written down here. The English had drifted too, by one line: LibreOffice, OpenOffice and Libre Office are no longer named in the list of office suites that use the format. Nothing is reworded here. This is what play serves today, so that the next commit is a diff of what changes rather than of what was already true. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
The listing claimed two things that stopped being true. The app has no file
browser of its own since scoped storage - documents come through Android's own
picker - and ads have not been removable from a menu since there stopped being
a menu; that is a row in the settings on the landing screen now. Both are
corrected in all fifteen languages, and each listing now says plainly that a
document is opened on the device and never uploaded, which is the thing the
worst-rated review on the store says the app does.
fastlane/metadata/android is what pro and lite share. fastlane/metadata-pro and
-lite hold the rest, read over it. Two things differ: the title, and the
sentences about advertising, which pro has been carrying in every locale
without linking an ad SDK. That one sentence is a ${ads} in the shared
description rather than a second copy of it.
The title is no longer translated. Play has been serving OpenDocument Reader
Pro in all fifteen storefronts already, and the titles checked in here were
never what play showed: eleven of the fifteen were 36 to 49 characters, written
when the limit was 50 rather than today's 30, so supply would have refused
every one of them. LibreOffice and the local words live in the short
description, which play indexes just as well.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
The "What's new" text was typed into the play console at promotion and never translated: only en-US was kept here, and play fell back to the listing's own language everywhere else. scripts/store-copy.py now writes it from the changelog, one agent per language and a second one of that language reading each draft back, and scripts/store-listing.py checks a version has copy in every locale and stages it for supply. Play takes 500 characters where the App Store takes 4000, so the limit is the interesting part. 4.15.0's English was written at 497 and no translation of it fits - German came back a fifth longer and French a quarter. The English is rewritten inside a 400 character budget, the check is hard at 500, and both prompts say so; the longest of the fifteen is French at 491. OpenDocument.ios has the same two scripts against App Store Connect's shape. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
Crowdin wrote values-de-rDE beside the older values-de and the two drifted, so which strings a user saw depended on the region their phone was set to. Korean was the sharp end of it: all 43 strings were in values-ko-rKR and values-ko was empty, so a Korean speaker outside Korea got an entirely English app. Nothing here differs by region, so the region qualifier is gone and values-de answers for every German-speaking one. Thirty of the sixty-six directories held nothing but <resources></resources> - fifteen languages that shipped a file and no words. They are removed. Estonian and Swedish are kept though they were two of them, because the play listing sells the app in both. crowdin.yml goes with them. Nothing has come back from it since September 2023, which is before the redesign that added most of what is missing, and a source of translations that no longer delivers is worse than none: it says the gap is somebody else's to close. app_title is marked untranslatable rather than left to fall back, for the same reason the store title is not translated. crouton_remove_ads was still offering to remove ads "via the menu"; it is a snackbar whose OK button makes the purchase, and there has been no menu since the options menu went. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
No language had more than 44 of the 75 strings, and most had far fewer: German was missing 42 of them - the whole landing screen, every document action, all of the house ad, the unsaved-changes dialog, and OK and Cancel. Catalan had 15. Whatever was added after September 2023, when the last translation arrived, was English in every language, and that is most of what the app now shows. All nineteen languages are complete. Estonian and Swedish are translated for the first time, though the store has been selling the app in both for years. scripts/translate-app.py writes them, one agent per language and a second one of that language reading the whole file back - not only the new strings, since a string translated three years ago beside one translated today is where the two stop agreeing on what "document" is called. values/strings.xml is the source: the keys it has, in its order, and nothing else, so a string that leaves it leaves every translation with it. The values come back as plain text and the escaping is put on here, so an agent cannot write an apostrophe that stops the resources compiling. OpenDocument.ios did the same for its .strings files. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
supply was told to skip metadata, changelogs and images, so nothing under fastlane/metadata ever reached play - the console was the only copy of the listing and this repository held an older one. The release now uploads the listing with the bundle, which is what makes the text checked in here the text the store shows. scripts/store-listing.py stages what goes up rather than supply being pointed at fastlane/metadata directly: the two apps say almost the same thing, and the places they differ have to be read over the shared text before either is sent. The release run stages it a second time before it builds, so a locale missing its notes stops the run in seconds. listingPro and listingLite upload the listing without a bundle, for a typo or a locale that came out wrong - play refuses a version code twice, so repairing the words should not need a version to carry them. Images stay skipped. The four screenshots checked in here predate the 4.14 redesign, and uploading them would put the old ones back over the current. **The first run overwrites what the console says** for the title, both descriptions and the release notes, on both apps, in all fifteen locales. That is the point, but it is worth knowing before the run rather than after. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
The README pointed at a Crowdin project that has not delivered since 2023. It now says what writes each of the three - the app's strings, the listing, the release notes - and that a pull request correcting any of them is welcome. CHANGELOG.md said its sections were pasted into the Play Console at promotion. They are what the store copy is written from now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2780b05b62
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
`locales()` read the tree and believed it: a directory deleted, or one that lost its full_description.txt, simply left the set, and the pre-build check passed with fourteen locales instead of fifteen. That storefront would then keep the listing of whatever version last reached it, and nothing would say so. The fifteen are written down in `LOCALES` now, with the language each is written in, and the tree is checked against the list both ways round - a locale gone missing fails the release, and one beside them the list does not name fails it too rather than be translated and never uploaded. That is the same table `store-copy.py` kept as `LANGUAGES` to name the language it hands the translator, so it now reads it from here. One list, in the place the release consults. Staging had the same silence one file down: a `title.txt`, `short_description.txt` or `full_description.txt` that no layer held was left out of the staged tree, and supply uploads what it is handed and leaves the rest of the console alone - so the result is not a blank listing but the old one still standing, which is the arrangement this branch replaces. Those three are required per locale now and name the three directories they were looked for in; `video.txt` stays optional, since a listing without a trailer is a listing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Q9iTwwgnYcYkC9jEUvUEgN
andiwand
added a commit
to opendocument-app/OpenDocument.ios
that referenced
this pull request
Aug 16, 2026
Both were counted up from what was on disk. A locale that lost its directory, or only its description, simply stopped being a locale: the check passed with ten, and that storefront kept whatever the console said. The eleven are written down now. Same for the listing itself. A field found nowhere was left out of what is staged, and App Store Connect reads a field it was not given as "leave this be" - so the run meant to replace the old words would have kept them instead. The name is the easiest to lose, since each app says it in one file for all eleven languages. Both come from the review of the Android half, opendocument-app/OpenDocument.droid#593. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Xryx81PvamT674wzzQujjg
andiwand
added a commit
that referenced
this pull request
Aug 16, 2026
andiwand
added a commit
to opendocument-app/OpenDocument.ios
that referenced
this pull request
Aug 16, 2026
#162) * Write the store copy before the release, not during it The "What's New" text was typed into App Store Connect at submission and translated by hand. scripts/store-copy.py now writes it from the changelog, one agent per language and a second one reading each draft back, and the release run uploads it and refuses a version any locale is missing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Translate the app again Every language but English showed English for the onboarding buttons, the privacy screen and the banner - nineteen of the forty-four strings. Danish, Catalan, Turkish and Czech showed it for most of the rest, and the Chinese introduction named a different app. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Translate the store listing from what it says now Every listing but the English one was a translation of an older, shorter listing: six of the nine features and the whole list of formats the app opens were missing, and so were the notes about ads and where to send feedback. The Swedish one called an office suite office supplies. The 1.41 notes say PDFs fit the screen and take a password like everything else, rather than which engine draws them. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Name the app in its own language, and let the release write the listing Eight of the ten storefronts showed an English name and subtitle, both saying the app only reads. Every one showed the same English keywords, so nobody searching in their own language found it. Each listing now leads with LibreOffice, says somewhere that it edits, and spends its keywords on words people there actually type. The release run uploads all of it, not just the release notes, so the store says what is written here. Lite still takes the notes alone: a name has to be unique in the store, and only Pro's listing is checked in. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Say the same about both apps, except where they differ fastlane/metadata is what Pro and Lite share. fastlane/metadata-pro and -lite hold the rest, read over it. Two things differ: the name, because the store wants a unique one, and the sentence about ads, which Pro has been carrying for years without showing any. That one sentence is a ${ads} in the shared description rather than a second copy of it. The name is no longer translated. OpenDocument is the format's own name, and the App Store indexes the subtitle just as well, so the local words and LibreOffice moved down there. Nothing sells the app as an editor now. It edits text, but not well enough to promise. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Fail the release when a language or a field goes missing Both were counted up from what was on disk. A locale that lost its directory, or only its description, simply stopped being a locale: the check passed with ten, and that storefront kept whatever the console said. The eleven are written down now. Same for the listing itself. A field found nowhere was left out of what is staged, and App Store Connect reads a field it was not given as "leave this be" - so the run meant to replace the old words would have kept them instead. The name is the easiest to lose, since each app says it in one file for all eleven languages. Both come from the review of the Android half, opendocument-app/OpenDocument.droid#593. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The Android half of OpenDocument.ios#162. Same two problems, and one that repo did not have.
What was different here
The listing in this repository was behind the Play Console, not ahead of it. Play has been serving a full translation of the current English in all fifteen locales for some time; the copies checked in here were one or two generations older - six of them around 1700 characters against the console's 3500, Japanese and Chinese under 1000. Even the English had drifted by a line.
So
skip_upload_metadatacould not simply be turned off. Doing that would have pushed the old copies over fifteen locales of current translation. The first commit takes the live listing back into the repository unchanged, so the second one is a diff of what changes rather than of what was already true.The store copy
scripts/store-copy.py v4.15.0writes the "What's new" text for every locale before the release, instead of it being typed into the promotion box.The English comes from the
CHANGELOG.mdsection of that version, or fromUnreleasedwhile the heading is still open. Every other locale is translated by an agent of its own, given that locale's own description and the release before it, then read back by a second agent of the same language. Output is checked mechanically and a language that comes back wrong is retried, then named so it can be redone with--locales.Play takes 500 characters where the App Store takes 4000, and that is the whole difference. 4.15.0's English was written at 497 and there is no translation of it that fits - German came back a fifth longer, French a quarter. The English is rewritten inside a 400-character budget, the check is hard at 500, and both prompts say so. The longest of the fifteen is French at 491.
scripts/store-listing.pyowns the layout and stages what supply uploads. The release run checks before it builds, so a missing translation fails in seconds rather than after both bundles are up.The app
No language had more than 44 of the 75 strings. German was missing 42 - the whole landing screen, every document action, all of the house ad, the unsaved-changes dialog, and OK and Cancel. Catalan had 15. Anything added after September 2023 was English everywhere, and that is most of what the app now shows.
Beyond the missing strings:
values-directories held nothing but<resources></resources>values-de-rDEbeside the oldervalues-deand the two drifted, so which strings a user saw depended on their phone's region. All 43 Korean strings were invalues-ko-rKRandvalues-kowas empty, so a Korean speaker outside Korea got an entirely English app.toast_error_genericcrouton_remove_adsstill offered to remove ads "via the menu" - it is a snackbar whose OK button makes the purchase, and there has been no menu since the options menu wentAll nineteen languages are now complete, written by
scripts/translate-app.pyand each read back by a second agent of that language - over the whole file, not only the new strings, since a string translated three years ago beside one translated today is where the two stop agreeing on what "document" is called. Estonian and Swedish are translated for the first time, though the store has sold the app in both for years.crowdin.ymlis gone. Nothing came back from it after September 2023, and a source of translations that no longer delivers is worse than none: it says the gap is somebody else's to close.The listing
Two things it claimed had stopped being true, in all fifteen languages: the app has had no file browser of its own since scoped storage, and ads have not been removable from a menu since there stopped being a menu. Each listing now also says plainly that a document is opened on the device and never uploaded - which is what the worst-rated review on the store says the app does, and it stopped being true of the app when the online loader went.
Title, and the two apps
fastlane/metadata/androidis what both apps share;fastlane/metadata-proand-litehold the rest, read over it. Two things differ.The title. Play has been serving
OpenDocument Reader Proin all fifteen storefronts already, and liteOpenDocument Reader - view ODT. The titles checked in here were never what Play showed, and eleven of the fifteen were 36 to 49 characters - written when the limit was 50 rather than today's 30, so supply would have refused every one of them.Settled rather than guessed, and no longer translated:
OpenDocument Reader ProOpenDocument ReaderOpenDocumentis the format's own name and one name is one app people can pass to each other. Nothing is lost to search - Play indexes the title, the short description and the full description alike, soLibreOfficeand the local words live in the short description, which has 80 characters for them.app_titleinstrings.xmlis marked untranslatable for the same reason.Advertising. Pro links no ad SDK and shows none, but every description said ads were shown, in all fifteen languages, on both apps. The shared description holds
${ads}and each app fills it in from its ownads.txt- lite has fifteen, pro has none, and a fill-in nobody answers leaves nothing behind, the space in front of it included.The listing is uploaded now
The release uploads the listing with the bundle: title, both descriptions and that version's release notes, per app, in fifteen locales.
listingPro/listingLitesend it without a bundle, which is how a typo is fixed - Play refuses a version code twice, so repairing words should not need a version to carry them.Graphics are not uploaded. The four screenshots checked in here predate the 4.14 redesign, and sending them would put the old ones back over the current.
The first run overwrites what the console says for those fields, on both apps, in all fifteen locales. That is the point - the copy is written here now - but it is worth knowing before the run rather than after.
Checked
values-*/strings.xmlparses, holds all 75 keys in source order, none extra, apostrophes escapedspotlessCheck,assembleDebug(all three flavors),lintProDebugandtestProDebugUnitTestpasstitle.txt, and one sentence offull_description.txt${...}survives staging, and no double space is left where one was filled in emptyThe Play Store call itself needs the repository secrets, so the first real release run is its own proof.
🤖 Generated with Claude Code