From cbacff1ce5151681c5199cf7d73b49108557b777 Mon Sep 17 00:00:00 2001 From: JingMatrix Date: Wed, 29 Jul 2026 14:42:22 +0200 Subject: [PATCH] Fix source matching and locale placeholders in the Crowdin config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two independent defects, both of which the tooling reports as success. Source patterns. Within a path node the CLI compiles `*` to `.+` and applies the result as an anchored match, so a `*` must consume at least one character. A pattern of the form `strings*.xml` therefore selects only names that carry something between the stem and the extension, never the bare `strings.xml`. A file that no pattern selects never enters the candidate set, so the upload neither includes it nor reports it as missing: the failure is silent by construction. Neither `**` nor `?` closes the gap — `**` is special only as a whole path node, and `?` adds a further required character. Naming each source file is the only formulation without such a hole. Locale placeholders. %android_code% is region-qualified for every language, whereas an Android resource folder carries a region only where one is needed to disambiguate a variant. Aligning folders with it would require one mapping entry per language to strip the region back off — an obligation that grows with every language added and degrades silently when forgotten, since translation upload derives one expected path per target language and skips the ones it cannot find. %two_letters_code% inverts the default: it already agrees with the unqualified folders, so only the genuinely region-qualified locales, plus the codes Android retained after the ISO renames, need an entry. Those are now written down in the repository rather than left implicit in project state that no checkout can see. The mapping is repeated per file because it is a file-level key; a YAML anchor keeps the four entries identical by construction. The `translation` value doubles as the file's server-side export pattern and is expanded there, where the local mapping does not apply, so the same overrides must exist in the project's language settings for downloads to resolve. Nothing in CI observes this, as it does not download translations. The workflow trigger now names the same files instead of globbing them. Its matching rules and the CLI's are defined independently, and a trigger that quietly never fires is the worse failure of the two. Before this reaches master: hosted word count scales with the number of target languages, so the newly matched source file has to wait until the files orphaned by the previous layout are removed from the project. --- .github/workflows/crowdin.yml | 7 +++++- crowdin.yml | 42 ++++++++++++++++++++++++++++++----- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/.github/workflows/crowdin.yml b/.github/workflows/crowdin.yml index 1aacca7da..8c67d05ed 100644 --- a/.github/workflows/crowdin.yml +++ b/.github/workflows/crowdin.yml @@ -5,7 +5,12 @@ on: push: branches: [ master ] paths: - - manager/src/main/res/values/strings*.xml + # Named rather than globbed, to match crowdin.yml. The trigger's matching rules and the + # CLI's are defined independently — notably on whether `*` may match nothing — and a + # trigger that quietly never fires is the worse failure. + - manager/src/main/res/values/strings.xml + - manager/src/main/res/values/strings_logs.xml + - manager/src/main/res/values/strings_store.xml - daemon/src/main/res/values/strings.xml jobs: diff --git a/crowdin.yml b/crowdin.yml index ff983868f..85cfcfeac 100644 --- a/crowdin.yml +++ b/crowdin.yml @@ -4,13 +4,43 @@ base_path: . base_url: 'https://api.crowdin.com' pull_request_title: '[translation] Update translation from Crowdin' preserve_hierarchy: 1 + +# Every source file is named individually. Within a path node the CLI compiles `*` to `.+`, not +# `.*`, and applies it as an anchored match, so a `*` has to consume at least one character: a +# pattern of the form `strings*.xml` cannot select `strings.xml`. A file that no pattern selects +# never becomes a candidate, and the CLI says nothing about a file it never considered. +# +# %two_letters_code% rather than %android_code%: %android_code% is region-qualified for every +# language, while a resource folder carries a region only where one is needed to disambiguate. +# Using it would mean one mapping entry per language to strip the region back off, in perpetuity, +# and a language enabled later without such an entry resolves to a folder that does not exist. +# The two-letter code already agrees with the unqualified folders, so only the exceptions need an +# entry here. +# +# These overrides must also exist in the project's language settings: `translation` is uploaded +# verbatim as the file's export pattern and expanded server-side, where this mapping has no say. +# Keep the two in step. files: - # %android_code% rather than %two_letters_code%: it is the only placeholder that produces the - # region-qualified resource folders Android actually uses — values-zh-rCN, values-pt-rBR — and - # with the two-letter form Crowdin cannot even find the existing ones to upload them. - - source: /manager/src/main/res/values/strings*.xml - translation: /manager/src/main/res/values-%android_code%/%original_file_name% + - source: /manager/src/main/res/values/strings.xml + translation: /manager/src/main/res/values-%two_letters_code%/%original_file_name% type: android + languages_mapping: &resource_folders + two_letters_code: + 'id': 'in' # Android kept the superseded ISO code + 'he': 'iw' # likewise + 'pt-BR': 'pt-rBR' # the unqualified code denotes the European variant + 'zh-CN': 'zh-rCN' + 'zh-HK': 'zh-rHK' + 'zh-TW': 'zh-rTW' + - source: /manager/src/main/res/values/strings_logs.xml + translation: /manager/src/main/res/values-%two_letters_code%/%original_file_name% + type: android + languages_mapping: *resource_folders + - source: /manager/src/main/res/values/strings_store.xml + translation: /manager/src/main/res/values-%two_letters_code%/%original_file_name% + type: android + languages_mapping: *resource_folders - source: /daemon/src/main/res/values/strings.xml - translation: /daemon/src/main/res/values-%android_code%/%original_file_name% + translation: /daemon/src/main/res/values-%two_letters_code%/%original_file_name% type: android + languages_mapping: *resource_folders