0b9d5f216e
Follow-up to the previous download fix: the old pack was no longer deleted before the download, but it was still deleted at the start of the extraction step. If the app crashed mid-extraction or the archive was truncated, the device was left without a valid pack; worse, a partially extracted directory containing language.db would pass is_language_directory_valid() on the next offline launch and be accepted as a working pack. The extraction thread now follows an extract / verify / swap sequence: 1. Extract the archive into <lang>_tmp instead of the final location, leaving the current pack untouched and avoiding any risk of merging old and new files. 2. Validate the extracted pack (non-empty, language.db present) before touching the current one; on failure, discard the temp directory and the archive, show the invalid-directory error, and keep playing with the current pack. 3. Only then delete the previous pack and rename the new one into place. The window without a valid pack shrinks from the whole extraction to two filesystem operations. If the final rename fails, the temp directory is kept (the data is intact on disk) and the error popup is shown; the next launch detects the missing pack and downloads it again. A leftover temp directory from a crash is removed at the start of the next extraction. Verified with the GUT test suite (62/62 passing).