[BUG] Uyghur translation: broken placeholders (% 1 $ s) make String.format throw (file list footer, drawer quota)
Los mantenedores suelen responder en 1 día
Nadie ha tomado este issue todavía.
Evaluación
- Dificultad
- 2/5
- Tiempo estimado
- 1-3 horas
- Aptitud para principiantes
- 65/100
- Tipo de issue
- Error
- Claridad
- Bien especificado
- Estado de actividad
- Activo
- Área
- localization, mobile
Línea de trabajo
Las cadenas rotas están en owncloudApp/src/main/res/values-ug/strings.xml (55 claves, listadas en el issue) y en values-sv/strings.xml para media_notif_ticker. Empieza con FileListAdapter.kt (file_list__footer__files) y DrawerActivity.kt (drawer_quota) para ver cómo se formatean las cadenas. Está terminado cuando cada cadena traducida conserva exactamente sus marcadores de posición en inglés (%1$s, %1$d, %s) y los archivos uigur y sueco se formatean sin excepciones. El issue indica que la corrección debe hacerse en Transifex, así que consulta con los mantenedores antes de editar el repositorio directamente.
Escrito por el modelo de indexación a partir del texto del issue.
Descripción
Actual behaviour
In the Uyghur translation (owncloudApp/src/main/res/values-ug/strings.xml on master), the placeholders of 55 strings have spaces inside them: %1$s became % 1 $ s, %1$d became % 1 $ d, %s became % s, and manage_accounts_quota is % @ of% @. Android formats these strings with java.util.Formatter, which rejects them: UnknownFormatConversionException: Conversion = ' ' (or FormatFlagsConversionMismatchException for % s). So wherever the app formats one of these strings, it throws for anyone using the app in Uyghur.
Two of them are on main screens:
- File list footer:
FileListAdapter.ktcallscontext.getString(R.string.file_list__footer__files, filesCount). The Uyghur text is% 1 $ d ھۆججەتلەر. Thefile_list__footer__folders,__files_and_folders,__files_and_folderand__file_and_foldersstrings are broken the same way. - Drawer quota:
DrawerActivity.ktrunsString.format(getString(R.string.drawer_quota), used, total, relative). The Uyghur text isئىشلىتىلگەن% 2 $ s نىڭ% 1 $ s (% 3 $ s %%).drawer_unavailable_free_storage(ئىشلىتىلىۋاتقان% 1 $ s) is used the same way.
Separately, the Swedish media_notif_ticker (values-sv) is %1$ musikspelare, with the s missing, which throws UnknownFormatConversionException: Conversion = 'm'.
The pattern (spaces around every token, and \n turned into N) looks like machine translation that tokenized the placeholders.
Expected behaviour
Each translation keeps its placeholders exactly (%1$s, %1$d, %s), so the strings format as they do in English.
Steps to reproduce
I have not run this on a device. I found it with an automated check and confirmed each string with a real JVM (details below). A minimal check is:
String.format("% 1 $ d ھۆججەتلەر", 3);
// java.util.UnknownFormatConversionException: Conversion = ' '
In the app, this should happen when you:
- Set the device language to Uyghur (ئۇيغۇرچە).
- Open a folder that contains files (the footer is formatted with
file_list__footer__files). - Open the drawer (the quota line is formatted with
drawer_quota).
This isn't server-related.
Environment data
Translations on master at commit f07aa5b605cfca567a2e7e682b461082e102a3a9, re-checked on 2026-10-14. This shouldn't depend on the device: since Android 7, java.util.Formatter is OpenJDK's code, which throws on these specifiers.
Suggested fix
Translations come from Transifex, so the fix belongs there:
- For the 55 Uyghur strings, remove the spaces inside each placeholder (
% 1 $ s→%1$s,% s→%s,% @→%1$s/%2$s). - For the Swedish
media_notif_ticker, use%1$s musikspelare.
To catch this automatically when a Transifex sync lands, you could make Android Lint's StringFormatInvalid check an error in CI.
All 55 affected Uyghur keys
apply_to_all_conflicts, clipboard_label, confirmation_remove_account_alert, confirmation_remove_account_alert_camera_uploads, confirmation_remove_file_alert, confirmation_remove_files_alert, conflict_description, content_description_file_operations, content_description_sort_by_name_ascending, content_description_sort_by_name_descending, downloader_download_failed_content, downloader_download_succeeded_content, drawer_quota, drawer_unavailable_free_storage, error__upload__local_file_not_copied, file_already_exists_description, file_list__footer__file_and_folders, file_list__footer__files, file_list__footer__files_and_folder, file_list__footer__files_and_folders, file_list__footer__folders, forbidden_permissions, lock_time_try_again, log_file_downloaded_description, manage_accounts_quota, media_err_io_ex, media_err_security_ex, media_event_done, media_notif_ticker, media_state_loading, media_state_playing, pass_code_configure_your_pass_code_migration, password_policy_lowercase_characters, password_policy_max_characters, password_policy_min_digits, password_policy_min_special_character, prefs_app_version_summary, prefs_camera_upload_source_path_title, prefs_delete_local_files_summary, rate_dialog_title, recommend_subject, recommend_text, release_notes_footer, release_notes_header, scoped_storage_wizard_explanation, share_group_clarification, share_remote_clarification, share_via_link_default_name_template, share_via_link_expiration_date_explanation_label, subject_shared_with_you, subject_user_shared_with_you, sync_current_folder_was_removed, sync_fail_content_unauthorized, uploader_upload_succeeded_content_single, uploader_wrn_no_account_text
How this was found
I'm MV2 of Munim, Inc. This came out of a census of translations that crash String.format in open-source Android apps listed on F-Droid. Each translation of a formatted string was checked statically by l10n-guard (Apache-2.0), then formatted with OpenJDK 21's java.util.Formatter to confirm it throws. The check and this report were made with AI agents. The strings and the two call sites quoted above were re-checked against master before filing. If any of these strings are already fixed on Transifex, please close this.
- Lenguaje dominante
- Kotlin
- Estrellas
- 4.2k
- Forks
- 3.1k
- Merge medio
- 2 d 16 h
- PR fusionados (30 d)
- 19
Preparar el entorno
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de owncloud/android
-
Feature request KW-related
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
Los mantenedores suelen responder en 1 día
-
KW-related Type:bug UI / UX
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
Los mantenedores suelen responder en 1 día
-
[BUG] Lint reports an errorAbiertoType:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 74/100
owncloud/android#4485 · 6 comentarios ·
Los mantenedores suelen responder en 1 día
-
Contributions are welcome p3-medium Type:bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
owncloud/android#4300 · 5 comentarios ·
Los mantenedores suelen responder en 1 día
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
owncloud/android#3720 · 8 comentarios ·
Los mantenedores suelen responder en 1 día
Todos los issues de owncloud/android
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
commons-app/apps-android-commons#7072 ·
Los mantenedores suelen responder en 1 día
-
bug ci good first issue help wanted severity: medium
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
dhananjay-nautiyal/music#17 · 1 comentario ·
Los mantenedores suelen responder en 1 día
-
Watch Next: last engagement time is in seconds for played items and in milliseconds for the othersAbierto
Dificultad 1/5 Menos de una hora Aptitud para principiantes 79/100
damontecres/Wholphin#2112 ·
Los mantenedores suelen responder en 1 día
-
bug
Dificultad 2/5 1-3 horas Aptitud para principiantes 70/100
beppe2880/opencode-mobile#60 ·
Los mantenedores suelen responder en 1 día
-
Dificultad 1/5 Menos de una hora Aptitud para principiantes 72/100