From 185fee2027f0356b603dc9c5cfd0baa6c788a059 Mon Sep 17 00:00:00 2001 From: rhunk <101876869+rhunk@users.noreply.github.com> Date: Tue, 16 May 2023 01:35:16 +0200 Subject: [PATCH] localization --- app/src/main/assets/lang/en.json | 76 ++++++++++++++++ .../kotlin/me/rhunk/snapenhance/ModContext.kt | 6 ++ .../snapenhance/bridge/client/BridgeClient.kt | 17 +++- .../bridge/common/impl/LocaleRequest.kt | 7 +- .../bridge/service/BridgeService.kt | 11 ++- .../snapenhance/config/ConfigCategory.kt | 16 ++-- .../snapenhance/config/ConfigProperty.kt | 88 ++++++++----------- .../features/impl/ConfigEnumKeys.kt | 2 +- .../impl/downloader/MediaDownloader.kt | 17 ++-- .../snapenhance/features/impl/ui/UITweaks.kt | 2 +- .../impl/ui/menus/impl/FriendFeedInfoMenu.kt | 24 ++--- .../manager/impl/MappingManager.kt | 8 +- .../manager/impl/TranslationManager.kt | 25 +++++- app/src/main/res/values-fr/strings.xml | 4 - app/src/main/res/values/strings.xml | 30 ------- 15 files changed, 199 insertions(+), 134 deletions(-) create mode 100644 app/src/main/assets/lang/en.json delete mode 100644 app/src/main/res/values-fr/strings.xml diff --git a/app/src/main/assets/lang/en.json b/app/src/main/assets/lang/en.json new file mode 100644 index 000000000..fd84443ab --- /dev/null +++ b/app/src/main/assets/lang/en.json @@ -0,0 +1,76 @@ +{ + "category": { + "general": "General", + "spy": "Spy", + "media_download": "Media Downloader", + "privacy": "Privacy", + "ui": "UI", + "extras": "Extras", + "tweaks": "Tweaks", + "experimental": "Experimental" + }, + + "property": { + "save_folder": "Save Folder", + "prevent_read_receipts": "Prevent Read Receipts", + "hide_bitmoji_presence": "Hide Bitmoji Presence", + "show_message_content": "Show Message Content", + "message_logger": "Message Logger", + "auto_download_snaps": "Auto Download Snaps", + "auto_download_stories": "Auto Download Stories", + "auto_download_public_stories": "Auto Download Public Stories", + "auto_download_spotlight": "Auto Download Spotlight", + "overlay_merge": "Snap Image Overlay Merge", + "download_inchat_snaps": "Download Inchat Snaps", + "anti_auto_download_button": "Anti Auto Download Button", + "disable_metrics": "Disable Metrics", + "prevent_screenshots": "Prevent Screenshots", + "prevent_status_notifications": "Prevent Status Notifications (Screenrecord, media save)", + "anonymous_story_view": "Anonymous Story View", + "hide_typing_notification": "Hide Typing Notification", + "menu_slot_id": "Friend Menu Slot ID", + "message_preview_length": "Message Preview Length", + "auto_save": "Auto Save", + "snapchat_plus": "Snapchat Plus", + "remove_voice_record_button": "Remove Voice Record Button", + "remove_stickers_button": "Remove Stickers Button", + "remove_cognac_button": "Remove Cognac Button", + "remove_call_buttons": "Remove Call Buttons", + "long_snap_sending": "Long Snap Sending", + "block_ads": "Block Ads", + "streak_expiration_info": "Show Streak Expiration Info", + "new_map_ui": "New Map UI", + "use_download_manager": "Use Android Download Manager" + }, + + + "friend_menu_option": { + "preview": "Preview", + "stealth_mode": "Stealth Mode", + "anti_auto_download": "Anti Auto Download" + }, + + "message_context_menu_option": { + "download": "Download", + "preview": "Preview" + }, + + "modal_option": { + "profile_info": "Profile Info", + "close": "Close" + }, + + "conversation_preview": { + "streak_expiration": "expires in %s days %s hours %s minutes", + "title": "Preview", + "unknown_user": "Unknown User" + }, + + "profile_info": { + "title": "Profile Info", + "username": "Username", + "display_name": "Display Name", + "added_date": "Added Date", + "birthday": "Birthday : {month} {day}" + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt b/app/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt index 00161e916..f900c8132 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/ModContext.kt @@ -89,6 +89,12 @@ class ModContext { exitProcess(0) } + fun crash(message: String, throwable: Throwable? = null) { + Logger.xposedLog(message, throwable) + longToast(message) + delayForceCloseApp(100) + } + fun delayForceCloseApp(delay: Long) = Handler(Looper.getMainLooper()).postDelayed({ forceCloseApp() }, delay) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt index ef13f8b9e..d86354ff8 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/client/BridgeClient.kt @@ -53,11 +53,12 @@ class BridgeClient( BridgeMessageType.FILE_ACCESS_RESULT -> FileAccessResult() BridgeMessageType.DOWNLOAD_CONTENT_RESULT -> DownloadContentResult() BridgeMessageType.MESSAGE_LOGGER_RESULT -> MessageLoggerResult() + BridgeMessageType.LOCALE_RESULT -> LocaleResult() else -> { - log("Unknown message type: ${msg.what}") - null + future.completeExceptionally(IllegalStateException("Unknown message type: ${msg.what}")) + return } - } ?: return + } with(message) { read(msg.data) @@ -220,6 +221,16 @@ class BridgeClient( ) } + fun fetchTranslations(): LocaleResult { + sendMessage( + BridgeMessageType.LOCALE_REQUEST, + LocaleRequest(), + LocaleResult::class + ).run { + return this + } + } + override fun onServiceConnected(name: ComponentName, service: IBinder) { messenger = Messenger(service) future.complete(true) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/LocaleRequest.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/LocaleRequest.kt index da2a1bc0c..df3f6c7ad 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/LocaleRequest.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/common/impl/LocaleRequest.kt @@ -3,15 +3,10 @@ package me.rhunk.snapenhance.bridge.common.impl import android.os.Bundle import me.rhunk.snapenhance.bridge.common.BridgeMessage -class LocaleRequest( - var locale: String? = null -) : BridgeMessage() { - +class LocaleRequest() : BridgeMessage() { override fun write(bundle: Bundle) { - bundle.putString("locale", locale) } override fun read(bundle: Bundle) { - locale = bundle.getString("locale") } } \ No newline at end of file diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt index 48e145a80..6a7661d89 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/bridge/service/BridgeService.kt @@ -10,6 +10,7 @@ import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.bridge.common.BridgeMessageType import me.rhunk.snapenhance.bridge.common.impl.* import java.io.File +import java.util.* class BridgeService : Service() { companion object { @@ -112,9 +113,13 @@ class BridgeService : Service() { } private fun handleLocaleRequest(msg: LocaleRequest, reply: (Message) -> Unit) { - val locale = resources.configuration.locales[0] - Logger.log("Locale: ${locale.language}_${locale.country}") - TODO() + val deviceLocale = Locale.getDefault().language + val compatibleLocale = resources.assets.list("lang")?.find { it.startsWith(deviceLocale) }?.substring(0, 2) ?: "en" + + resources.assets.open("lang/$compatibleLocale.json").use { inputStream -> + val json = inputStream.bufferedReader().use { it.readText() } + reply(LocaleResult(compatibleLocale, json.toByteArray(Charsets.UTF_8)).toMessage(BridgeMessageType.LOCALE_RESULT.value)) + } } private fun handleDownloadContent(msg: DownloadContentRequest, reply: (Message) -> Unit) { diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt index 590af4acf..a13befb67 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigCategory.kt @@ -3,12 +3,12 @@ package me.rhunk.snapenhance.config enum class ConfigCategory( val key: String ) { - GENERAL("general"), - SPY("spy"), - MEDIA_DOWNLOADER("media_download"), - PRIVACY("privacy"), - UI("ui"), - EXTRAS("extras"), - TWEAKS("tweaks"), - EXPERIMENTS("experiments"); + GENERAL("category.general"), + SPY("category.spy"), + MEDIA_DOWNLOADER("category.media_download"), + PRIVACY("category.privacy"), + UI("category.ui"), + EXTRAS("category.extras"), + TWEAKS("category.tweaks"), + EXPERIMENTAL("category.experimental"); } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt index 3e68323f5..0e2b35f1e 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/config/ConfigProperty.kt @@ -10,7 +10,7 @@ enum class ConfigProperty( val defaultValue: Any ) { SAVE_FOLDER( - "save_folder", "description.save_folder", ConfigCategory.GENERAL, + "property.save_folder", "description.save_folder", ConfigCategory.GENERAL, File( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM).absolutePath + "/Snapchat", "SnapEnhance" @@ -18,166 +18,148 @@ enum class ConfigProperty( ), PREVENT_READ_RECEIPTS( - "prevent_read_receipts", + "property.prevent_read_receipts", "description.prevent_read_receipts", ConfigCategory.SPY, false ), HIDE_BITMOJI_PRESENCE( - "hide_bitmoji_presence", + "property.hide_bitmoji_presence", "description.hide_bitmoji_presence", ConfigCategory.SPY, false ), SHOW_MESSAGE_CONTENT( - "show_message_content", + "property.show_message_content", "description.show_message_content", ConfigCategory.SPY, false ), - MESSAGE_LOGGER("message_logger", "description.message_logger", ConfigCategory.SPY, false), + MESSAGE_LOGGER("property.message_logger", "description.message_logger", ConfigCategory.SPY, false), - MEDIA_DOWNLOADER( - "media_downloader", - "description.media_downloader", - ConfigCategory.MEDIA_DOWNLOADER, - true - ), AUTO_DOWNLOAD_SNAPS( - "auto_download_snaps", + "property.auto_download_snaps", "description.auto_download_snaps", ConfigCategory.MEDIA_DOWNLOADER, true ), AUTO_DOWNLOAD_STORIES( - "auto_download_stories", + "property.auto_download_stories", "description.auto_download_stories", ConfigCategory.MEDIA_DOWNLOADER, false ), AUTO_DOWNLOAD_PUBLIC_STORIES( - "auto_download_public_stories", + "property.auto_download_public_stories", "description.auto_download_public_stories", ConfigCategory.MEDIA_DOWNLOADER, false ), AUTO_DOWNLOAD_SPOTLIGHT( - "auto_download_spotlight", + "property.auto_download_spotlight", "description.auto_download_spotlight", ConfigCategory.MEDIA_DOWNLOADER, false ), OVERLAY_MERGE( - "overlay_merge", + "property.overlay_merge", "description.overlay_merge", ConfigCategory.MEDIA_DOWNLOADER, true ), DOWNLOAD_INCHAT_SNAPS( - "download_inchat_snaps", + "property.download_inchat_snaps", "description.download_inchat_snaps", ConfigCategory.MEDIA_DOWNLOADER, true ), ANTI_DOWNLOAD_BUTTON( - "anti_download_button", - "description.anti_download_button", + "property.anti_auto_download_button", + "description.anti_auto_download_button", ConfigCategory.MEDIA_DOWNLOADER, false ), - DISABLE_METRICS("disable_metrics", "description.disable_metrics", ConfigCategory.PRIVACY, true), + DISABLE_METRICS("property.disable_metrics", "description.disable_metrics", ConfigCategory.PRIVACY, true), PREVENT_SCREENSHOTS( - "prevent_screenshots", + "property.prevent_screenshots", "description.prevent_screenshots", ConfigCategory.PRIVACY, true ), PREVENT_STATUS_NOTIFICATIONS( - "prevent_status_notifications", + "property.prevent_status_notifications", "description.prevent_status_notifications", ConfigCategory.PRIVACY, true ), ANONYMOUS_STORY_VIEW( - "anonymous_story_view", + "property.anonymous_story_view", "description.anonymous_story_view", ConfigCategory.PRIVACY, false ), HIDE_TYPING_NOTIFICATION( - "hide_typing_notification", + "property.hide_typing_notification", "description.hide_typing_notification", ConfigCategory.PRIVACY, false ), - MENU_SLOT_ID("menu_slot_id", "description.menu_slot_id", ConfigCategory.UI, 1), + MENU_SLOT_ID("property.menu_slot_id", "description.menu_slot_id", ConfigCategory.UI, 1), MESSAGE_PREVIEW_LENGTH( - "message_preview_length", + "property.message_preview_length", "description.message_preview_length", ConfigCategory.UI, 20 ), - AUTO_SAVE("auto_save", "description.auto_save", ConfigCategory.EXTRAS, false), - /*EXTERNAL_MEDIA_AS_SNAP( - "external_media_as_snap", - "description.external_media_as_snap", - ConfigCategory.EXTRAS, - false - ), - CONVERSATION_EXPORT( - "conversation_export", - "description.conversation_export", - ConfigCategory.EXTRAS, - false - ),*/ - SNAPCHAT_PLUS("snapchat_plus", "description.snapchat_plus", ConfigCategory.EXTRAS, false), + AUTO_SAVE("property.auto_save", "description.auto_save", ConfigCategory.EXTRAS, false), + SNAPCHAT_PLUS("property.snapchat_plus", "description.snapchat_plus", ConfigCategory.EXTRAS, false), REMOVE_VOICE_RECORD_BUTTON( - "remove_voice_record_button", + "property.remove_voice_record_button", "description.remove_voice_record_button", ConfigCategory.TWEAKS, false ), REMOVE_STICKERS_BUTTON( - "remove_stickers_button", + "property.remove_stickers_button", "description.remove_stickers_button", ConfigCategory.TWEAKS, false ), REMOVE_COGNAC_BUTTON( - "remove_cognac_button", + "property.remove_cognac_button", "description.remove_cognac_button", ConfigCategory.TWEAKS, false ), - REMOVE_CALLBUTTONS( - "remove_callbuttons", - "description.remove_callbuttons", + REMOVE_CALL_BUTTONS( + "property.remove_call_buttons", + "description.remove_call_buttons", ConfigCategory.TWEAKS, false ), LONG_SNAP_SENDING( - "long_snap_sending", + "property.long_snap_sending", "description.long_snap_sending", ConfigCategory.TWEAKS, false ), - BLOCK_ADS("block_ads", "description.block_ads", ConfigCategory.TWEAKS, false), - STREAKEXPIRATIONINFO( - "streakexpirationinfo", + BLOCK_ADS("property.block_ads", "description.block_ads", ConfigCategory.TWEAKS, false), + STREAK_EXPIRATION_INFO( + "property.streak_expiration_info", "description.streakexpirationinfo", ConfigCategory.TWEAKS, false ), - NEW_MAP_UI("new_map_ui", "description.new_map_ui", ConfigCategory.TWEAKS, false), + NEW_MAP_UI("property.new_map_ui", "description.new_map_ui", ConfigCategory.TWEAKS, false), USE_DOWNLOAD_MANAGER( - "use_download_manager", + "property.use_download_manager", "description.use_download_manager", - ConfigCategory.EXPERIMENTS, + ConfigCategory.EXPERIMENTAL, false ); diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt index b3632d822..4c7dd5cf2 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ConfigEnumKeys.kt @@ -47,7 +47,7 @@ class ConfigEnumKeys : Feature("Config enum keys", loadParams = FeatureLoadParam } } - if (context.config.bool(ConfigProperty.STREAKEXPIRATIONINFO)) { + if (context.config.bool(ConfigProperty.STREAK_EXPIRATION_INFO)) { hookAllEnums(context.mappings.getMappedClass("enums", "FRIENDS_FEED")) { key, atomicValue -> if (key == "STREAK_EXPIRATION_INFO") atomicValue.set(true) } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt index 63b37eb48..6a1ac3f6b 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/downloader/MediaDownloader.kt @@ -84,7 +84,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam ) onDownloadComplete() } catch (e: Throwable) { - Logger.xposedLog(e) + xposedLog(e) context.longToast("Failed to save file: " + e.message) return false } @@ -135,7 +135,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam if (fFmpegSession.returnCode.value != 0) { mergedFile.delete() context.longToast("Failed to merge video and overlay. See logs for more details.") - Logger.xposedLog(fFmpegSession.output) + xposedLog(fFmpegSession.output) return null } val mergedFileData: ByteArray = FileInputStream(mergedFile).readBytes() @@ -285,11 +285,18 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam } } + private fun canAutoDownload(): Boolean { + return context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SNAPS) || + context.config.bool(ConfigProperty.AUTO_DOWNLOAD_STORIES) || + context.config.bool(ConfigProperty.AUTO_DOWNLOAD_PUBLIC_STORIES) || + context.config.bool(ConfigProperty.AUTO_DOWNLOAD_SPOTLIGHT) + } + override fun asyncOnActivityCreate() { val operaViewerControllerClass: Class<*> = context.mappings.getMappedClass("OperaPageViewController", "Class") val onOperaViewStateCallback: (HookAdapter) -> Unit = onOperaViewStateCallback@{ param -> - if (!context.config.bool(ConfigProperty.MEDIA_DOWNLOADER)) return@onOperaViewStateCallback + if (!canAutoDownload()) return@onOperaViewStateCallback val viewState = (param.thisObject() as Any).getObjectField(context.mappings.getMappedValue("OperaPageViewController", "viewStateField")).toString() if (viewState != "FULLY_DISPLAYED") { @@ -317,7 +324,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam try { handleOperaMedia(mediaParamMap, mediaInfoMap, false) } catch (e: Throwable) { - Logger.xposedLog(e) + xposedLog(e) context.longToast(e.message!!) } } @@ -390,7 +397,7 @@ class MediaDownloader : Feature("MediaDownloader", loadParams = FeatureLoadParam } } if (videoData == null || overlayData == null) { - Logger.xposedLog("Invalid data in zip file") + xposedLog("Invalid data in zip file") return } val mergedVideo = mergeOverlay(videoData, overlayData, isPreviewMode) diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt index c887f9517..8339c1b6d 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/UITweaks.kt @@ -45,7 +45,7 @@ class UITweaks : Feature("UITweaks", loadParams = FeatureLoadParams.ACTIVITY_CRE if (chatInputBarSticker == viewId && context.config.bool(ConfigProperty.REMOVE_STICKERS_BUTTON)) { view.visibility = View.GONE } - if (context.config.bool(ConfigProperty.REMOVE_CALLBUTTONS)) { + if (context.config.bool(ConfigProperty.REMOVE_CALL_BUTTONS)) { if (viewId == callButton1 || viewId == callButton2) { if (view.visibility == View.GONE) return@hook Hooker.ephemeralHookObjectMethod(View::class.java, view, "setVisibility", HookStage.BEFORE) { param -> diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/FriendFeedInfoMenu.kt b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/FriendFeedInfoMenu.kt index 4bdaa5b21..bc682721a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/FriendFeedInfoMenu.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/features/impl/ui/menus/impl/FriendFeedInfoMenu.kt @@ -64,15 +64,15 @@ class FriendFeedInfoMenu : AbstractMenu() { val birthday = Calendar.getInstance() birthday[Calendar.MONTH] = (profile.birthday shr 32).toInt() - 1 val message: String = """ - ${context.translation.get("info.username")}: ${profile.username} - ${context.translation.get("info.display_name")}: ${profile.displayName} - ${context.translation.get("info.added_date")}: ${formatDate(addedTimestamp)} + ${context.translation.get("profile_info.username")}: ${profile.username} + ${context.translation.get("profile_info.display_name")}: ${profile.displayName} + ${context.translation.get("profile_info.added_date")}: ${formatDate(addedTimestamp)} ${birthday.getDisplayName( Calendar.MONTH, Calendar.LONG, - context.translation.getLocale() + context.translation.locale )?.let { - context.translation.get("info.birthday") + context.translation.get("profile_info.birthday") .replace("{month}", it) .replace("{day}", profile.birthday.toInt().toString()) } @@ -120,7 +120,7 @@ class FriendFeedInfoMenu : AbstractMenu() { } } - var displayUsername = sender?.displayName ?: sender?.usernameForSorting?: "Unknown user" + var displayUsername = sender?.displayName ?: sender?.usernameForSorting?: context.translation.get("conversation_preview.unknown_user") if (displayUsername.length > 12) { displayUsername = displayUsername.substring(0, 13) + "... " @@ -136,7 +136,7 @@ class FriendFeedInfoMenu : AbstractMenu() { val timeSecondDiff = ((it.streakExpirationTimestamp - System.currentTimeMillis()) / 1000 / 60).toInt() messageBuilder.append("\n\n") .append("\uD83D\uDD25 ") //fire emoji - .append(context.translation.get("streak_expiration").format( + .append(context.translation.get("conversation_preview.streak_expiration").format( timeSecondDiff / 60 / 24, timeSecondDiff / 60 % 24, timeSecondDiff % 60 @@ -145,13 +145,13 @@ class FriendFeedInfoMenu : AbstractMenu() { //alert dialog val builder = AlertDialog.Builder(context.mainActivity) - builder.setTitle(context.translation.get("preview")) + builder.setTitle(context.translation.get("conversation_preview.title")) builder.setMessage(messageBuilder.toString()) builder.setPositiveButton( "OK" ) { dialog: DialogInterface, _: Int -> dialog.dismiss() } targetPerson?.let { - builder.setNegativeButton(context.translation.get("profile_info")) {_, _ -> + builder.setNegativeButton(context.translation.get("modal_option.profile_info")) {_, _ -> context.executeAsync { showProfileInfo(it) } @@ -175,7 +175,7 @@ class FriendFeedInfoMenu : AbstractMenu() { //preview button val previewButton = Button(viewModel.context) - previewButton.text = context.translation.get("preview") + previewButton.text = context.translation.get("friend_menu_option.preview") applyTheme(viewModel, previewButton) val finalFocusedConversationTargetUser = focusedConversationTargetUser previewButton.setOnClickListener { v: View? -> @@ -188,7 +188,7 @@ class FriendFeedInfoMenu : AbstractMenu() { //stealth switch val stealthSwitch = Switch(viewModel.context) - stealthSwitch.text = context.translation.get("stealth_mode") + stealthSwitch.text = context.translation.get("friend_menu_option.stealth_mode") stealthSwitch.isChecked = context.feature(StealthMode::class).isStealth(conversationId) applyTheme(viewModel, stealthSwitch) stealthSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> @@ -202,7 +202,7 @@ class FriendFeedInfoMenu : AbstractMenu() { val userId = context.database.getFriendFeedInfoByConversationId(conversationId)?.friendUserId ?: return val antiAutoDownload = Switch(viewModel.context) - antiAutoDownload.text = context.translation.get("anti_auto_download") + antiAutoDownload.text = context.translation.get("friend_menu_option.anti_auto_download") antiAutoDownload.isChecked = context.feature(AntiAutoDownload::class).isUserIgnored(userId) applyTheme(viewModel, antiAutoDownload) antiAutoDownload.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt index b0d5c217a..92c619842 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/MappingManager.kt @@ -44,9 +44,7 @@ class MappingManager(private val context: ModContext) : Manager { runCatching { loadCached() }.onFailure { - context.shortToast("Failed to load cached mappings ${it.message}") - Logger.xposedLog(it) - context.delayForceCloseApp(1000) + context.crash("Failed to load cached mappings ${it.message}", it) } if (snapBuildNumber != currentBuildNumber) { @@ -60,9 +58,7 @@ class MappingManager(private val context: ModContext) : Manager { }.onSuccess { context.shortToast("Generated mappings for build $snapBuildNumber") }.onFailure { - context.shortToast("Failed to generate mappings ${it.message}") - Logger.xposedLog(it) - context.delayForceCloseApp(1000) + context.crash("Failed to generate mappings ${it.message}", it) } } diff --git a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/TranslationManager.kt b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/TranslationManager.kt index 5f99d8a2b..1f930f05a 100644 --- a/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/TranslationManager.kt +++ b/app/src/main/kotlin/me/rhunk/snapenhance/manager/impl/TranslationManager.kt @@ -1,5 +1,7 @@ package me.rhunk.snapenhance.manager.impl +import com.google.gson.JsonParser +import me.rhunk.snapenhance.Logger import me.rhunk.snapenhance.ModContext import me.rhunk.snapenhance.manager.Manager import java.util.* @@ -7,13 +9,32 @@ import java.util.* class TranslationManager( private val context: ModContext ) : Manager { + private val translationMap = mutableMapOf() + lateinit var locale: Locale + override fun init() { + val messageLocaleResult = context.bridgeClient.fetchTranslations(); + locale = Locale(messageLocaleResult.locale!!) + + val translations = JsonParser.parseString(messageLocaleResult.content?.toString(Charsets.UTF_8)).asJsonObject + if (translations == null || translations.isJsonNull) { + context.crash("Failed to fetch translations") + return + } + translations.asJsonObject.entrySet().forEach { + if (it.value.isJsonPrimitive) { + translationMap[it.key] = it.value.asString + } + if (!it.value.isJsonObject) return@forEach + it.value.asJsonObject.entrySet().forEach { entry -> + translationMap["${it.key}.${entry.key}"] = entry.value.asString + } + } } - fun getLocale(): Locale = Locale.getDefault() fun get(key: String): String { - return key + return translationMap[key] ?: key.also { Logger.xposedLog("Missing translation for $key") } } } \ No newline at end of file diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml deleted file mode 100644 index 0d2c4cc40..000000000 --- a/app/src/main/res/values-fr/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0d7eee6bf..2a6df4458 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,33 +1,3 @@ Snap Enhance - Save folder - Prevent read receipts - Hide Bitmoji presence - Show message content - Message logger - Media downloader feature - Download stories - Download public stories - Download spotlight - Overlay merge - Download in chat snaps - Disable metrics - Prevent screenshot - Anonymous story view - Hide typing notification - Menu slot id - Message preview length - Auto save - External media as snap - Conversation export - Snapchat Plus - Remove voice record button - Remove stickers button - Remove cognac button - Remove call buttons - Long snap sending - Block ads - Streak Expiration Info - New map ui - Use download manager \ No newline at end of file