Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ability to change localization in app #637

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions Xcodes.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,7 @@
nl,
pl,
ar,
fa,
);
mainGroup = CAD2E7952449574E00113D76;
packageReferences = (
Expand Down Expand Up @@ -1142,7 +1143,7 @@
CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT = ZU6GR6B2FY;
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
DEVELOPMENT_TEAM = ZU6GR6B2FY;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "$(SRCROOT)/$(TARGET_NAME)/Info.plist";
MARKETING_VERSION = 2.0.0;
Expand Down Expand Up @@ -1192,10 +1193,10 @@
buildSettings = {
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT = ZU6GR6B2FY;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
CREATE_INFOPLIST_SECTION_IN_BINARY = YES;
DEVELOPMENT_TEAM = ZU6GR6B2FY;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
INFOPLIST_FILE = "$(SRCROOT)/$(TARGET_NAME)/Info.plist";
MARKETING_VERSION = 2.0.0;
Expand Down Expand Up @@ -1340,12 +1341,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT = ZU6GR6B2FY;
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 28;
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
DEVELOPMENT_TEAM = ZU6GR6B2FY;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Xcodes/Resources/Info.plist;
Expand All @@ -1368,12 +1369,12 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGNING_SUBJECT_ORGANIZATIONAL_UNIT = ZU6GR6B2FY;
CODE_SIGN_ENTITLEMENTS = Xcodes/Resources/Xcodes.entitlements;
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "-";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 28;
DEVELOPMENT_ASSET_PATHS = "\"Xcodes/Preview Content\"";
DEVELOPMENT_TEAM = ZU6GR6B2FY;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_PREVIEWS = YES;
INFOPLIST_FILE = Xcodes/Resources/Info.plist;
Expand All @@ -1397,7 +1398,7 @@
BUNDLE_LOADER = "$(TEST_HOST)";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = ZU6GR6B2FY;
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = XcodesTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
Expand Down
10 changes: 9 additions & 1 deletion Xcodes/Backend/AppState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class AppState: ObservableObject {
/// Whether the user is being prepared for the helper installation alert with an explanation.
/// This closure will be performed after the user chooses whether or not to proceed.
@Published var isPreparingUserForActionRequiringHelper: ((Bool) -> Void)?

// MARK: - Errors

@Published var error: Error?
Expand Down Expand Up @@ -136,6 +136,14 @@ class AppState: ObservableObject {
}
}


@Published var appLanguage: String? {
didSet {
Current.defaults.set(appLanguage, forKey: "appLanguage")
}

}

// MARK: - Runtimes

@Published var downloadableRuntimes: [DownloadableRuntime] = []
Expand Down
40 changes: 39 additions & 1 deletion Xcodes/Frontend/Preferences/GeneralPreferencePane.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import SwiftUI

struct GeneralPreferencePane: View {
@EnvironmentObject var appState: AppState

@State var languages: [String: String] = [:]
@State var currentLanguage: String? = ""
var body: some View {
VStack(alignment: .leading) {
GroupBox(label: Text("AppleID")) {
Expand All @@ -19,6 +20,23 @@ struct GeneralPreferencePane: View {
GroupBox(label: Text("Notifications")) {
NotificationsView().environmentObject(appState)
}

.groupBoxStyle(PreferencesGroupBoxStyle())
Divider()
GroupBox(label: Text("Language")) {
Picker("", selection: $currentLanguage) {
ForEach(languages.values.sorted(), id: \.self) { language in
Text(language)
.tag(language)
}
}
.onChange(of: currentLanguage!) { newLanguage in
if let langKey = languages.first(where: { $0.value == newLanguage })?.key {
changeAppLanguage(to: langKey)
}

}
}
.groupBoxStyle(PreferencesGroupBoxStyle())
Divider()

Expand All @@ -27,6 +45,26 @@ struct GeneralPreferencePane: View {
}
.groupBoxStyle(PreferencesGroupBoxStyle())
}
.onAppear {
languages = getLocalizedLanguages()
currentLanguage = languages[Current.defaults.string(forKey: "appLanguage") ?? "en"]
}
}

func getLocalizedLanguages() -> [String : String] {
let langIds = Bundle.main.localizations
var languages = [String:String]()
for langId in langIds {
let loc = Locale(identifier: langId)
if let name = loc.localizedString(forLanguageCode: langId) {
languages[langId] = name
}
}
return languages
}

func changeAppLanguage(to languageCode: String) {
self.appState.appLanguage = languageCode
}
}

Expand Down
7 changes: 7 additions & 0 deletions Xcodes/XcodesApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ struct XcodesApp: App {
MainWindow()
.environmentObject(appState)
.environmentObject(updater)
.environment(\.locale, Locale(identifier: Current.defaults.string(forKey: "appLanguage") ?? "en"))
// .environment(\.layoutDirection, Current.defaults.string(forKey: "appLanguage") ?? "en" == "fa" ? .rightToLeft : .leftToRight)
// This is intentionally used on a View, and not on a WindowGroup,
// so that it's triggered when an individual window's phase changes instead of all window phases.
// When used on a View it's also invoked on launch, which doesn't occur with a WindowGroup.
Expand Down Expand Up @@ -73,6 +75,8 @@ struct XcodesApp: App {
PreferencesView()
.environmentObject(appState)
.environmentObject(updater)
.environment(\.locale, Locale(identifier: Current.defaults.string(forKey: "appLanguage") ?? "en"))
.environment(\.layoutDirection, Current.defaults.string(forKey: "appLanguage") ?? "en" == "fa" ? .rightToLeft : .leftToRight)
.alert(item: $appState.presentedPreferenceAlert, content: { presentedAlert in
alert(for: presentedAlert)
})
Expand All @@ -81,6 +85,9 @@ struct XcodesApp: App {
Window("Platforms", id: "platforms") {
PlatformsListView()
.environmentObject(appState)
.environmentObject(updater)
.environment(\.locale, Locale(identifier: Current.defaults.string(forKey: "appLanguage") ?? "en"))
.environment(\.layoutDirection, Current.defaults.string(forKey: "appLanguage") ?? "en" == "fa" ? .rightToLeft : .leftToRight)
.alert(item: $appState.presentedPreferenceAlert, content: { presentedAlert in
alert(for: presentedAlert)
})
Expand Down