feat(macos): 实现 macOS 系统菜单栏多语言支持与闪退修复

本次提交完成 macOS 端多项关键优化与修复:
1. 修复启动期竞态闪退问题,通过前移窗口属性初始化、串行化特效调用、跳过首次同步实现稳定启动
2. 实现系统菜单栏多语言本地化,支持中英日韩繁五种语言,软件内切换语言可同步更新菜单栏
3. 移除视图菜单中重复的全屏按钮,统一窗口标题栏逻辑
4. 新增 macOS App Store 打包配置与本地化资源
This commit is contained in:
Developer
2026-06-24 08:35:08 +08:00
parent 6119918185
commit 93d580fa1e
19 changed files with 958 additions and 37 deletions

14
macos/ExportOptions.plist Normal file
View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>app-store</string>
<key>teamID</key>
<string>5V9NVUU6K5</string>
<key>uploadSymbols</key>
<false/>
<key>uploadBitcode</key>
<false/>
</dict>
</plist>

View File

@@ -29,6 +29,7 @@
33CC11132044BFA00003C045 /* MainFlutterWindow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC11122044BFA00003C045 /* MainFlutterWindow.swift */; };
69AC2FD7F25C22464C6AA971 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5EAD42DE88C17A1D7496A378 /* Pods_RunnerTests.framework */; };
740419A3DA2BFE0F5E85D9AF /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9097D4D2EB98F14D8827394A /* Pods_Runner.framework */; };
A1B2C3D4E5F6000000000007 /* MainMenu.strings in Resources */ = {isa = PBXBuildFile; fileRef = A1B2C3D4E5F6000000000006 /* MainMenu.strings */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -66,7 +67,7 @@
331C80D7294CF71000263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
333000ED22D3DE5D00554162 /* Warnings.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Warnings.xcconfig; sourceTree = "<group>"; };
335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GeneratedPluginRegistrant.swift; sourceTree = "<group>"; };
33CC10ED2044A3C60003C045 /* s2ss.com */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = s2ss.com; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10ED2044A3C60003C045 /* xianyan.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = xianyan.app; sourceTree = BUILT_PRODUCTS_DIR; };
33CC10F02044A3C60003C045 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
33CC10F22044A3C60003C045 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Runner/Assets.xcassets; sourceTree = "<group>"; };
33CC10F52044A3C60003C045 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
@@ -84,6 +85,11 @@
9097D4D2EB98F14D8827394A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = "<group>"; };
9DF906408CB20CD31706ACF0 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
A1B2C3D4E5F6000000000001 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/MainMenu.strings; sourceTree = "<group>"; };
A1B2C3D4E5F6000000000002 /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/MainMenu.strings"; sourceTree = "<group>"; };
A1B2C3D4E5F6000000000003 /* zh-Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hant"; path = "zh-Hant.lproj/MainMenu.strings"; sourceTree = "<group>"; };
A1B2C3D4E5F6000000000004 /* ja */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/MainMenu.strings; sourceTree = "<group>"; };
A1B2C3D4E5F6000000000005 /* ko */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ko; path = ko.lproj/MainMenu.strings; sourceTree = "<group>"; };
CC173CB9C4D834544F95E13C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
E124C85A506C3CD1E10E0BF4 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
F3F87547C10EAEA1CDC2EAC9 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
@@ -144,7 +150,7 @@
33CC10EE2044A3C60003C045 /* Products */ = {
isa = PBXGroup;
children = (
33CC10ED2044A3C60003C045 /* s2ss.com */,
33CC10ED2044A3C60003C045 /* xianyan.app */,
331C80D5294CF71000263BE5 /* RunnerTests.xctest */,
);
name = Products;
@@ -155,6 +161,7 @@
children = (
33CC10F22044A3C60003C045 /* Assets.xcassets */,
33CC10F42044A3C60003C045 /* MainMenu.xib */,
A1B2C3D4E5F6000000000006 /* MainMenu.strings */,
33CC10F72044A3C60003C045 /* Info.plist */,
);
name = Resources;
@@ -195,7 +202,6 @@
475082748095A981E9B2017D /* Pods-RunnerTests.release.xcconfig */,
9DF906408CB20CD31706ACF0 /* Pods-RunnerTests.profile.xcconfig */,
);
name = Pods;
path = Pods;
sourceTree = "<group>";
};
@@ -249,7 +255,7 @@
);
name = Runner;
productName = Runner;
productReference = 33CC10ED2044A3C60003C045 /* s2ss.com */;
productReference = 33CC10ED2044A3C60003C045 /* xianyan.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
@@ -289,6 +295,10 @@
hasScannedForEncodings = 0;
knownRegions = (
en,
"zh-Hans",
"zh-Hant",
ja,
ko,
Base,
);
mainGroup = 33CC10E42044A3C60003C045;
@@ -317,6 +327,7 @@
files = (
33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */,
33CC10F62044A3C60003C045 /* MainMenu.xib in Resources */,
A1B2C3D4E5F6000000000007 /* MainMenu.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -468,6 +479,19 @@
path = Runner;
sourceTree = "<group>";
};
A1B2C3D4E5F6000000000006 /* MainMenu.strings */ = {
isa = PBXVariantGroup;
children = (
A1B2C3D4E5F6000000000001 /* en */,
A1B2C3D4E5F6000000000002 /* zh-Hans */,
A1B2C3D4E5F6000000000003 /* zh-Hant */,
A1B2C3D4E5F6000000000004 /* ja */,
A1B2C3D4E5F6000000000005 /* ko */,
);
name = MainMenu.strings;
path = Runner;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -729,12 +753,12 @@
isa = XCBuildConfiguration;
baseConfigurationReference = 33E5194F232828860026EE4D /* AppInfo.xcconfig */;
buildSettings = {
ARCHS = "$(ARCHS_STANDARD)";
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
ARCHS = arm64;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = 5V9NVUU6K5;
INFOPLIST_FILE = Runner/Info.plist;

View File

@@ -289,12 +289,6 @@
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="View" id="HyV-fh-RgO">
<items>
<menuItem title="Enter Full Screen" keyEquivalent="f" id="4J7-dP-txa">
<modifierMask key="keyEquivalentModifierMask" control="YES" command="YES"/>
<connections>
<action selector="toggleFullScreen:" target="-1" id="dU3-MA-1Rq"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>

View File

@@ -4,6 +4,14 @@
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleLocalizations</key>
<array>
<string>en</string>
<string>zh-Hans</string>
<string>zh-Hant</string>
<string>ja</string>
<string>ko</string>
</array>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleDisplayName</key>

View File

@@ -3,11 +3,24 @@
/// : 2026-06-02
/// : 2026-06-24
/// : apps.xy.xianyan/macos MethodChannel
/// : 退退
/// : menuItemIds XIB objectId
/// assignMenuItemIdentifiers menuItem identifier
/// setMenuLanguage languageId lproj/MainMenu.strings
/// NSApp.mainMenu
///
/// awakeFromNib
/// MainFlutterWindowManipulator.start(mainFlutterWindow: self)
/// reset() start(nil)
/// contentViewController FlutterViewController
/// MacOSWindowUtilsViewController 使 setMaterial/
/// setNSVisualEffectViewState
/// setExtraFlag fullSizeContentView + titlebarAppearsTransparent
/// 绿 Flutter DesktopWindowTitleBar
/// ============================================================
import Cocoa
import FlutterMacOS
import macos_window_utils
class MainFlutterWindow: NSWindow, NSTouchBarDelegate {
// ============================================================
@@ -23,9 +36,63 @@ class MainFlutterWindow: NSWindow, NSTouchBarDelegate {
override func awakeFromNib() {
let flutterViewController = FlutterViewController()
let windowFrame = self.frame
self.contentViewController = flutterViewController
// 使 MacOSWindowUtilsViewController FlutterViewController
// macos_window_utils setMaterial/setNSVisualEffectViewState/
// addVisualEffectSubview
// `contentViewController as! MacOSWindowUtilsViewController`
// 使 FlutterViewController contentViewController
// "Could not cast value of type 'FlutterViewController' to
// 'MacOSWindowUtilsViewController'"
// MacOSWindowUtilsViewController.loadView() NSVisualEffectView
// addChild(flutterViewController)
let macOSWindowUtilsViewController = MacOSWindowUtilsViewController(
flutterViewController: flutterViewController
)
self.contentViewController = macOSWindowUtilsViewController
self.setFrame(windowFrame, display: true)
// Flutter Impeller
// macos_window_utils setWindowBackgroundColorToClear()
// [NSWindow setBackgroundColor:] NSThemeFrame._updateBackdropView removeFromSuperview
// Impeller raster 线 SetupRenderPass Release
// Dart
self.isOpaque = false
self.backgroundColor = NSColor.clear
self.titlebarAppearsTransparent = true
self.titleVisibility = .hidden
if !self.styleMask.contains(.fullSizeContentView) {
self.styleMask.insert(.fullSizeContentView)
}
// MainFlutterWindowManipulator.start(mainFlutterWindow: self)
// macos_window_utils mainFlutterWindow
// Dart WindowManipulator.initialize() reset()
// mainFlutterWindow == nil start(nil)
// setWindowBackgroundColorToDefaultColor() [NSWindow setBackgroundColor:]
// NSThemeFrame._updateBackdropView removeFromSuperview
// Impeller raster 线 SetupRenderPass EXC_BAD_ACCESS
//
// start() showTitle()/makeTitlebarOpaque()/disableFullSizeContentView()/
// setWindowBackgroundColorToDefaultColor() start()
// Flutter Impeller raster 线
// [NSWindow setBackgroundColor:] 线
//
// mainFlutterWindow: selfstart() isProvidedWindow=true
// configureMainFlutterWindow() contentViewController
// MacOSWindowUtilsViewController FlutterViewController
// configure
MainFlutterWindowManipulator.start(mainFlutterWindow: self)
// start()
self.isOpaque = false
self.backgroundColor = NSColor.clear
self.titlebarAppearsTransparent = true
self.titleVisibility = .hidden
if !self.styleMask.contains(.fullSizeContentView) {
self.styleMask.insert(.fullSizeContentView)
}
RegisterGeneratedPlugins(registry: flutterViewController)
// Flutter MethodChannel MissingPluginException
@@ -40,6 +107,11 @@ class MainFlutterWindow: NSWindow, NSTouchBarDelegate {
object: self
)
// mainMenu menuItem identifierXIB objectId
// 便 setMenuLanguage identifier .strings
// NSApp.mainMenu XIB awakeFromNib mainMenu
self.assignMenuItemIdentifiers()
super.awakeFromNib()
}
@@ -204,6 +276,13 @@ class MainFlutterWindow: NSWindow, NSTouchBarDelegate {
}
result(nil)
// ---------- ----------
case "setMenuLanguage":
let args = call.arguments as? [String: Any] ?? [:]
let languageId = (args["languageId"] as? String) ?? "system"
self.setMenuLanguage(languageId: languageId)
result(nil)
default:
result(FlutterMethodNotImplemented)
}
@@ -299,6 +378,159 @@ class MainFlutterWindow: NSWindow, NSTouchBarDelegate {
)
}
// ============================================================
// MARK: -
// ============================================================
/// XIB menuItem objectId
/// awakeFromNib menuItem identifier
/// separatorItem
/// MainMenu.xib menuItem
private static let menuItemIds: [String] = [
// App Menu +
"1Xt-HY-uBw", "5kV-Vb-QxS", "BOF-NM-1cW", "NMo-om-nkz",
"Olw-nP-bQN", "Vdr-fp-XzO", "Kd2-mp-pUS", "4sb-4s-VLi",
// Edit Menu +
"5QF-Oa-p0T", "dRJ-4n-Yzg", "6dh-zS-Vam", "uRl-iY-unG",
"x3v-GG-iWU", "gVA-U4-sdL", "WeT-3V-zwk", "pa3-QI-u2k",
"Ruw-6m-B2m",
// Edit > Find
"4EN-yA-p0u", "Xz5-n4-O0W", "YEy-JH-Tfz", "q09-fT-Sye",
"OwM-mh-QMV", "buJ-ug-pKt", "S0p-oC-mLd",
// Edit > Spelling and Grammar
"Dv1-io-Yv7", "HFo-cy-zxI", "hz2-CU-CR7", "rbD-Rh-wIN",
"mK6-2p-4JG", "78Y-hA-62v",
// Edit > Substitutions
"9ic-FL-obx", "z6F-FW-3nz", "9yt-4B-nSM", "hQb-2v-fYv",
"rgM-f4-ycn", "cwL-P1-jid", "tRr-pd-1PS", "HFQ-gK-NFA",
// Edit > Transformations
"2oI-Rn-ZJC", "vmV-6d-7jI", "d9M-CD-aMd", "UEZ-Bs-lqG",
// Edit > Speech
"xrE-MZ-jX0", "Ynk-f8-cLZ", "Oyz-dy-DGm",
// View Menu
"H8h-7b-M4v",
// Window Menu +
"aUF-d1-5bR", "OY7-WF-poV", "R4o-n2-Eq4", "LE2-aR-0XJ",
// Help Menu
"EPT-qC-fAb",
]
/// mainMenu menuItem identifierXIB objectId
///
/// XIB menuItem.identifier nil objectId
/// mainMenu menuItemIds objectId
/// menuItem.identifier objectId menuItem
/// separatorItemXIB separator objectId
private func assignMenuItemIdentifiers() {
var index = 0
func assign(_ menu: NSMenu) {
for item in menu.items {
if item.isSeparatorItem { continue }
if index < MainFlutterWindow.menuItemIds.count {
item.identifier = NSUserInterfaceItemIdentifier(
rawValue: MainFlutterWindow.menuItemIds[index]
)
index += 1
}
if let submenu = item.submenu {
assign(submenu)
}
}
}
guard let mainMenu = NSApp.mainMenu else {
NSLog("[assignMenuItemIdentifiers] NSApp.mainMenu 为 nil")
return
}
assign(mainMenu)
NSLog("[assignMenuItemIdentifiers] 已为 \(index) 个菜单项设置 identifier")
}
/// macOS
///
/// [languageId] ID
/// - 'system' / 'auto' 使 preferredLocalizations
/// - 'zh-CN' / 'zh-Hans'
/// - 'zh-TW' / 'zh-Hant'
/// - 'en'
/// - 'ja'
/// - 'ko'
///
///
/// 1. languageId lproj
/// 2. MainMenu.strings [String: String]
/// 3. NSApp.mainMenu menuItem.identifierXIB objectId
/// .strings key"id.title"
/// 4. "APP_NAME" CFBundleName
///
/// action
private func setMenuLanguage(languageId: String) {
// 1. lproj
let lprojName: String
switch languageId {
case "system", "auto":
// preferredLocalizations(from:) Bundle
//
let preferred = Bundle.preferredLocalizations(from: [
"en", "zh-Hans", "zh-Hant", "ja", "ko",
])
lprojName = preferred.first ?? "en"
case "zh-CN", "zh-Hans":
lprojName = "zh-Hans"
case "zh-TW", "zh-Hant":
lprojName = "zh-Hant"
case "en":
lprojName = "en"
case "ja":
lprojName = "ja"
case "ko":
lprojName = "ko"
default:
// 退
lprojName = "en"
}
// 2. MainMenu.strings
guard let stringsPath = Bundle.main.path(
forResource: "MainMenu",
ofType: "strings",
inDirectory: nil,
forLocalization: lprojName
) else {
NSLog("[setMenuLanguage] 未找到 \(lprojName).lproj/MainMenu.strings")
return
}
guard let strings = NSDictionary(contentsOfFile: stringsPath) as? [String: String] else {
NSLog("[setMenuLanguage] 加载 \(lprojName).lproj/MainMenu.strings 失败")
return
}
// 3. mainMenu
let appName = (Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String) ?? "闲言"
var updatedCount = 0
func updateMenu(_ menu: NSMenu) {
for item in menu.items {
if item.isSeparatorItem { continue }
if let identifier = item.identifier?.rawValue {
let key = "\(identifier).title"
if let localized = strings[key] {
// APP_NAME
item.title = localized.replacingOccurrences(of: "APP_NAME", with: appName)
updatedCount += 1
}
}
if let submenu = item.submenu {
updateMenu(submenu)
}
}
}
guard let mainMenu = NSApp.mainMenu else {
NSLog("[setMenuLanguage] NSApp.mainMenu 为 nil")
return
}
updateMenu(mainMenu)
NSLog("[setMenuLanguage] 菜单栏语言已切换为 \(lprojName),更新 \(updatedCount) 个菜单项")
}
// ============================================================
// MARK: - Touch Bar
// ============================================================

View File

@@ -0,0 +1,76 @@
/* ============================================================
* 闲言APP — macOS 主菜单本地化(英语)
* 创建时间: 2026-06-24
* 作用: macOS 系统菜单栏英文文案
* ============================================================ */
/* ===== App Menu ===== */
"1Xt-HY-uBw.title" = "xianyan";
"5kV-Vb-QxS.title" = "About xianyan";
"BOF-NM-1cW.title" = "Preferences…";
"NMo-om-nkz.title" = "Services";
"Olw-nP-bQN.title" = "Hide xianyan";
"Vdr-fp-XzO.title" = "Hide Others";
"Kd2-mp-pUS.title" = "Show All";
"4sb-4s-VLi.title" = "Quit xianyan";
/* ===== Edit Menu ===== */
"5QF-Oa-p0T.title" = "Edit";
"dRJ-4n-Yzg.title" = "Undo";
"6dh-zS-Vam.title" = "Redo";
"uRl-iY-unG.title" = "Cut";
"x3v-GG-iWU.title" = "Copy";
"gVA-U4-sdL.title" = "Paste";
"WeT-3V-zwk.title" = "Paste and Match Style";
"pa3-QI-u2k.title" = "Delete";
"Ruw-6m-B2m.title" = "Select All";
/* ===== Edit > Find ===== */
"4EN-yA-p0u.title" = "Find";
"Xz5-n4-O0W.title" = "Find…";
"YEy-JH-Tfz.title" = "Find and Replace…";
"q09-fT-Sye.title" = "Find Next";
"OwM-mh-QMV.title" = "Find Previous";
"buJ-ug-pKt.title" = "Use Selection for Find";
"S0p-oC-mLd.title" = "Jump to Selection";
/* ===== Edit > Spelling and Grammar ===== */
"Dv1-io-Yv7.title" = "Spelling and Grammar";
"HFo-cy-zxI.title" = "Show Spelling and Grammar";
"hz2-CU-CR7.title" = "Check Document Now";
"rbD-Rh-wIN.title" = "Check Spelling While Typing";
"mK6-2p-4JG.title" = "Check Grammar With Spelling";
"78Y-hA-62v.title" = "Correct Spelling Automatically";
/* ===== Edit > Substitutions ===== */
"9ic-FL-obx.title" = "Substitutions";
"z6F-FW-3nz.title" = "Show Substitutions";
"9yt-4B-nSM.title" = "Smart Copy/Paste";
"hQb-2v-fYv.title" = "Smart Quotes";
"rgM-f4-ycn.title" = "Smart Dashes";
"cwL-P1-jid.title" = "Smart Links";
"tRr-pd-1PS.title" = "Data Detectors";
"HFQ-gK-NFA.title" = "Text Replacement";
/* ===== Edit > Transformations ===== */
"2oI-Rn-ZJC.title" = "Transformations";
"vmV-6d-7jI.title" = "Make Upper Case";
"d9M-CD-aMd.title" = "Make Lower Case";
"UEZ-Bs-lqG.title" = "Capitalize";
/* ===== Edit > Speech ===== */
"xrE-MZ-jX0.title" = "Speech";
"Ynk-f8-cLZ.title" = "Start Speaking";
"Oyz-dy-DGm.title" = "Stop Speaking";
/* ===== View Menu ===== */
"H8h-7b-M4v.title" = "View";
/* ===== Window Menu ===== */
"aUF-d1-5bR.title" = "Window";
"OY7-WF-poV.title" = "Minimize";
"R4o-n2-Eq4.title" = "Zoom";
"LE2-aR-0XJ.title" = "Bring All to Front";
/* ===== Help Menu ===== */
"EPT-qC-fAb.title" = "Help";

View File

@@ -0,0 +1,76 @@
/* ============================================================
* 闲言APP — macOS 主菜单本地化(日语)
* 创建时间: 2026-06-24
* 作用: macOS 系统菜单栏日本語文案
* ============================================================ */
/* ===== App Menu ===== */
"1Xt-HY-uBw.title" = "閑言";
"5kV-Vb-QxS.title" = "閑言について";
"BOF-NM-1cW.title" = "設定…";
"NMo-om-nkz.title" = "サービス";
"Olw-nP-bQN.title" = "閑言を隠す";
"Vdr-fp-XzO.title" = "ほかを隠す";
"Kd2-mp-pUS.title" = "すべてを表示";
"4sb-4s-VLi.title" = "閑言を終了";
/* ===== Edit Menu ===== */
"5QF-Oa-p0T.title" = "編集";
"dRJ-4n-Yzg.title" = "取り消す";
"6dh-zS-Vam.title" = "やり直す";
"uRl-iY-unG.title" = "カット";
"x3v-GG-iWU.title" = "コピー";
"gVA-U4-sdL.title" = "ペースト";
"WeT-3V-zwk.title" = "スタイルを適用してペースト";
"pa3-QI-u2k.title" = "削除";
"Ruw-6m-B2m.title" = "すべてを選択";
/* ===== Edit > Find ===== */
"4EN-yA-p0u.title" = "検索";
"Xz5-n4-O0W.title" = "検索…";
"YEy-JH-Tfz.title" = "検索と置換…";
"q09-fT-Sye.title" = "次を検索";
"OwM-mh-QMV.title" = "前を検索";
"buJ-ug-pKt.title" = "選択部分を検索に使用";
"S0p-oC-mLd.title" = "選択部分へジャンプ";
/* ===== Edit > Spelling and Grammar ===== */
"Dv1-io-Yv7.title" = "スペルと文法";
"HFo-cy-zxI.title" = "スペルと文法を表示";
"hz2-CU-CR7.title" = "今すぐ書類をチェック";
"rbD-Rh-wIN.title" = "入力中にスペルをチェック";
"mK6-2p-4JG.title" = "スペルと一緒に文法をチェック";
"78Y-hA-62v.title" = "スペルを自動的に修正";
/* ===== Edit > Substitutions ===== */
"9ic-FL-obx.title" = "置換";
"z6F-FW-3nz.title" = "置換を表示";
"9yt-4B-nSM.title" = "スマートコピー/ペースト";
"hQb-2v-fYv.title" = "スマート引用符";
"rgM-f4-ycn.title" = "スマートダッシュ";
"cwL-P1-jid.title" = "スマートリンク";
"tRr-pd-1PS.title" = "データ検出";
"HFQ-gK-NFA.title" = "テキスト置換";
/* ===== Edit > Transformations ===== */
"2oI-Rn-ZJC.title" = "変換";
"vmV-6d-7jI.title" = "大文字にする";
"d9M-CD-aMd.title" = "小文字にする";
"UEZ-Bs-lqG.title" = "頭文字を大文字にする";
/* ===== Edit > Speech ===== */
"xrE-MZ-jX0.title" = "スピーチ";
"Ynk-f8-cLZ.title" = "読み上げを開始";
"Oyz-dy-DGm.title" = "読み上げを停止";
/* ===== View Menu ===== */
"H8h-7b-M4v.title" = "表示";
/* ===== Window Menu ===== */
"aUF-d1-5bR.title" = "ウインドウ";
"OY7-WF-poV.title" = "しまう";
"R4o-n2-Eq4.title" = "拡大/縮小";
"LE2-aR-0XJ.title" = "すべてを手前に移動";
/* ===== Help Menu ===== */
"EPT-qC-fAb.title" = "ヘルプ";

View File

@@ -0,0 +1,76 @@
/* ============================================================
* 闲言APP — macOS 主菜单本地化(韩语)
* 创建时间: 2026-06-24
* 作用: macOS 系统菜单栏한국어文案
* ============================================================ */
/* ===== App Menu ===== */
"1Xt-HY-uBw.title" = "한언";
"5kV-Vb-QxS.title" = "한언 정보";
"BOF-NM-1cW.title" = "환경설정…";
"NMo-om-nkz.title" = "서비스";
"Olw-nP-bQN.title" = "한언 숨기기";
"Vdr-fp-XzO.title" = "기타 숨기기";
"Kd2-mp-pUS.title" = "모두 보기";
"4sb-4s-VLi.title" = "한언 종료";
/* ===== Edit Menu ===== */
"5QF-Oa-p0T.title" = "편집";
"dRJ-4n-Yzg.title" = "실행 취소";
"6dh-zS-Vam.title" = "다시 실행";
"uRl-iY-unG.title" = "잘라내기";
"x3v-GG-iWU.title" = "복사";
"gVA-U4-sdL.title" = "붙여넣기";
"WeT-3V-zwk.title" = "스타일 적용하여 붙여넣기";
"pa3-QI-u2k.title" = "삭제";
"Ruw-6m-B2m.title" = "모두 선택";
/* ===== Edit > Find ===== */
"4EN-yA-p0u.title" = "찾기";
"Xz5-n4-O0W.title" = "찾기…";
"YEy-JH-Tfz.title" = "찾기 및 바꾸기…";
"q09-fT-Sye.title" = "다음 찾기";
"OwM-mh-QMV.title" = "이전 찾기";
"buJ-ug-pKt.title" = "선택 항목으로 찾기";
"S0p-oC-mLd.title" = "선택 항목으로 이동";
/* ===== Edit > Spelling and Grammar ===== */
"Dv1-io-Yv7.title" = "맞춤법 및 문법";
"HFo-cy-zxI.title" = "맞춤법 및 문법 표시";
"hz2-CU-CR7.title" = "지금 문서 검사";
"rbD-Rh-wIN.title" = "입력하는 동안 맞춤법 검사";
"mK6-2p-4JG.title" = "맞춤법과 함께 문법 검사";
"78Y-hA-62v.title" = "맞춤법 자동 수정";
/* ===== Edit > Substitutions ===== */
"9ic-FL-obx.title" = "대체";
"z6F-FW-3nz.title" = "대체 표시";
"9yt-4B-nSM.title" = "스마트 복사/붙여넣기";
"hQb-2v-fYv.title" = "스마트 인용 부호";
"rgM-f4-ycn.title" = "스마트 대시";
"cwL-P1-jid.title" = "스마트 링크";
"tRr-pd-1PS.title" = "데이터 감지기";
"HFQ-gK-NFA.title" = "텍스트 대체";
/* ===== Edit > Transformations ===== */
"2oI-Rn-ZJC.title" = "변환";
"vmV-6d-7jI.title" = "대문자로 만들기";
"d9M-CD-aMd.title" = "소문자로 만들기";
"UEZ-Bs-lqG.title" = "첫 글자를 대문자로";
/* ===== Edit > Speech ===== */
"xrE-MZ-jX0.title" = "음성";
"Ynk-f8-cLZ.title" = "말하기 시작";
"Oyz-dy-DGm.title" = "말하기 중지";
/* ===== View Menu ===== */
"H8h-7b-M4v.title" = "보기";
/* ===== Window Menu ===== */
"aUF-d1-5bR.title" = "윈도우";
"OY7-WF-poV.title" = "최소화";
"R4o-n2-Eq4.title" = "확대/축소";
"LE2-aR-0XJ.title" = "모두 앞으로 가져오기";
/* ===== Help Menu ===== */
"EPT-qC-fAb.title" = "도움말";

View File

@@ -0,0 +1,76 @@
/* ============================================================
* 闲言APP — macOS 主菜单本地化(简体中文)
* 创建时间: 2026-06-24
* 作用: macOS 系统菜单栏简体中文文案
* ============================================================ */
/* ===== App Menu ===== */
"1Xt-HY-uBw.title" = "闲言";
"5kV-Vb-QxS.title" = "关于 闲言";
"BOF-NM-1cW.title" = "偏好设置…";
"NMo-om-nkz.title" = "服务";
"Olw-nP-bQN.title" = "隐藏 闲言";
"Vdr-fp-XzO.title" = "隐藏其他";
"Kd2-mp-pUS.title" = "显示全部";
"4sb-4s-VLi.title" = "退出 闲言";
/* ===== Edit Menu ===== */
"5QF-Oa-p0T.title" = "编辑";
"dRJ-4n-Yzg.title" = "撤销";
"6dh-zS-Vam.title" = "重做";
"uRl-iY-unG.title" = "剪切";
"x3v-GG-iWU.title" = "复制";
"gVA-U4-sdL.title" = "粘贴";
"WeT-3V-zwk.title" = "粘贴并匹配样式";
"pa3-QI-u2k.title" = "删除";
"Ruw-6m-B2m.title" = "全选";
/* ===== Edit > Find ===== */
"4EN-yA-p0u.title" = "查找";
"Xz5-n4-O0W.title" = "查找…";
"YEy-JH-Tfz.title" = "查找和替换…";
"q09-fT-Sye.title" = "查找下一个";
"OwM-mh-QMV.title" = "查找上一个";
"buJ-ug-pKt.title" = "使用所选内容查找";
"S0p-oC-mLd.title" = "跳到所选内容";
/* ===== Edit > Spelling and Grammar ===== */
"Dv1-io-Yv7.title" = "拼写和语法";
"HFo-cy-zxI.title" = "显示拼写和语法";
"hz2-CU-CR7.title" = "立即检查文稿";
"rbD-Rh-wIN.title" = "键入时检查拼写";
"mK6-2p-4JG.title" = "随拼写检查语法";
"78Y-hA-62v.title" = "自动纠正拼写";
/* ===== Edit > Substitutions ===== */
"9ic-FL-obx.title" = "替换";
"z6F-FW-3nz.title" = "显示替换";
"9yt-4B-nSM.title" = "智能复制/粘贴";
"hQb-2v-fYv.title" = "智能引号";
"rgM-f4-ycn.title" = "智能破折号";
"cwL-P1-jid.title" = "智能链接";
"tRr-pd-1PS.title" = "数据检测器";
"HFQ-gK-NFA.title" = "文本替换";
/* ===== Edit > Transformations ===== */
"2oI-Rn-ZJC.title" = "变换";
"vmV-6d-7jI.title" = "转为大写";
"d9M-CD-aMd.title" = "转为小写";
"UEZ-Bs-lqG.title" = "首字母大写";
/* ===== Edit > Speech ===== */
"xrE-MZ-jX0.title" = "语音";
"Ynk-f8-cLZ.title" = "开始朗读";
"Oyz-dy-DGm.title" = "停止朗读";
/* ===== View Menu ===== */
"H8h-7b-M4v.title" = "视图";
/* ===== Window Menu ===== */
"aUF-d1-5bR.title" = "窗口";
"OY7-WF-poV.title" = "最小化";
"R4o-n2-Eq4.title" = "缩放";
"LE2-aR-0XJ.title" = "前置全部窗口";
/* ===== Help Menu ===== */
"EPT-qC-fAb.title" = "帮助";

View File

@@ -0,0 +1,76 @@
/* ============================================================
* 闲言APP — macOS 主菜单本地化(繁体中文)
* 创建时间: 2026-06-24
* 作用: macOS 系统菜单栏繁體中文文案
* ============================================================ */
/* ===== App Menu ===== */
"1Xt-HY-uBw.title" = "閒言";
"5kV-Vb-QxS.title" = "關於 閒言";
"BOF-NM-1cW.title" = "偏好設定…";
"NMo-om-nkz.title" = "服務";
"Olw-nP-bQN.title" = "隱藏 閒言";
"Vdr-fp-XzO.title" = "隱藏其他";
"Kd2-mp-pUS.title" = "顯示全部";
"4sb-4s-VLi.title" = "結束 閒言";
/* ===== Edit Menu ===== */
"5QF-Oa-p0T.title" = "編輯";
"dRJ-4n-Yzg.title" = "還原";
"6dh-zS-Vam.title" = "重做";
"uRl-iY-unG.title" = "剪下";
"x3v-GG-iWU.title" = "拷貝";
"gVA-U4-sdL.title" = "貼上";
"WeT-3V-zwk.title" = "貼上並符合樣式";
"pa3-QI-u2k.title" = "刪除";
"Ruw-6m-B2m.title" = "全選";
/* ===== Edit > Find ===== */
"4EN-yA-p0u.title" = "尋找";
"Xz5-n4-O0W.title" = "尋找…";
"YEy-JH-Tfz.title" = "尋找與取代…";
"q09-fT-Sye.title" = "尋找下一個";
"OwM-mh-QMV.title" = "尋找上一個";
"buJ-ug-pKt.title" = "使用選取範圍尋找";
"S0p-oC-mLd.title" = "跳至選取範圍";
/* ===== Edit > Spelling and Grammar ===== */
"Dv1-io-Yv7.title" = "拼字和文法";
"HFo-cy-zxI.title" = "顯示拼字和文法";
"hz2-CU-CR7.title" = "立即檢查文件";
"rbD-Rh-wIN.title" = "鍵入時檢查拼字";
"mK6-2p-4JG.title" = "隨拼字檢查文法";
"78Y-hA-62v.title" = "自動校正拼字";
/* ===== Edit > Substitutions ===== */
"9ic-FL-obx.title" = "取代";
"z6F-FW-3nz.title" = "顯示取代";
"9yt-4B-nSM.title" = "智慧拷貝/貼上";
"hQb-2v-fYv.title" = "智慧引號";
"rgM-f4-ycn.title" = "智慧破折號";
"cwL-P1-jid.title" = "智慧連結";
"tRr-pd-1PS.title" = "資料偵測器";
"HFQ-gK-NFA.title" = "文字取代";
/* ===== Edit > Transformations ===== */
"2oI-Rn-ZJC.title" = "變換";
"vmV-6d-7jI.title" = "設為大寫";
"d9M-CD-aMd.title" = "設為小寫";
"UEZ-Bs-lqG.title" = "首字母大寫";
/* ===== Edit > Speech ===== */
"xrE-MZ-jX0.title" = "語音";
"Ynk-f8-cLZ.title" = "開始朗讀";
"Oyz-dy-DGm.title" = "停止朗讀";
/* ===== View Menu ===== */
"H8h-7b-M4v.title" = "顯示方式";
/* ===== Window Menu ===== */
"aUF-d1-5bR.title" = "視窗";
"OY7-WF-poV.title" = "縮到最小";
"R4o-n2-Eq4.title" = "縮放";
"LE2-aR-0XJ.title" = "將此程式所有視窗移至最前";
/* ===== Help Menu ===== */
"EPT-qC-fAb.title" = "輔助說明";