Skip to content

Commit

Permalink
App Language preference (#468)
Browse files Browse the repository at this point in the history
* modify localized bundle pointer by runtime

* swiftui localized

* 删除log

* use swift to implement EZLocalizedBundle

* remove the EZ prefix in swift.

* optimize code

* Update Easydict/Feature/ViewController/Window/BaseQueryWindow/EZBaseQueryViewController.m

Co-authored-by: Phillip Song <103433299+phlpsong@users.noreply.github.com>

* Update Easydict/NewApp/LanguagePreference/I18nHelper.swift

Co-authored-by: Phillip Song <103433299+phlpsong@users.noreply.github.com>

* Update Easydict/NewApp/LanguagePreference/I18nHelper.swift

Co-authored-by: Phillip Song <103433299+phlpsong@users.noreply.github.com>

* rename

---------

Co-authored-by: Phillip Song <103433299+phlpsong@users.noreply.github.com>
Co-authored-by: Tisfeng <tisfeng@gmail.com>
  • Loading branch information
3 people authored Mar 24, 2024
1 parent b90b336 commit a86f56c
Show file tree
Hide file tree
Showing 15 changed files with 207 additions and 25 deletions.
24 changes: 24 additions & 0 deletions Easydict.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,10 @@
62E2BF4B2B4082BA00E42D38 /* AliResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E2BF482B4082BA00E42D38 /* AliResponse.swift */; };
62E2BF4C2B4082BA00E42D38 /* AliTranslateType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 62E2BF492B4082BA00E42D38 /* AliTranslateType.swift */; };
62ED29A22B15F1F500901F51 /* EZWrapView.m in Sources */ = {isa = PBXBuildFile; fileRef = 62ED29A12B15F1F500901F51 /* EZWrapView.m */; };
6A8C988E2BAC88B500DB835A /* LanguageState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8C988C2BAC88B500DB835A /* LanguageState.swift */; };
6A8C988F2BAC88B500DB835A /* I18nHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8C988D2BAC88B500DB835A /* I18nHelper.swift */; };
6A8C98952BAE841600DB835A /* LocalizedBundle.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6A8C98942BAE841600DB835A /* LocalizedBundle.swift */; };
6ADED1552BAE8809004A15BE /* NSBundle+LanguagePreference.m in Sources */ = {isa = PBXBuildFile; fileRef = 6ADED1542BAE8809004A15BE /* NSBundle+LanguagePreference.m */; };
960835502B6791F200C6A931 /* Shortcut+Validator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9608354F2B6791F200C6A931 /* Shortcut+Validator.swift */; };
96099AE22B5D40330055C4DD /* ShortcutTab.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96099AE12B5D40330055C4DD /* ShortcutTab.swift */; };
9627F9382B59956800B1E999 /* GlobalShortcutSetting.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9627F9352B59956800B1E999 /* GlobalShortcutSetting.swift */; };
Expand Down Expand Up @@ -801,6 +805,10 @@
62ED29A02B15F1F500901F51 /* EZWrapView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = EZWrapView.h; sourceTree = "<group>"; };
62ED29A12B15F1F500901F51 /* EZWrapView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = EZWrapView.m; sourceTree = "<group>"; };
6372B33DFF803C7096A82250 /* Pods_Easydict.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Easydict.framework; sourceTree = BUILT_PRODUCTS_DIR; };
6A8C988C2BAC88B500DB835A /* LanguageState.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LanguageState.swift; sourceTree = "<group>"; };
6A8C988D2BAC88B500DB835A /* I18nHelper.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = I18nHelper.swift; sourceTree = "<group>"; };
6A8C98942BAE841600DB835A /* LocalizedBundle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalizedBundle.swift; sourceTree = "<group>"; };
6ADED1542BAE8809004A15BE /* NSBundle+LanguagePreference.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "NSBundle+LanguagePreference.m"; sourceTree = "<group>"; };
91E3E579C6DB88658B4BB102 /* Pods-Easydict.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Easydict.release.xcconfig"; path = "Target Support Files/Pods-Easydict/Pods-Easydict.release.xcconfig"; sourceTree = "<group>"; };
9608354F2B6791F200C6A931 /* Shortcut+Validator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Shortcut+Validator.swift"; sourceTree = "<group>"; };
96099AE12B5D40330055C4DD /* ShortcutTab.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShortcutTab.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2164,6 +2172,7 @@
27FE98032B3DCA9F000AD654 /* NewApp */ = {
isa = PBXGroup;
children = (
6A8C988B2BAC88A600DB835A /* LanguagePreference */,
967712EB2B5B93E200105E0F /* Feature */,
EA9943E12B534C2900EE7B97 /* Model */,
EA9943DD2B534BAE00EE7B97 /* Utility */,
Expand Down Expand Up @@ -2248,6 +2257,17 @@
path = EZWrapView;
sourceTree = "<group>";
};
6A8C988B2BAC88A600DB835A /* LanguagePreference */ = {
isa = PBXGroup;
children = (
6A8C988D2BAC88B500DB835A /* I18nHelper.swift */,
6A8C988C2BAC88B500DB835A /* LanguageState.swift */,
6A8C98942BAE841600DB835A /* LocalizedBundle.swift */,
6ADED1542BAE8809004A15BE /* NSBundle+LanguagePreference.m */,
);
path = LanguagePreference;
sourceTree = "<group>";
};
713A345D86B5BC86D158B68F /* Frameworks */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -2889,6 +2909,7 @@
960835502B6791F200C6A931 /* Shortcut+Validator.swift in Sources */,
03542A522937B69200C34C33 /* EZYoudaoTranslateResponse.m in Sources */,
03B0230129231FA6001C7E63 /* EZQueryView.m in Sources */,
6A8C988E2BAC88B500DB835A /* LanguageState.swift in Sources */,
03542A3D2937AF4F00C34C33 /* EZQueryResult.m in Sources */,
03262C1F29EF8EE500EFECA0 /* EZPrivacyViewController.m in Sources */,
9672D7D22B4008B40023B8FB /* MASShortcutBinder+EZMASShortcutBinder.m in Sources */,
Expand Down Expand Up @@ -2935,6 +2956,7 @@
03B0230229231FA6001C7E63 /* EZWordResultView.m in Sources */,
0399C6A529A747E600B4AFCC /* EZDeepLTranslateResponse.m in Sources */,
17BCAEF82B0DFF9000A7D372 /* EZNiuTransTranslate.m in Sources */,
6A8C98952BAE841600DB835A /* LocalizedBundle.swift in Sources */,
039F5506294B6E29004AB940 /* EZSettingViewController.m in Sources */,
03BD281E29481C0400F5891A /* EZAudioPlayer.m in Sources */,
0A8685C82B552A590022534F /* DisabledAppTab.swift in Sources */,
Expand Down Expand Up @@ -3013,9 +3035,11 @@
03B0231729231FA6001C7E63 /* Snip.m in Sources */,
03BFFC6E295FE59C004E033E /* EZQueryResult+EZYoudaoDictModel.m in Sources */,
DC3C643F2B187119008EEDD8 /* ChangeFontSizeView.swift in Sources */,
6ADED1552BAE8809004A15BE /* NSBundle+LanguagePreference.m in Sources */,
03B0232829231FA6001C7E63 /* NSTextView+Height.m in Sources */,
03B0232129231FA6001C7E63 /* NSPasteboard+MM.m in Sources */,
03D043522928935300E7559E /* EZMainQueryWindow.m in Sources */,
6A8C988F2BAC88B500DB835A /* I18nHelper.swift in Sources */,
03D8B26E292DBD2000D5A811 /* EZCoordinateUtils.m in Sources */,
03B0232029231FA6001C7E63 /* NSWindow+MM.m in Sources */,
0AC8A8432B6957B0006DA5CC /* BingService+ConfigurableService.swift in Sources */,
Expand Down
51 changes: 34 additions & 17 deletions Easydict/App/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -1761,6 +1761,23 @@
}
}
},
"language_preference" : {
"extractionState" : "manual",
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Display Language"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "显示语言"
}
}
}
},
"large" : {
"extractionState" : "manual",
"localizations" : {
Expand Down Expand Up @@ -2675,22 +2692,6 @@
}
}
},
"service.configuration.custom_openai.name.title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Custom Service Name"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "自定义服务名称"
}
}
}
},
"service.configuration.custom_openai.model.placeholder" : {
"localizations" : {
"en" : {
Expand All @@ -2707,6 +2708,22 @@
}
}
},
"service.configuration.custom_openai.name.title" : {
"localizations" : {
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Custom Service Name"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "自定义服务名称"
}
}
}
},
"service.configuration.custom_openai.supported_models.title" : {
"localizations" : {
"en" : {
Expand Down Expand Up @@ -4634,4 +4651,4 @@
}
},
"version" : "1.0"
}
}
2 changes: 2 additions & 0 deletions Easydict/App/PrefixHeader.pch
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,5 @@
#import "EZConst.h"
#import "EZConstKey.h"
#import "NSString+EZConvenience.h"

#import "Easydict-Swift.h"
2 changes: 1 addition & 1 deletion Easydict/Feature/Service/Language/EZLanguageManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ - (NSString *)languageLocalName:(EZLanguage)language {
/// Showing language name according user first language, Chinese: English -> 英语, English: English -> English.
- (NSString *)showingLanguageName:(EZLanguage)language {
NSString *languageName = language ?: EZLanguageAuto;
if ([self isSystemChineseFirstLanguage]) {
if (EZI18nHelper.shared.isSimplifiedChineseLocalize) {
languageName = [self languageChineseName:language];
} else {
if ([language isEqualToString:EZLanguageAuto]) {
Expand Down
6 changes: 3 additions & 3 deletions Easydict/Feature/Utility/EZCategory/NSObject+EZWindowType.m
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@

#import "NSObject+EZWindowType.h"

static NSString *EZWindowTypeKey = @"EZWindowTypeKey";
static NSString *_EZWindowTypeKey = @"EZWindowTypeKey";

@implementation NSObject (EZWindowType)

- (void)setWindowType:(EZWindowType)windowType {
objc_setAssociatedObject(self, (__bridge const void *)(EZWindowTypeKey), @(windowType), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(self, (__bridge const void *)(_EZWindowTypeKey), @(windowType), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

- (EZWindowType)windowType {
return [objc_getAssociatedObject(self, (__bridge const void *)(EZWindowTypeKey)) integerValue];
return [objc_getAssociatedObject(self, (__bridge const void *)(_EZWindowTypeKey)) integerValue];
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ extension Notification.Name {
static let serviceHasUpdated = Notification.Name(EZServiceHasUpdatedNotification)

static let openSettings = Notification.Name(EZOpenSettingsNotification)

static let languagePreferenceChanged = Notification.Name(I18nHelper.languagePreferenceChangedNotification)
}

@objc
extension NSNotification {
public static let serviceHasUpdated = Notification.Name.serviceHasUpdated

public static let openSettings = Notification.Name.openSettings

public static let languagePreferenceChanged = Notification.Name.languagePreferenceChanged
}
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ - (void)setupMenu {
NSString *languageFlag = [languageManager languageFlagEmoji:language];

if ([language isEqualToString:EZLanguageAuto]) {
if ([languageManager isSystemChineseFirstLanguage] && self.autoChineseSelectedTitle.length) {
if (EZI18nHelper.shared.isSimplifiedChineseLocalize && self.autoChineseSelectedTitle.length) {
languageName = self.autoChineseSelectedTitle;
}
}
Expand Down Expand Up @@ -171,7 +171,7 @@ - (void)setSelectedLanguage:(EZLanguage)selectedLanguage {
NSString *toolTip = nil;

if ([selectedLanguage isEqualToString:EZLanguageAuto]) {
if ([languageManager isSystemChineseFirstLanguage] && self.autoChineseSelectedTitle.length) {
if (EZI18nHelper.shared.isSimplifiedChineseLocalize && self.autoChineseSelectedTitle.length) {
languageName = self.autoChineseSelectedTitle;
}
languageFlag = [languageManager languageFlagEmoji:self.autoSelectedLanguage];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ - (void)setupUI {
[self updateAllResultCellHeight];
}];
}];

[defaultCenter addObserver:self selector:@selector(modifyLanduage:) name:NSNotification.languagePreferenceChanged object:nil];
}

- (void)modifyLanduage:(NSNotification *)notification {
[self.tableView reloadData];
}


Expand Down
8 changes: 7 additions & 1 deletion Easydict/NewApp/EasydictApp.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ struct EasydictApp: App {
if #available(macOS 13, *) {
MenuBarExtra(isInserted: $hideMenuBar.toggledValue) {
MenuItemView()
.environmentObject(languageState)
.environment(\.locale, .init(identifier: I18nHelper.shared.localizeCode))
} label: {
Label {
Text("Easydict")
Expand Down Expand Up @@ -62,7 +64,10 @@ struct EasydictApp: App {
.windowResizability(.contentSize)

Settings {
SettingView()
SettingView().environmentObject(languageState).environment(
\.locale,
.init(identifier: I18nHelper.shared.localizeCode)
)
}
}
}
Expand All @@ -77,6 +82,7 @@ struct EasydictApp: App {
private var hideMenuBar = Defaults.Key<Bool>.hideMenuBarIcon.defaultValue

@Default(.selectedMenuBarIcon) private var menuBarIcon
@StateObject private var languageState = LanguageState()
}

// MARK: - FakeViewToOpenSettingsInSonoma
Expand Down
39 changes: 39 additions & 0 deletions Easydict/NewApp/LanguagePreference/I18nHelper.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
//
// I18nHelper.swift
// Easydict
//
// Created by choykarl on 2024/3/4.
// Copyright © 2024 izual. All rights reserved.
//

import SwiftUI

// MARK: - I18nHelper

@objcMembers
@objc(EZI18nHelper)
class I18nHelper: NSObject {
static let languagePreferenceChangedNotification = "LanguagePreferenceChangedNotification"
static let shared = I18nHelper()

var localizedBundle: Bundle {
guard let path = Bundle.main.path(forResource: localizeCode, ofType: "lproj"),
let bundle = Bundle(path: path) else {
return .main
}
return bundle
}

var localizeCode: String {
UserDefaults.standard.string(forKey: languagePreferenceLocalKey) ?? LanguageState.LanguageType
.simplifiedChinese.rawValue
}

var languageType: LanguageState.LanguageType {
LanguageState.LanguageType(rawValue: localizeCode) ?? .simplifiedChinese
}

var isSimplifiedChineseLocalize: Bool {
localizeCode == LanguageState.LanguageType.simplifiedChinese.rawValue
}
}
41 changes: 41 additions & 0 deletions Easydict/NewApp/LanguagePreference/LanguageState.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
//
// LanguageState.swift
// Easydict
//
// Created by choykarl on 2024/3/3.
// Copyright © 2024 izual. All rights reserved.
//

import SwiftUI

// MARK: - LanguageState

let languagePreferenceLocalKey = "LanguagePreferenceLocalKey"

// MARK: - LanguageState

class LanguageState: ObservableObject {
enum LanguageType: String, CaseIterable {
case english = "en"
case simplifiedChinese = "zh-Hans"

// MARK: Internal

var name: String {
switch self {
case .english:
"English"
case .simplifiedChinese:
"简体中文"
}
}
}

@AppStorage(languagePreferenceLocalKey) var language: LanguageType = (.init(
rawValue: Locale.current.identifier
) ?? .simplifiedChinese) {
didSet {
NotificationCenter.default.post(name: .languagePreferenceChanged, object: nil)
}
}
}
16 changes: 16 additions & 0 deletions Easydict/NewApp/LanguagePreference/LocalizedBundle.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//
// LocalizedBundle.swift
// Easydict
//
// Created by choykarl on 2024/3/23.
// Copyright © 2024 izual. All rights reserved.
//

import Foundation

@objc(EZLocalizedBundle)
class LocalizedBundle: Bundle {
override func localizedString(forKey key: String, value: String?, table tableName: String?) -> String {
I18nHelper.shared.localizedBundle.localizedString(forKey: key, value: value, table: tableName)
}
}
20 changes: 20 additions & 0 deletions Easydict/NewApp/LanguagePreference/NSBundle+LanguagePreference.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// NSBundle+LanguagePreference.m
// Easydict
//
// Created by choykarl on 2024/3/23.
// Copyright © 2024 izual. All rights reserved.
//

#import <objc/runtime.h>

@implementation NSBundle (LanguagePreference)

+ (void)load {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
object_setClass([NSBundle mainBundle], [EZLocalizedBundle class]);
});
}

@end
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ extension Language {
}

public var localizedName: String {
if EZLanguageManager.shared().isSystemChineseFirstLanguage() {
if I18nHelper.shared.isSimplifiedChineseLocalize {
chineseName
} else {
if self == .auto {
Expand Down
Loading

0 comments on commit a86f56c

Please sign in to comment.