8000 GitHub - MTACS/PreferenceLocalizer: Quickly change language of Settings app for testing localizations
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

MTACS/PreferenceLocalizer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

PreferenceLocalizer

Available on mtac.app

#import <UIKit/UIKit.h>
#import <Preferences/PSListController.h>
#include <rootless.h>

extern "C" void BKSTerminateApplicationForReasonAndReportWithDescription(NSString *bundleID, int reasonID, bool report, NSString *description);

@import SafariServices;

@interface PSUIPrefsListController : PSListController
@end

@interface UINavigationController (PL)
@property (readonly, nonatomic) UINavigationBar *navigationBar;
@end

@interface UINavigationBar (PL) <UIContextMenuInteractionDelegate>
@end

@interface UIView (PL)
- (UIViewController *)_viewControllerForAncestor;
@end

@interface SpringBoard: NSObject
+ (id)sharedApplication;
- (void)launchApplicationWithIdentifier:(NSString *)identifier suspended:(BOOL)suspended;
@end

void setApplicationLanguage(NSString *languageCode) {
	if (languageCode == nil) {
		[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"AppleLanguages"]; // Setting this will force change of locale
	} else {
		[[NSUserDefaults standardUserDefaults] setObject:[NSArray arrayWithObjects:languageCode, nil] forKey:@"AppleLanguages"];
	}
	[[NSUserDefaults standardUserDefaults] synchronize];

	CFNotificationCenterPostNotification(CFNotificationCenterGetDarwinNotifyCenter(), (CFStringRef)@"com.mtac.preference.localizer/relaunchSettings", nil, nil, true); // Send relaunch notification
	[[UIApplication sharedApplication] performSelector:@selector(suspend) withObject:nil afterDelay:0]; // Suspend Settings
}

NSArray *languageList() {
	NSFileManager *manager = [NSFileManager defaultManager];
	NSArray *settingsContent = [manager contentsOfDirectoryAtPath:@"/Applications/Preferences.app" error:nil];
	NSMutableArray *languageList = [NSMutableArray new];
	for (NSString *item in settingsContent) {
		if ([item.pathExtension isEqualToString:@"lproj"]) {
			[languageList addObject:[item stringByDeletingPathExtension]];
		}
	}
	return [languageList sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];
}

%group Preferences
%hook UINavigationBar
- (void)didMoveToWindow {
	%orig;
	UIContextMenuInteraction *menuInteraction = [[UIContextMenuInteraction alloc] initWithDelegate:self];
	[self addInteraction:menuInteraction]; // Add interaction to all navigation bars
	NSLog(@"[+] PL DEBUG: List -> %@", languageList());
}
%new
- (UIContextMenuConfiguration *)contextMenuInteraction:(UIContextMenuInteraction *)interaction configurationForMenuAtLocation:(CGPoint)location {
    UIContextMenuConfiguration *config = [UIContextMenuConfiguration configurationWithIdentifier:nil previewProvider:nil actionProvider:^UIMenu* _Nullable(NSArray<UIMenuElement*>* _Nonnull suggestedActions) {
        NSLocale *locale = [NSLocale autoupdatingCurrentLocale];
		NSMutableArray *languages = [NSMutableArray new];
		for (NSString *language in languageList()) {
			NSString *languageDisplayName = [locale localizedStringForLanguageCode:language];
			UIAction *languageAction = [UIAction actionWithTitle:[NSString stringWithFormat:@"%@%@", languageDisplayName, language] image:nil identifier:nil handler:^(__kindof UIAction *_Nonnull action) {
				setApplicationLanguage(language); 
			}];
			[languages addObject:languageAction];
		}
		
		UIMenu *languageList = [UIMenu menuWithTitle:@"Set Language" image:[UIImage systemImageNamed:@"globe"] identifier:nil options:0 children:languages];

		UIAction *resetAction = [UIAction actionWithTitle:@"Reset" image:[UIImage systemImageNamed:@"arrow.clockwise.circle.fill"] identifier:nil handler:^(__kindof UIAction *_Nonnull action) {
			setApplicationLanguage(nil);
        }];
		resetAction.attributes = UIMenuElementAttributesDestructive;

        UIMenu *menu = [UIMenu menuWithTitle:@"" children:@[languageList, resetAction]];
        return menu;
    }];
    return config;
}
%new
- (UITargetedPreview *)contextMenuInteraction:(UIContextMenuInteraction *)interaction previewForHighlightingMenuWithConfiguration:(UIContextMenuConfiguration *)configuration {
    UIPreviewParameters *params = [[UIPreviewParameters alloc] init];
    params.backgroundColor = [UIColor clearColor];
    params.shadowPath = [UIBezierPath bezierPath];
    
    UITargetedPreview *preview = [[UITargetedPreview alloc] initWithView:self parameters:params];
    return preview;
}
%end
%end

%group SpringBoard
void relaunchSettings() {
	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
		BKSTerminateApplicationForReasonAndReportWithDescription(@"com.apple.Preferences", 5, false, NULL); // Terminate Settings
	});
	dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
		[((SpringBoard *)[%c(SpringBoard) sharedApplication]) launchApplicationWithIdentifier:@"com.apple.Preferences" suspended:0]; // Relaunch after delay
	});
}
%end

%ctor {
	NSString *bundleID = [[NSBundle mainBundle] bundleIdentifier];
	if ([bundleID isEqualToString:@"com.apple.Preferences"]) {
		%init(Preferences);
	} 
	if ([bundleID isEqualToString:@"com.apple.springboard"]) {
		CFNotificationCenterAddObserver(CFNotificationCenterGetDarwinNotifyCenter(), NULL, (CFNotificationCallback)relaunchSettings, (CFStringRef)@"com.mtac.preference.localizer/relaunchSettings", NULL, (CFNotificationSuspensionBehavior)kNilOptions);
	}
}

About

Quickly change language of Settings app for testing localizations

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published
0