From f166a165ff3380ec2b80be980cd3c8034eecf2ec Mon Sep 17 00:00:00 2001
From: James Rich <2199651+jamesarich@users.noreply.github.com>
Date: Fri, 18 Sep 2026 18:21:19 -0700
Subject: [PATCH] fix(l10n): give Play the locale codes it actually accepts
(#7225)
---
.github/workflows/pull-request.yml | 5 +
.github/workflows/scheduled-updates.yml | 4 +
crowdin.yml | 36 +++++
.../{ar-SA => ar}/changelogs/default.txt | 0
.../{ar-SA => ar}/full_description.txt | 0
.../{ar-SA => ar}/short_description.txt | 0
.../metadata/android/{ar-SA => ar}/title.txt | 0
.../{be-BY => be}/changelogs/default.txt | 0
.../{be-BY => be}/full_description.txt | 0
.../{be-BY => be}/short_description.txt | 0
.../metadata/android/{be-BY => be}/title.txt | 0
.../{bg-BG => bg}/changelogs/default.txt | 0
.../{bg-BG => bg}/full_description.txt | 0
.../{bg-BG => bg}/short_description.txt | 0
.../metadata/android/{bg-BG => bg}/title.txt | 0
.../{ca-ES => ca}/changelogs/default.txt | 0
.../{ca-ES => ca}/full_description.txt | 0
.../{ca-ES => ca}/short_description.txt | 0
.../metadata/android/{ca-ES => ca}/title.txt | 0
.../{et-EE => et}/changelogs/default.txt | 0
.../{et-EE => et}/full_description.txt | 0
.../{et-EE => et}/short_description.txt | 0
.../metadata/android/{et-EE => et}/title.txt | 0
.../{ga-IE => hr}/changelogs/default.txt | 0
.../{hr-HR => hr}/full_description.txt | 0
.../{ga-IE => hr}/short_description.txt | 0
.../metadata/android/{ga-IE => hr}/title.txt | 0
.../{he-IL => iw-IL}/changelogs/default.txt | 0
.../{ga-IE => iw-IL}/full_description.txt | 0
.../{he-IL => iw-IL}/short_description.txt | 0
.../android/{he-IL => iw-IL}/title.txt | 0
.../{hr-HR => lt}/changelogs/default.txt | 0
.../{he-IL => lt}/full_description.txt | 0
.../{hr-HR => lt}/short_description.txt | 0
.../metadata/android/{hr-HR => lt}/title.txt | 0
.../{ro-RO => ro}/changelogs/default.txt | 0
.../{ht-HT => ro}/full_description.txt | 0
.../{ro-RO => ro}/short_description.txt | 0
.../metadata/android/{ht-HT => ro}/title.txt | 0
.../{ht-HT => sk}/changelogs/default.txt | 0
.../{sk-SK => sk}/full_description.txt | 0
.../{sk-SK => sk}/short_description.txt | 0
.../metadata/android/{lt-LT => sk}/title.txt | 0
.../{lt-LT => sl}/changelogs/default.txt | 0
.../{lt-LT => sl}/full_description.txt | 0
.../{ht-HT => sl}/short_description.txt | 0
.../metadata/android/{ro-RO => sl}/title.txt | 0
.../android/sq-AL/changelogs/default.txt | 1 -
.../android/sq-AL/full_description.txt | 21 ---
.../android/sq-AL/short_description.txt | 1 -
.../{sk-SK => sq}/changelogs/default.txt | 0
.../{ro-RO => sq}/full_description.txt | 0
.../{lt-LT => sq}/short_description.txt | 0
.../metadata/android/{sk-SK => sq}/title.txt | 0
.../android/sr-Latn/changelogs/default.txt | 1 -
.../android/sr-Latn/full_description.txt | 21 ---
.../android/sr-Latn/short_description.txt | 1 -
fastlane/metadata/android/sr-Latn/title.txt | 1 -
.../{sl-SI => sr}/changelogs/default.txt | 0
.../{sl-SI => sr}/full_description.txt | 0
.../{sl-SI => sr}/short_description.txt | 0
.../metadata/android/{sl-SI => sr}/title.txt | 0
.../android/srp/changelogs/default.txt | 1 -
.../metadata/android/srp/full_description.txt | 21 ---
.../android/srp/short_description.txt | 1 -
fastlane/metadata/android/srp/title.txt | 1 -
fastlane/metadata/android/uk-UA/title.txt | 1 -
.../{uk-UA => uk}/changelogs/default.txt | 0
.../{uk-UA => uk}/full_description.txt | 0
.../{uk-UA => uk}/short_description.txt | 0
.../metadata/android/{sq-AL => uk}/title.txt | 0
scripts/check-play-locales.py | 124 ++++++++++++++++++
72 files changed, 169 insertions(+), 72 deletions(-)
rename fastlane/metadata/android/{ar-SA => ar}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{ar-SA => ar}/full_description.txt (100%)
rename fastlane/metadata/android/{ar-SA => ar}/short_description.txt (100%)
rename fastlane/metadata/android/{ar-SA => ar}/title.txt (100%)
rename fastlane/metadata/android/{be-BY => be}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{be-BY => be}/full_description.txt (100%)
rename fastlane/metadata/android/{be-BY => be}/short_description.txt (100%)
rename fastlane/metadata/android/{be-BY => be}/title.txt (100%)
rename fastlane/metadata/android/{bg-BG => bg}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{bg-BG => bg}/full_description.txt (100%)
rename fastlane/metadata/android/{bg-BG => bg}/short_description.txt (100%)
rename fastlane/metadata/android/{bg-BG => bg}/title.txt (100%)
rename fastlane/metadata/android/{ca-ES => ca}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{ca-ES => ca}/full_description.txt (100%)
rename fastlane/metadata/android/{ca-ES => ca}/short_description.txt (100%)
rename fastlane/metadata/android/{ca-ES => ca}/title.txt (100%)
rename fastlane/metadata/android/{et-EE => et}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{et-EE => et}/full_description.txt (100%)
rename fastlane/metadata/android/{et-EE => et}/short_description.txt (100%)
rename fastlane/metadata/android/{et-EE => et}/title.txt (100%)
rename fastlane/metadata/android/{ga-IE => hr}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{hr-HR => hr}/full_description.txt (100%)
rename fastlane/metadata/android/{ga-IE => hr}/short_description.txt (100%)
rename fastlane/metadata/android/{ga-IE => hr}/title.txt (100%)
rename fastlane/metadata/android/{he-IL => iw-IL}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{ga-IE => iw-IL}/full_description.txt (100%)
rename fastlane/metadata/android/{he-IL => iw-IL}/short_description.txt (100%)
rename fastlane/metadata/android/{he-IL => iw-IL}/title.txt (100%)
rename fastlane/metadata/android/{hr-HR => lt}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{he-IL => lt}/full_description.txt (100%)
rename fastlane/metadata/android/{hr-HR => lt}/short_description.txt (100%)
rename fastlane/metadata/android/{hr-HR => lt}/title.txt (100%)
rename fastlane/metadata/android/{ro-RO => ro}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{ht-HT => ro}/full_description.txt (100%)
rename fastlane/metadata/android/{ro-RO => ro}/short_description.txt (100%)
rename fastlane/metadata/android/{ht-HT => ro}/title.txt (100%)
rename fastlane/metadata/android/{ht-HT => sk}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{sk-SK => sk}/full_description.txt (100%)
rename fastlane/metadata/android/{sk-SK => sk}/short_description.txt (100%)
rename fastlane/metadata/android/{lt-LT => sk}/title.txt (100%)
rename fastlane/metadata/android/{lt-LT => sl}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{lt-LT => sl}/full_description.txt (100%)
rename fastlane/metadata/android/{ht-HT => sl}/short_description.txt (100%)
rename fastlane/metadata/android/{ro-RO => sl}/title.txt (100%)
delete mode 100644 fastlane/metadata/android/sq-AL/changelogs/default.txt
delete mode 100644 fastlane/metadata/android/sq-AL/full_description.txt
delete mode 100644 fastlane/metadata/android/sq-AL/short_description.txt
rename fastlane/metadata/android/{sk-SK => sq}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{ro-RO => sq}/full_description.txt (100%)
rename fastlane/metadata/android/{lt-LT => sq}/short_description.txt (100%)
rename fastlane/metadata/android/{sk-SK => sq}/title.txt (100%)
delete mode 100644 fastlane/metadata/android/sr-Latn/changelogs/default.txt
delete mode 100644 fastlane/metadata/android/sr-Latn/full_description.txt
delete mode 100644 fastlane/metadata/android/sr-Latn/short_description.txt
delete mode 100644 fastlane/metadata/android/sr-Latn/title.txt
rename fastlane/metadata/android/{sl-SI => sr}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{sl-SI => sr}/full_description.txt (100%)
rename fastlane/metadata/android/{sl-SI => sr}/short_description.txt (100%)
rename fastlane/metadata/android/{sl-SI => sr}/title.txt (100%)
delete mode 100644 fastlane/metadata/android/srp/changelogs/default.txt
delete mode 100644 fastlane/metadata/android/srp/full_description.txt
delete mode 100644 fastlane/metadata/android/srp/short_description.txt
delete mode 100644 fastlane/metadata/android/srp/title.txt
delete mode 100644 fastlane/metadata/android/uk-UA/title.txt
rename fastlane/metadata/android/{uk-UA => uk}/changelogs/default.txt (100%)
rename fastlane/metadata/android/{uk-UA => uk}/full_description.txt (100%)
rename fastlane/metadata/android/{uk-UA => uk}/short_description.txt (100%)
rename fastlane/metadata/android/{sq-AL => uk}/title.txt (100%)
create mode 100755 scripts/check-play-locales.py
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index cec33ee66d..1e137eb8c0 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -305,6 +305,11 @@ jobs:
run: ./scripts/verify-abi-parity-selftest.sh
- name: Validate store listing metadata lengths
run: python3 scripts/check-metadata-length.py
+ # supply uploads every locale directory it finds and neither it nor the Crowdin CLI
+ # validates the names, so an unmapped code is only rejected by the Play API, partway
+ # through an upload. Catch it here instead.
+ - name: Validate store listing locale codes
+ run: python3 scripts/check-play-locales.py
# Compose Multiplatform does not strip Android-style \" / \' escapes, so a
# backslash written before a quote renders literally in the UI (PR #6357).
# Guards the English source strings; locale mirrors are cleaned upstream by
diff --git a/.github/workflows/scheduled-updates.yml b/.github/workflows/scheduled-updates.yml
index 96efada32a..edf6f0ea47 100644
--- a/.github/workflows/scheduled-updates.yml
+++ b/.github/workflows/scheduled-updates.yml
@@ -294,6 +294,10 @@ jobs:
continue-on-error: true
run: python3 scripts/check-metadata-length.py
+ - name: Check store locale codes
+ continue-on-error: true
+ run: python3 scripts/check-play-locales.py
+
- name: Build PR body
id: pr_body
env:
diff --git a/crowdin.yml b/crowdin.yml
index 974a9c4ca3..21d692ee8c 100644
--- a/crowdin.yml
+++ b/crowdin.yml
@@ -10,10 +10,46 @@ files:
escape_quotes: 0
escape_special_characters: 0
type: android
+ # Crowdin's %locale% is not Google Play's language set: it renders regions Play rejects
+ # (ar-SA), `srp` for Serbian, and the modern Hebrew code where Play wants the legacy one.
+ # Nothing validates this - supply uploads every directory it finds and fastlane documents
+ # no behaviour for unknown ones - so a bad code is rejected by the Play API mid-upload,
+ # after earlier locales have already been written.
- source: /fastlane/metadata/android/en-US/*.txt
translation: /fastlane/metadata/android/%locale%/%original_file_name%
+ languages_mapping: &play_locales
+ locale:
+ # Keys are Crowdin language ids, not the locale %locale% renders. Play takes the
+ # bare language for these; %locale% would render a region it rejects.
+ ar: ar
+ be: be
+ bg: bg
+ ca: ca
+ et: et
+ hr: hr
+ lt: lt
+ ro: ro
+ sk: sk
+ sl: sl
+ sq: sq
+ uk: uk
+ # Play still uses the pre-1989 ISO code for Hebrew; %locale% renders he-IL.
+ he: iw-IL
+ # Crowdin renders Serbian as `srp`, which Play does not accept in any form.
+ sr: sr
+ # Play publishes no slot for these. Irish and Haitian Creole are absent from its
+ # supported-languages list entirely, and it lists Serbian only as `sr` with no script
+ # variant - mapping sr-Latn there too would point two languages at one directory and
+ # silently lose whichever wrote first. They keep translating the app's own strings;
+ # only the store listing is out of reach.
+ excluded_target_languages: &play_unsupported
+ - ga
+ - ht
+ - sr-Latn
- source: /fastlane/metadata/android/en-US/changelogs/default.txt
translation: /fastlane/metadata/android/%locale%/changelogs/%original_file_name%
+ languages_mapping: *play_locales
+ excluded_target_languages: *play_unsupported
# In-app docs — user guide only (developer guide is English-only)
# English sources live under docs/en/; translations land at docs/{android_code}/
# Uses %android_code% to output Android/CMP qualifier format directly (pt-rBR, zh-rCN, fr)
diff --git a/fastlane/metadata/android/ar-SA/changelogs/default.txt b/fastlane/metadata/android/ar/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/ar-SA/changelogs/default.txt
rename to fastlane/metadata/android/ar/changelogs/default.txt
diff --git a/fastlane/metadata/android/ar-SA/full_description.txt b/fastlane/metadata/android/ar/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/ar-SA/full_description.txt
rename to fastlane/metadata/android/ar/full_description.txt
diff --git a/fastlane/metadata/android/ar-SA/short_description.txt b/fastlane/metadata/android/ar/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/ar-SA/short_description.txt
rename to fastlane/metadata/android/ar/short_description.txt
diff --git a/fastlane/metadata/android/ar-SA/title.txt b/fastlane/metadata/android/ar/title.txt
similarity index 100%
rename from fastlane/metadata/android/ar-SA/title.txt
rename to fastlane/metadata/android/ar/title.txt
diff --git a/fastlane/metadata/android/be-BY/changelogs/default.txt b/fastlane/metadata/android/be/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/be-BY/changelogs/default.txt
rename to fastlane/metadata/android/be/changelogs/default.txt
diff --git a/fastlane/metadata/android/be-BY/full_description.txt b/fastlane/metadata/android/be/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/be-BY/full_description.txt
rename to fastlane/metadata/android/be/full_description.txt
diff --git a/fastlane/metadata/android/be-BY/short_description.txt b/fastlane/metadata/android/be/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/be-BY/short_description.txt
rename to fastlane/metadata/android/be/short_description.txt
diff --git a/fastlane/metadata/android/be-BY/title.txt b/fastlane/metadata/android/be/title.txt
similarity index 100%
rename from fastlane/metadata/android/be-BY/title.txt
rename to fastlane/metadata/android/be/title.txt
diff --git a/fastlane/metadata/android/bg-BG/changelogs/default.txt b/fastlane/metadata/android/bg/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/bg-BG/changelogs/default.txt
rename to fastlane/metadata/android/bg/changelogs/default.txt
diff --git a/fastlane/metadata/android/bg-BG/full_description.txt b/fastlane/metadata/android/bg/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/bg-BG/full_description.txt
rename to fastlane/metadata/android/bg/full_description.txt
diff --git a/fastlane/metadata/android/bg-BG/short_description.txt b/fastlane/metadata/android/bg/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/bg-BG/short_description.txt
rename to fastlane/metadata/android/bg/short_description.txt
diff --git a/fastlane/metadata/android/bg-BG/title.txt b/fastlane/metadata/android/bg/title.txt
similarity index 100%
rename from fastlane/metadata/android/bg-BG/title.txt
rename to fastlane/metadata/android/bg/title.txt
diff --git a/fastlane/metadata/android/ca-ES/changelogs/default.txt b/fastlane/metadata/android/ca/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/ca-ES/changelogs/default.txt
rename to fastlane/metadata/android/ca/changelogs/default.txt
diff --git a/fastlane/metadata/android/ca-ES/full_description.txt b/fastlane/metadata/android/ca/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/ca-ES/full_description.txt
rename to fastlane/metadata/android/ca/full_description.txt
diff --git a/fastlane/metadata/android/ca-ES/short_description.txt b/fastlane/metadata/android/ca/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/ca-ES/short_description.txt
rename to fastlane/metadata/android/ca/short_description.txt
diff --git a/fastlane/metadata/android/ca-ES/title.txt b/fastlane/metadata/android/ca/title.txt
similarity index 100%
rename from fastlane/metadata/android/ca-ES/title.txt
rename to fastlane/metadata/android/ca/title.txt
diff --git a/fastlane/metadata/android/et-EE/changelogs/default.txt b/fastlane/metadata/android/et/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/et-EE/changelogs/default.txt
rename to fastlane/metadata/android/et/changelogs/default.txt
diff --git a/fastlane/metadata/android/et-EE/full_description.txt b/fastlane/metadata/android/et/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/et-EE/full_description.txt
rename to fastlane/metadata/android/et/full_description.txt
diff --git a/fastlane/metadata/android/et-EE/short_description.txt b/fastlane/metadata/android/et/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/et-EE/short_description.txt
rename to fastlane/metadata/android/et/short_description.txt
diff --git a/fastlane/metadata/android/et-EE/title.txt b/fastlane/metadata/android/et/title.txt
similarity index 100%
rename from fastlane/metadata/android/et-EE/title.txt
rename to fastlane/metadata/android/et/title.txt
diff --git a/fastlane/metadata/android/ga-IE/changelogs/default.txt b/fastlane/metadata/android/hr/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/ga-IE/changelogs/default.txt
rename to fastlane/metadata/android/hr/changelogs/default.txt
diff --git a/fastlane/metadata/android/hr-HR/full_description.txt b/fastlane/metadata/android/hr/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/hr-HR/full_description.txt
rename to fastlane/metadata/android/hr/full_description.txt
diff --git a/fastlane/metadata/android/ga-IE/short_description.txt b/fastlane/metadata/android/hr/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/ga-IE/short_description.txt
rename to fastlane/metadata/android/hr/short_description.txt
diff --git a/fastlane/metadata/android/ga-IE/title.txt b/fastlane/metadata/android/hr/title.txt
similarity index 100%
rename from fastlane/metadata/android/ga-IE/title.txt
rename to fastlane/metadata/android/hr/title.txt
diff --git a/fastlane/metadata/android/he-IL/changelogs/default.txt b/fastlane/metadata/android/iw-IL/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/he-IL/changelogs/default.txt
rename to fastlane/metadata/android/iw-IL/changelogs/default.txt
diff --git a/fastlane/metadata/android/ga-IE/full_description.txt b/fastlane/metadata/android/iw-IL/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/ga-IE/full_description.txt
rename to fastlane/metadata/android/iw-IL/full_description.txt
diff --git a/fastlane/metadata/android/he-IL/short_description.txt b/fastlane/metadata/android/iw-IL/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/he-IL/short_description.txt
rename to fastlane/metadata/android/iw-IL/short_description.txt
diff --git a/fastlane/metadata/android/he-IL/title.txt b/fastlane/metadata/android/iw-IL/title.txt
similarity index 100%
rename from fastlane/metadata/android/he-IL/title.txt
rename to fastlane/metadata/android/iw-IL/title.txt
diff --git a/fastlane/metadata/android/hr-HR/changelogs/default.txt b/fastlane/metadata/android/lt/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/hr-HR/changelogs/default.txt
rename to fastlane/metadata/android/lt/changelogs/default.txt
diff --git a/fastlane/metadata/android/he-IL/full_description.txt b/fastlane/metadata/android/lt/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/he-IL/full_description.txt
rename to fastlane/metadata/android/lt/full_description.txt
diff --git a/fastlane/metadata/android/hr-HR/short_description.txt b/fastlane/metadata/android/lt/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/hr-HR/short_description.txt
rename to fastlane/metadata/android/lt/short_description.txt
diff --git a/fastlane/metadata/android/hr-HR/title.txt b/fastlane/metadata/android/lt/title.txt
similarity index 100%
rename from fastlane/metadata/android/hr-HR/title.txt
rename to fastlane/metadata/android/lt/title.txt
diff --git a/fastlane/metadata/android/ro-RO/changelogs/default.txt b/fastlane/metadata/android/ro/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/ro-RO/changelogs/default.txt
rename to fastlane/metadata/android/ro/changelogs/default.txt
diff --git a/fastlane/metadata/android/ht-HT/full_description.txt b/fastlane/metadata/android/ro/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/ht-HT/full_description.txt
rename to fastlane/metadata/android/ro/full_description.txt
diff --git a/fastlane/metadata/android/ro-RO/short_description.txt b/fastlane/metadata/android/ro/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/ro-RO/short_description.txt
rename to fastlane/metadata/android/ro/short_description.txt
diff --git a/fastlane/metadata/android/ht-HT/title.txt b/fastlane/metadata/android/ro/title.txt
similarity index 100%
rename from fastlane/metadata/android/ht-HT/title.txt
rename to fastlane/metadata/android/ro/title.txt
diff --git a/fastlane/metadata/android/ht-HT/changelogs/default.txt b/fastlane/metadata/android/sk/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/ht-HT/changelogs/default.txt
rename to fastlane/metadata/android/sk/changelogs/default.txt
diff --git a/fastlane/metadata/android/sk-SK/full_description.txt b/fastlane/metadata/android/sk/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/sk-SK/full_description.txt
rename to fastlane/metadata/android/sk/full_description.txt
diff --git a/fastlane/metadata/android/sk-SK/short_description.txt b/fastlane/metadata/android/sk/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/sk-SK/short_description.txt
rename to fastlane/metadata/android/sk/short_description.txt
diff --git a/fastlane/metadata/android/lt-LT/title.txt b/fastlane/metadata/android/sk/title.txt
similarity index 100%
rename from fastlane/metadata/android/lt-LT/title.txt
rename to fastlane/metadata/android/sk/title.txt
diff --git a/fastlane/metadata/android/lt-LT/changelogs/default.txt b/fastlane/metadata/android/sl/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/lt-LT/changelogs/default.txt
rename to fastlane/metadata/android/sl/changelogs/default.txt
diff --git a/fastlane/metadata/android/lt-LT/full_description.txt b/fastlane/metadata/android/sl/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/lt-LT/full_description.txt
rename to fastlane/metadata/android/sl/full_description.txt
diff --git a/fastlane/metadata/android/ht-HT/short_description.txt b/fastlane/metadata/android/sl/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/ht-HT/short_description.txt
rename to fastlane/metadata/android/sl/short_description.txt
diff --git a/fastlane/metadata/android/ro-RO/title.txt b/fastlane/metadata/android/sl/title.txt
similarity index 100%
rename from fastlane/metadata/android/ro-RO/title.txt
rename to fastlane/metadata/android/sl/title.txt
diff --git a/fastlane/metadata/android/sq-AL/changelogs/default.txt b/fastlane/metadata/android/sq-AL/changelogs/default.txt
deleted file mode 100644
index 0553de284f..0000000000
--- a/fastlane/metadata/android/sq-AL/changelogs/default.txt
+++ /dev/null
@@ -1 +0,0 @@
-For detailed release notes, please visit: https://github.com/meshtastic/Meshtastic-Android/releases/
\ No newline at end of file
diff --git a/fastlane/metadata/android/sq-AL/full_description.txt b/fastlane/metadata/android/sq-AL/full_description.txt
deleted file mode 100644
index 4ade9c5360..0000000000
--- a/fastlane/metadata/android/sq-AL/full_description.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Meshtastic is a tool for using Android devices with open-source, off-grid mesh radios. This app is the main client for the Meshtastic project, allowing you to manage your mesh devices and communicate with other users.
-
-For more information about the Meshtastic project, please visit our website: meshtastic.org. The firmware that runs on the radio devices is a separate open-source project, which you can find here: https://github.com/meshtastic/Meshtastic-device.
-
-Community and Support
-
-This project is currently in beta. We would love to hear from you! If you have questions, feedback, or encounter any problems, please join our friendly and active community:
-
-• Discussion Forum: https://github.com/orgs/meshtastic/discussions
-• Discord: https://discord.gg/meshtastic
-• Report an Issue: https://github.com/meshtastic/Meshtastic-Android/issues
-
-Documentation
-
-To learn more about the features and capabilities of this app and Meshtastic, please view our official documentation:
-View Documentation
-
-Translations
-
-You can help translate the app into your native language using Crowdin:
-https://crowdin.meshtastic.org/android
diff --git a/fastlane/metadata/android/sq-AL/short_description.txt b/fastlane/metadata/android/sq-AL/short_description.txt
deleted file mode 100644
index e3f0988dbd..0000000000
--- a/fastlane/metadata/android/sq-AL/short_description.txt
+++ /dev/null
@@ -1 +0,0 @@
-The official app for Meshtastic, an open-source, off-grid, mesh radio.
\ No newline at end of file
diff --git a/fastlane/metadata/android/sk-SK/changelogs/default.txt b/fastlane/metadata/android/sq/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/sk-SK/changelogs/default.txt
rename to fastlane/metadata/android/sq/changelogs/default.txt
diff --git a/fastlane/metadata/android/ro-RO/full_description.txt b/fastlane/metadata/android/sq/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/ro-RO/full_description.txt
rename to fastlane/metadata/android/sq/full_description.txt
diff --git a/fastlane/metadata/android/lt-LT/short_description.txt b/fastlane/metadata/android/sq/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/lt-LT/short_description.txt
rename to fastlane/metadata/android/sq/short_description.txt
diff --git a/fastlane/metadata/android/sk-SK/title.txt b/fastlane/metadata/android/sq/title.txt
similarity index 100%
rename from fastlane/metadata/android/sk-SK/title.txt
rename to fastlane/metadata/android/sq/title.txt
diff --git a/fastlane/metadata/android/sr-Latn/changelogs/default.txt b/fastlane/metadata/android/sr-Latn/changelogs/default.txt
deleted file mode 100644
index 0553de284f..0000000000
--- a/fastlane/metadata/android/sr-Latn/changelogs/default.txt
+++ /dev/null
@@ -1 +0,0 @@
-For detailed release notes, please visit: https://github.com/meshtastic/Meshtastic-Android/releases/
\ No newline at end of file
diff --git a/fastlane/metadata/android/sr-Latn/full_description.txt b/fastlane/metadata/android/sr-Latn/full_description.txt
deleted file mode 100644
index 4ade9c5360..0000000000
--- a/fastlane/metadata/android/sr-Latn/full_description.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Meshtastic is a tool for using Android devices with open-source, off-grid mesh radios. This app is the main client for the Meshtastic project, allowing you to manage your mesh devices and communicate with other users.
-
-For more information about the Meshtastic project, please visit our website: meshtastic.org. The firmware that runs on the radio devices is a separate open-source project, which you can find here: https://github.com/meshtastic/Meshtastic-device.
-
-Community and Support
-
-This project is currently in beta. We would love to hear from you! If you have questions, feedback, or encounter any problems, please join our friendly and active community:
-
-• Discussion Forum: https://github.com/orgs/meshtastic/discussions
-• Discord: https://discord.gg/meshtastic
-• Report an Issue: https://github.com/meshtastic/Meshtastic-Android/issues
-
-Documentation
-
-To learn more about the features and capabilities of this app and Meshtastic, please view our official documentation:
-View Documentation
-
-Translations
-
-You can help translate the app into your native language using Crowdin:
-https://crowdin.meshtastic.org/android
diff --git a/fastlane/metadata/android/sr-Latn/short_description.txt b/fastlane/metadata/android/sr-Latn/short_description.txt
deleted file mode 100644
index e3f0988dbd..0000000000
--- a/fastlane/metadata/android/sr-Latn/short_description.txt
+++ /dev/null
@@ -1 +0,0 @@
-The official app for Meshtastic, an open-source, off-grid, mesh radio.
\ No newline at end of file
diff --git a/fastlane/metadata/android/sr-Latn/title.txt b/fastlane/metadata/android/sr-Latn/title.txt
deleted file mode 100644
index c3ff693533..0000000000
--- a/fastlane/metadata/android/sr-Latn/title.txt
+++ /dev/null
@@ -1 +0,0 @@
-Meshtastic
\ No newline at end of file
diff --git a/fastlane/metadata/android/sl-SI/changelogs/default.txt b/fastlane/metadata/android/sr/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/sl-SI/changelogs/default.txt
rename to fastlane/metadata/android/sr/changelogs/default.txt
diff --git a/fastlane/metadata/android/sl-SI/full_description.txt b/fastlane/metadata/android/sr/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/sl-SI/full_description.txt
rename to fastlane/metadata/android/sr/full_description.txt
diff --git a/fastlane/metadata/android/sl-SI/short_description.txt b/fastlane/metadata/android/sr/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/sl-SI/short_description.txt
rename to fastlane/metadata/android/sr/short_description.txt
diff --git a/fastlane/metadata/android/sl-SI/title.txt b/fastlane/metadata/android/sr/title.txt
similarity index 100%
rename from fastlane/metadata/android/sl-SI/title.txt
rename to fastlane/metadata/android/sr/title.txt
diff --git a/fastlane/metadata/android/srp/changelogs/default.txt b/fastlane/metadata/android/srp/changelogs/default.txt
deleted file mode 100644
index 0553de284f..0000000000
--- a/fastlane/metadata/android/srp/changelogs/default.txt
+++ /dev/null
@@ -1 +0,0 @@
-For detailed release notes, please visit: https://github.com/meshtastic/Meshtastic-Android/releases/
\ No newline at end of file
diff --git a/fastlane/metadata/android/srp/full_description.txt b/fastlane/metadata/android/srp/full_description.txt
deleted file mode 100644
index 4ade9c5360..0000000000
--- a/fastlane/metadata/android/srp/full_description.txt
+++ /dev/null
@@ -1,21 +0,0 @@
-Meshtastic is a tool for using Android devices with open-source, off-grid mesh radios. This app is the main client for the Meshtastic project, allowing you to manage your mesh devices and communicate with other users.
-
-For more information about the Meshtastic project, please visit our website: meshtastic.org. The firmware that runs on the radio devices is a separate open-source project, which you can find here: https://github.com/meshtastic/Meshtastic-device.
-
-Community and Support
-
-This project is currently in beta. We would love to hear from you! If you have questions, feedback, or encounter any problems, please join our friendly and active community:
-
-• Discussion Forum: https://github.com/orgs/meshtastic/discussions
-• Discord: https://discord.gg/meshtastic
-• Report an Issue: https://github.com/meshtastic/Meshtastic-Android/issues
-
-Documentation
-
-To learn more about the features and capabilities of this app and Meshtastic, please view our official documentation:
-View Documentation
-
-Translations
-
-You can help translate the app into your native language using Crowdin:
-https://crowdin.meshtastic.org/android
diff --git a/fastlane/metadata/android/srp/short_description.txt b/fastlane/metadata/android/srp/short_description.txt
deleted file mode 100644
index e3f0988dbd..0000000000
--- a/fastlane/metadata/android/srp/short_description.txt
+++ /dev/null
@@ -1 +0,0 @@
-The official app for Meshtastic, an open-source, off-grid, mesh radio.
\ No newline at end of file
diff --git a/fastlane/metadata/android/srp/title.txt b/fastlane/metadata/android/srp/title.txt
deleted file mode 100644
index c3ff693533..0000000000
--- a/fastlane/metadata/android/srp/title.txt
+++ /dev/null
@@ -1 +0,0 @@
-Meshtastic
\ No newline at end of file
diff --git a/fastlane/metadata/android/uk-UA/title.txt b/fastlane/metadata/android/uk-UA/title.txt
deleted file mode 100644
index c3ff693533..0000000000
--- a/fastlane/metadata/android/uk-UA/title.txt
+++ /dev/null
@@ -1 +0,0 @@
-Meshtastic
\ No newline at end of file
diff --git a/fastlane/metadata/android/uk-UA/changelogs/default.txt b/fastlane/metadata/android/uk/changelogs/default.txt
similarity index 100%
rename from fastlane/metadata/android/uk-UA/changelogs/default.txt
rename to fastlane/metadata/android/uk/changelogs/default.txt
diff --git a/fastlane/metadata/android/uk-UA/full_description.txt b/fastlane/metadata/android/uk/full_description.txt
similarity index 100%
rename from fastlane/metadata/android/uk-UA/full_description.txt
rename to fastlane/metadata/android/uk/full_description.txt
diff --git a/fastlane/metadata/android/uk-UA/short_description.txt b/fastlane/metadata/android/uk/short_description.txt
similarity index 100%
rename from fastlane/metadata/android/uk-UA/short_description.txt
rename to fastlane/metadata/android/uk/short_description.txt
diff --git a/fastlane/metadata/android/sq-AL/title.txt b/fastlane/metadata/android/uk/title.txt
similarity index 100%
rename from fastlane/metadata/android/sq-AL/title.txt
rename to fastlane/metadata/android/uk/title.txt
diff --git a/scripts/check-play-locales.py b/scripts/check-play-locales.py
new file mode 100755
index 0000000000..987ef5637f
--- /dev/null
+++ b/scripts/check-play-locales.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python3
+"""Fail when a fastlane locale directory is not a language Google Play accepts.
+
+Nothing else checks this. Crowdin's locale placeholder renders Crowdin's own codes, and
+the Crowdin CLI silently ignores config keys it does not recognise, so a mapping typo is
+invisible there. On the other side, supply uploads every directory it finds - uploader.rb's
+all_languages is a bare Dir.entries with no reference to Supply::Languages::ALL_LANGUAGES -
+and fastlane documents no behaviour for unknown folders. The rejection therefore arrives
+from the Play API mid-upload, after earlier locales have already been written.
+
+The list below is Play's published set (Play Console Help, "Add your own translations"),
+not fastlane's ALL_LANGUAGES. They disagree: fastlane omits Albanian, which Play lists.
+Play is the authority here, because Play is what rejects the upload.
+"""
+import sys
+from pathlib import Path
+
+METADATA = Path(__file__).resolve().parent.parent / "fastlane/metadata/android"
+
+PLAY_LANGUAGES = {
+ "af",
+ "am",
+ "ar",
+ "az-AZ",
+ "be",
+ "bg",
+ "bn-BD",
+ "ca",
+ "cs-CZ",
+ "da-DK",
+ "de-DE",
+ "el-GR",
+ "en-AU",
+ "en-CA",
+ "en-GB",
+ "en-IN",
+ "en-SG",
+ "en-US",
+ "en-ZA",
+ "es-419",
+ "es-ES",
+ "es-US",
+ "et",
+ "eu-ES",
+ "fa",
+ "fi-FI",
+ "fil",
+ "fr-CA",
+ "fr-FR",
+ "gl-ES",
+ "hi-IN",
+ "hr",
+ "hu-HU",
+ "hy-AM",
+ "id",
+ "is-IS",
+ "it-IT",
+ "iw-IL",
+ "ja-JP",
+ "ka-GE",
+ "km-KH",
+ "kn-IN",
+ "ko-KR",
+ "ky-KG",
+ "lo-LA",
+ "lt",
+ "lv",
+ "mk-MK",
+ "ml-IN",
+ "mn-MN",
+ "mr-IN",
+ "ms",
+ "ms-MY",
+ "my-MM",
+ "ne-NP",
+ "nl-NL",
+ "no-NO",
+ "pl-PL",
+ "pt-BR",
+ "pt-PT",
+ "rm",
+ "ro",
+ "ru-RU",
+ "si-LK",
+ "sk",
+ "sl",
+ "sq",
+ "sr",
+ "sv-SE",
+ "sw",
+ "ta-IN",
+ "te-IN",
+ "th",
+ "tr-TR",
+ "uk",
+ "vi",
+ "zh-CN",
+ "zh-HK",
+ "zh-TW",
+ "zu",
+}
+
+
+def main() -> int:
+ if not METADATA.is_dir():
+ print(f"error: {METADATA} not found", file=sys.stderr)
+ return 2
+ dirs = sorted(p.name for p in METADATA.iterdir() if p.is_dir() and not p.name.startswith("."))
+ bad = [d for d in dirs if d not in PLAY_LANGUAGES]
+ if not bad:
+ print(f"All {len(dirs)} fastlane locale directories are languages Google Play accepts.")
+ return 0
+ for d in bad:
+ print(
+ f"::error file=fastlane/metadata/android/{d}::'{d}' is not a Play language code. "
+ "Map it in crowdin.yml languages_mapping, or exclude it there.",
+ file=sys.stderr,
+ )
+ print(f"\n{len(bad)} of {len(dirs)} locale directories would be rejected by Play.", file=sys.stderr)
+ return 1
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())