Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ jobs:
version: ${{ steps.version.outputs.version }}
run: .github/scripts/changelog-section.py --version "$version" > /dev/null

# before the build, so a locale with no release notes costs seconds rather than
# being found once both bundles are already on the store
- name: check the store copy is written in every locale
if: ${{ steps.version.outputs.version != '' }}
env:
version: ${{ steps.version.outputs.version }}
run: python3 scripts/store-listing.py --version "$version"

- name: setup java
uses: actions/setup-java@v5.7.0
with:
Expand Down Expand Up @@ -178,10 +186,18 @@ jobs:
- flavor: lite
lane: uploadLite
steps:
# for the Gemfile and the lanes; the bundles come from the artifact
# for the Gemfile, the lanes and the listing the upload stages
- name: checkout
uses: actions/checkout@v7

# re-resolved rather than carried as a job output, as in the record job below:
# the upload needs it to name the release notes it sends with the bundle
- name: resolve version
id: version
env:
given: ${{ inputs.version }}
run: .github/scripts/resolve-version.py --input "$given" --dry-run "$dry_run"

# back where gradle put them: the Fastfile reads a fixed path under here
- name: fetch the bundles
uses: actions/download-artifact@v8
Expand All @@ -203,10 +219,13 @@ jobs:
ruby-version: '3.4'
bundler-cache: true

# no track: the Fastfile's DEFAULT_TRACK is internal, and wider is a promotion
- name: upload ${{ matrix.flavor }} to play store
# no track: the Fastfile's DEFAULT_TRACK is internal, and wider is a promotion.
# ODR_VERSION rather than a lane argument: the Fastfile falls back to it, and it
# is what tells the staging script which release notes go up with the bundle
- name: upload ${{ matrix.flavor }} and its listing to play store
env:
ODR_PLAY_JSON_KEY: ${{ runner.temp }}/fastlane_google_play.json
ODR_VERSION: ${{ steps.version.outputs.version }}
run: bundle exec fastlane android ${{ matrix.lane }}

- name: drop credentials
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,6 @@ __pycache__/

# local agent state
.claude/

# staged by scripts/store-listing.py for one upload, then thrown away
fastlane/.listing/
11 changes: 7 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,13 @@ listed here too.
Entries go under `Unreleased` as the change lands, in the same pull request. That
heading is cut to the version when the version is dispatched to the release
workflow, which refuses a version without a section and makes it the body of the
GitHub release. It is not the store copy: Play's "What's new" is written for
users, one file per version code under
`fastlane/metadata/android/en-US/changelogs/`, and pasted into the Play Console
when the release is promoted.
GitHub release.

It is not the store copy, but it is what the store copy is written from: Play's
"What's new" is this section said for the people using the app, one file per
version code per locale under `fastlane/metadata/android/<locale>/changelogs/`,
written by `scripts/store-copy.py` before the release and uploaded by it. Play
takes 500 characters, so not everything here reaches the store.

## 4.15.0

Expand Down
63 changes: 54 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,39 @@ install the new one, uninstall the old one. Nothing carries over and nothing is
carrying - a recent documents list whose uri permissions die with the old package anyway.

## Translations
Please help to translate on the https://crowdin.com/project/opendocument

The app speaks nineteen languages and the Play listing fifteen, and both are written
in this repository.

| | source | written by |
|---|---|---|
| the app | `app/src/main/res/values/strings.xml` | `scripts/translate-app.py` |
| the listing | `fastlane/metadata/android/en-US/` | by hand, then translated |
| the release notes | `CHANGELOG.md` | `scripts/store-copy.py` |

Both scripts run one `claude -p` per language and a second one of the same language
reading the draft back, and both refuse an answer that has lost something - a key, a
paragraph, an address the English kept. Neither uploads: `scripts/store-listing.py`
checks and stages what they write, and the release run sends it. See
`fastlane/metadata/README.md` for how the two apps share one listing.

```sh
scripts/translate-app.py # fill in whatever strings are missing
scripts/store-copy.py v4.15.0 # write the release notes of a version
scripts/store-listing.py --version v4.15.0 # check every locale has them
```

There is one directory per language and no region qualifier: `values-de` answers for
every German-speaking region and nothing here differs by one. A pull request adding a
language adds it to `LANGUAGES` in `scripts/translate-app.py` too, or the next run
refuses to guess what it should be written in. A language the *store* is sold in goes
in `LOCALES` in `scripts/store-listing.py`, which the release checks its directories
against, so a listing that loses one fails rather than ships without it.

This used to be on Crowdin. Nothing came back from it after September 2023 - two years
before the redesign that added most of the app's current strings - so the app shipped
with no language more than 58% translated. Corrections in a pull request are very
welcome; a translated string is a translated string wherever it comes from.

## Setup

Expand Down Expand Up @@ -69,7 +101,7 @@ Nothing triggers it on a tag. It runs as three jobs:
| job | what it does |
|---|---|
| `build` | one gradle run producing all three signed flavors, archived on the run |
| `upload` | one job per play flavor, handing its bundle to fastlane |
| `upload` | one job per play flavor, handing its bundle and listing to fastlane |
| `record` | once both landed: tag the commit, draft the GitHub release |

Lite and Pro always go out together, and nothing chooses one: they are the same app with
Expand All @@ -79,9 +111,19 @@ the `v*` tag names and F-Droid builds.

Internal is the only track it uploads to. Anything wider - closed, open, production -
is a promotion in the Play Console, which moves the same bundle and version code that
was tested onto the wider track instead of uploading a second one, and is where the
release notes get written. It is also where the review that a production release waits
on actually happens, so the workflow finishing is not the same as the release being out.
was tested onto the wider track instead of uploading a second one. It is also where the
review that a production release waits on actually happens, so the workflow finishing is
not the same as the release being out.

The listing goes up with the bundle: the title, both descriptions and the release notes
of that version, in all fifteen locales, for each app. **This overwrites what the Play
Console says**, which is the point - the copy is written here now, not there. The release
notes are no longer typed into the promotion box. Graphics are not uploaded; see
`fastlane/metadata/README.md`.

`fastlane android listingPro` and `listingLite` send the listing without a bundle, which
is how a typo is fixed: Play refuses a version code twice, so repairing the words should
not need a version to carry them.

**If one flavor's upload fails, press "Re-run failed jobs".** Only that upload runs again,
against the bundle already built and signed, and `record` runs behind it. Re-running *all*
Expand All @@ -92,10 +134,13 @@ way out is a new patch version for both flavors.
`dry_run` builds and signs both flavors without uploading either. It is the only run
allowed to go without a version, and the only one leaving neither tag nor draft.

In its first seconds the run also refuses a version that has already gone out and one
with no `CHANGELOG.md` section, which is what the release body is made of.
`.github/scripts/resolve-version.py` and `changelog-section.py` decide both; run either
by hand to see what a dispatch would do.
In its first seconds the run also refuses a version that has already gone out, one with
no `CHANGELOG.md` section - which is what the release body is made of - and one whose
release notes have not been written in every locale, which `scripts/store-copy.py`
writes. All three are checked before the build, so they cost seconds rather than a
version. `.github/scripts/resolve-version.py`, `changelog-section.py` and
`scripts/store-listing.py` decide them; run any of the three by hand to see what a
dispatch would do.

It needs these repository secrets:

Expand Down
4 changes: 0 additions & 4 deletions app/src/main/res/values-af-rZA/strings.xml

This file was deleted.

2 changes: 0 additions & 2 deletions app/src/main/res/values-af/strings.xml

This file was deleted.

4 changes: 0 additions & 4 deletions app/src/main/res/values-ar-rSA/strings.xml

This file was deleted.

2 changes: 0 additions & 2 deletions app/src/main/res/values-ar/strings.xml

This file was deleted.

19 changes: 0 additions & 19 deletions app/src/main/res/values-ca-rES/strings.xml

This file was deleted.

73 changes: 66 additions & 7 deletions app/src/main/res/values-ca/strings.xml
Original file line number Diff line number Diff line change
@@ -1,19 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="toast_error_generic">Hi ha hagut un problema. No s\'ha pogut obrir el fitxer.</string>
<string name="toast_error_find_file">No s\'ha pogut trobar el fitxer. És possible que ja no existeixi?</string>
<string name="toast_error_out_of_memory">S\'ha esgotat la memòria del telèfon. Massa imatges o fitxer massa gran.</string>
<string name="toast_error_password_protected">El document està protegit per contrasenya</string>
<string name="dialog_broken_file_title">No s\'ha pogut obrir aquest fitxer</string>
<string name="dialog_broken_file">És possible que el fitxer estigui malmès o que hi hagi hagut un problema per part nostra. Si creieu que el fitxer és correcte, escriviu-nos a support@opendocument.app</string>
<string name="toast_error_find_file">No s\'ha pogut trobar el fitxer. Potser ja no existeix?</string>
<string name="toast_error_illegal_file_reopen">Format de fitxer no compatible. Proveu d\'obrir-lo amb una altra aplicació.</string>
<string name="toast_hint_unsupported_file">No us convenç com es mostra el fitxer? Obriu-lo amb una altra aplicació.</string>
<string name="toast_error_save_nofile">No s\'ha triat cap ubicació per desar el fitxer.</string>
<string name="toast_error_save_failed">No s\'ha pogut desar el fitxer. Contacteu amb support@opendocument.app</string>
<string name="toast_error_out_of_memory">S\'ha esgotat la memòria del dispositiu. Massa imatges o fitxer massa gran.</string>
<string name="toast_error_password_protected">Aquest document està protegit amb contrasenya</string>
<string name="dialog_loading_title">S\'està carregant…</string>
<string name="menu_search">Cerca</string>
<string name="dialog_generic_loading_message">Espereu, això pot trigar uns quants minuts.</string>
<string name="menu_search">Cerca al document</string>
<string name="menu_open_with">Obre amb...</string>
<string name="menu_share">Comparteix el document</string>
<string name="menu_edit">Edita el document</string>
<string name="menu_remove_ads">Suprimeix els anuncis</string>
<string name="menu_privacy_options">Configuració de privadesa dels anuncis</string>
<string name="house_ad_support_headline">Doneu suport a OpenDocument Reader</string>
<string name="house_ad_support_headline_short">Ajudeu-nos</string>
<string name="house_ad_support_subline">Obteniu Pro — mai més anuncis</string>
<string name="house_ad_support_subline_wide">És de codi obert i es finança amb anuncis. Pro elimina la publicitat.</string>
<string name="house_ad_ad_free_headline">Llegiu sense anuncis</string>
<string name="house_ad_ad_free_subline">ODR Pro — una compra única</string>
<string name="house_ad_ad_free_subline_wide">ODR Pro és el mateix lector, sense la publicitat.</string>
<string name="house_ad_open_source_headline">Codi obert, sempre gratuït</string>
<string name="house_ad_open_source_headline_short">Codi obert</string>
<string name="house_ad_open_source_subline">Pro el finança — i treu els anuncis</string>
<string name="house_ad_open_source_subline_wide">Comprar Pro finança la feina i elimina la publicitat.</string>
<string name="house_ad_cta_go_pro">Passa a Pro</string>
<string name="house_ad_cta_get_pro">Obtén Pro</string>
<string name="menu_fullscreen">Mode de pantalla completa</string>
<string name="menu_cloud_print">Google Cloud Print</string>
<string name="menu_tts">Text-a-paraula</string>
<string name="menu_cloud_print">Imprimeix el document</string>
<string name="menu_tts">Text a veu</string>
<string name="crouton_error_open_app">No s\'ha pogut obrir l\'aplicació seleccionada.</string>
<string name="action_find_previous">Anterior</string>
<string name="action_find_next">Següent</string>
<string name="action_find_on_page">Cerca a la pàgina</string>
<string name="action_tts_play">Reprodueix</string>
<string name="action_tts_pause">Pausa</string>
<string name="action_tts_next">Següent</string>
<string name="action_tts_previous">Anterior</string>
<string name="action_edit_save">Desa</string>
<string name="action_contact">Contacta</string>
<string name="action_edit_banner">Editeu el document a sota i premeu Desa</string>
<string name="landing_intro_open_all">De manera predeterminada, aquesta aplicació només s\'ofereix per obrir documents. Si una altra aplicació, com ara «Samsung My Files», no us deixa obrir un document aquí, activeu aquesta opció perquè s\'ofereixi per a qualsevol tipus de fitxer.</string>
<string name="landing_intro_view">OpenDocument Reader us permet veure documents desats en format OpenDocument (.odt, .ods, .odp i .odg) allà on sigueu.</string>
<string name="landing_intro_search">Amb OpenDocument Reader podeu llegir i cercar dins dels vostres documents en un tres i no res.</string>
<string name="landing_intro_edit">Us queda una última errada per corregir abans de la gran presentació? Ara també admet modificacions!</string>
<string name="landing_section_recent">Recents</string>
<string name="landing_section_intro">Què podeu fer</string>
<string name="landing_section_settings">Configuració</string>
<string name="landing_pagination_title">Mostra les vores de la pàgina</string>
<string name="landing_pagination_body">Conserva els marges laterals d\'una pàgina impresa en lloc d\'omplir la pantalla.</string>
<string name="landing_catch_all_title">Ofereix obrir qualsevol fitxer</string>
<string name="landing_sponsor">Doneu-nos suport a GitHub</string>
<string name="landing_recent_removed">S\'ha suprimit dels recents</string>
<string name="landing_undo">Desfés</string>
<string name="landing_open_file">Obre un fitxer</string>
<string name="document_actions_more">Més accions</string>
<string name="document_actions_close">Tanca les accions</string>
<string name="tts_status_reading">S\'està llegint…</string>
<string name="tts_status_initializing">S\'està iniciant la veu…</string>
<string name="tts_status_ready">A punt!</string>
<string name="tts_status_failed">La lectura en veu alta ha fallat.</string>
<string name="tts_status_paused">En pausa.</string>
<string name="tts_status_finished">Ha acabat.</string>
<string name="toast_edit_status_saved">S\'ha desat el document.</string>
<string name="crouton_printing">S\'està imprimint…</string>
<string name="crouton_remove_ads">Necessiteu més espai per llegir? Toqueu D\'acord per suprimir els anuncis de franc.</string>
<string name="reopen_chooser_title">Obriu-lo amb una altra aplicació instal·lada al dispositiu:</string>
<string name="ok">D\'acord</string>
<string name="cancel">Cancel·la</string>
<string name="alert_unsaved_changes">Canvis sense desar</string>
<string name="alert_save_now">Voleu desar-los ara?</string>
<string name="alert_discard_changes">Descarta</string>
</resources>
25 changes: 0 additions & 25 deletions app/src/main/res/values-cs-rCZ/strings.xml

This file was deleted.

Loading
Loading