diff --git a/Makefile b/Makefile index c176a8f..5423717 100644 --- a/Makefile +++ b/Makefile @@ -2,11 +2,10 @@ all: build test-ui-preview build: test-package build-ui-preview test-package: - cd app/xcode && swift test -Xswiftc -DCI_TESTING + cd app/xcode && xcodebuild -scheme VCam-Package test -destination 'platform=macOS' build-ui-preview: cd app/xcode/App && xcodebuild -project VCam.xcodeproj -scheme VCamUIPreview -derivedDataPath /tmp/build clean build test-ui-preview: cd app/xcode/App && xcodebuild -project VCam.xcodeproj -scheme VCamUIPreviewUITests -derivedDataPath /tmp/build -resultBundlePath /tmp/UITestResults test ONLY_ACTIVE_ARCH=YES CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO CODE_SIGN_ENTITLEMENTS="" - diff --git a/app/xcode/App/VCam.xcodeproj/project.pbxproj b/app/xcode/App/VCam.xcodeproj/project.pbxproj index ad6c112..7215c74 100644 --- a/app/xcode/App/VCam.xcodeproj/project.pbxproj +++ b/app/xcode/App/VCam.xcodeproj/project.pbxproj @@ -196,6 +196,7 @@ knownRegions = ( en, Base, + ja, ); mainGroup = 061238592ADE9A8300B67618; productRefGroup = 061238632ADE9A8300B67618 /* Products */; diff --git a/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift b/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift index 90ee848..c337ae2 100644 --- a/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift +++ b/app/xcode/App/VCamUIPreviewUITests/LaunchScreenshotTests.swift @@ -1,5 +1,4 @@ import XCTest -import VCamLocalization import VCamUI final class LaunchScreenshotTests: XCTestCase { @@ -10,61 +9,59 @@ final class LaunchScreenshotTests: XCTestCase { override func setUpWithError() throws { continueAfterFailure = false - LocalizationEnvironment.currentLocaleIdentifier = { "en_US" } } func testLaunch() throws { let app = XCUIApplication.make() + app.launchArguments += ["-AppleLanguages", "(en)", "-AppleLocale", "en_US"] app.launch() XCTContext.runActivity(named: "Launch Screen") { activity in add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(L10n.screenEffect.text) Screen") { activity in - app.buttons.contains(label: L10n.screenEffect.text).click() - _ = app.staticTexts[L10n.startRecording.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "Screen Effect Screen") { activity in + app.buttons["menu.screenEffect"].click() + _ = app.buttons["recording.startButton"].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(L10n.recording.text) Screen") { activity in - app.buttons.contains(label: L10n.recording.text).click() - _ = app.staticTexts[L10n.whiteBalance.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "Recording Screen") { activity in + app.buttons["menu.recording"].click() + _ = app.descendants(matching: .any)["display.whiteBalance"].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(L10n.settings.text) Screen") { activity in + XCTContext.runActivity(named: "Settings Screen") { activity in app.buttons["btn_settings"].click() - _ = app.staticTexts[L10n.settings.text].waitForExistence(timeout: 5) + _ = app.buttons["settings.tab.general"].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) XCTAssertTrue(app.cells.firstMatch.isSelected) - XCTContext.runActivity(named: "\(activity.name) - \(L10n.rendering.text)") { activity in - app.cells.staticTexts[L10n.rendering.text].click() - _ = app.staticTexts[L10n.renderingQuality.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "\(activity.name) - Rendering") { activity in + app.cells["settings.tab.rendering"].click() + _ = app.descendants(matching: .any)["settings.rendering.quality"].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(activity.name) - \(L10n.tracking.text)") { activity in - app.cells.staticTexts[L10n.tracking.text].click() - _ = app.staticTexts[L10n.fpsCamera.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "\(activity.name) - Tracking") { activity in + app.cells["settings.tab.tracking"].click() add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(activity.name) - \(L10n.virtualCamera.text)") { activity in - app.cells.staticTexts[L10n.virtualCamera.text].click() - _ = app.staticTexts[L10n.noteEnableNewCameraExtension.text].waitForExistence(timeout: 5) + XCTContext.runActivity(named: "\(activity.name) - Virtual Camera") { activity in + app.cells["settings.tab.virtualCamera"].click() add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(activity.name) - \(L10n.integration.text)") { activity in - app.cells.staticTexts[L10n.integration.text].click() + XCTContext.runActivity(named: "\(activity.name) - Integration") { activity in + app.cells["settings.tab.integration"].click() _ = app.staticTexts["VCamMocap"].waitForExistence(timeout: 5) add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } - XCTContext.runActivity(named: "\(activity.name) - \(L10n.experiment.text)") { activity in - app.cells.staticTexts[L10n.experiment.text].click() + XCTContext.runActivity(named: "\(activity.name) - Experiment") { activity in + app.cells["settings.tab.experiment"].click() add(.keepAlways(screenshot: app.screenshot(), activity: activity)) } } diff --git a/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift b/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift index 2cbbe9a..87a107e 100644 --- a/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift +++ b/app/xcode/App/VCamUIPreviewUITests/VCamUIPreviewUITests.swift @@ -1,11 +1,10 @@ import XCTest -import VCamLocalization +import VCamUI final class VCamUIPreviewUITests: XCTestCase { override func setUpWithError() throws { continueAfterFailure = false - LocalizationEnvironment.currentLocaleIdentifier = { "en_US" } } override func tearDownWithError() throws { @@ -13,10 +12,11 @@ final class VCamUIPreviewUITests: XCTestCase { func testLaunchApp() throws { let app = XCUIApplication.make() + app.launchArguments += ["-AppleLanguages", "(en)", "-AppleLocale", "en_US"] app.launch() XCTContext.runActivity(named: "Check VCamUI") { _ in - XCTAssertTrue(app.buttons.contains(label: L10n.main.text).exists) + XCTAssertTrue(app.buttons["menu.main"].exists) } } } diff --git a/app/xcode/Package.swift b/app/xcode/Package.swift index 94557a5..fc60422 100644 --- a/app/xcode/Package.swift +++ b/app/xcode/Package.swift @@ -13,7 +13,6 @@ let package = Package( .library(name: "VCamDefaults", targets: ["VCamDefaults"]), .library(name: "VCamAppExtension", targets: ["VCamAppExtension"]), - .library(name: "VCamLocalization", targets: ["VCamLocalization"]), .library(name: "VCamStub", targets: ["VCamStub"]), ], @@ -22,16 +21,15 @@ let package = Package( ], targets: [ .target(name: "VCamUI", dependencies: [ - "VCamUIFoundation", "VCamTracking", "VCamCamera", "VCamData", "VCamLocalization", "VCamBridge", "VCamWorkaround", + "VCamUIFoundation", "VCamTracking", "VCamCamera", "VCamData", "VCamBridge", "VCamWorkaround", ], resources: [ .process("Resources"), ]), .target(name: "VCamUIFoundation"), .target(name: "VCamData", dependencies: ["VCamBridge", "VCamEntity"]), - .target(name: "VCamEntity", dependencies: ["VCamDefaults", "VCamLocalization"]), - .target(name: "VCamLocalization", resources: [.process("VCamResources")]), + .target(name: "VCamEntity", dependencies: ["VCamDefaults"]), .target(name: "VCamMedia", dependencies: ["VCamEntity", "VCamAppExtension", "VCamLogger"]), - .target(name: "VCamBridge", dependencies: ["VCamEntity", "VCamUIFoundation", "VCamLocalization"]), + .target(name: "VCamBridge", dependencies: ["VCamEntity", "VCamUIFoundation"]), .target(name: "VCamTracking", dependencies: ["VCamCamera"]), .target(name: "VCamCamera", dependencies: ["VCamMedia", "VCamData", "VCamLogger"]), diff --git a/app/xcode/Sources/VCamBridge/LensFlare.swift b/app/xcode/Sources/VCamBridge/LensFlare.swift index ae69689..fef66d9 100644 --- a/app/xcode/Sources/VCamBridge/LensFlare.swift +++ b/app/xcode/Sources/VCamBridge/LensFlare.swift @@ -1,14 +1,6 @@ -// -// LensFlare.swift -// -// -// Created by Tatsuya Tanaka on 2022/03/22. -// - import Foundation -import VCamLocalization -public enum LensFlare: Int32, CaseIterable, Identifiable, CustomStringConvertible { +public enum LensFlare: Int32, CaseIterable, Identifiable { case none, type1, type2, type3, type4 public var id: Self { self } @@ -17,18 +9,4 @@ public enum LensFlare: Int32, CaseIterable, Identifiable, CustomStringConvertibl .init(rawValue: value) ?? .none } - public var description: String { - switch self { - case .none: - return L10n.none.text - case .type1: - return L10n.typeNo("1").text - case .type2: - return L10n.typeNo("2").text - case .type3: - return L10n.typeNo("3").text - case .type4: - return L10n.typeNo("4").text - } - } } diff --git a/app/xcode/Sources/VCamBridge/TrackingMappingEntry.swift b/app/xcode/Sources/VCamBridge/TrackingMappingEntry.swift index 40d9304..9910563 100644 --- a/app/xcode/Sources/VCamBridge/TrackingMappingEntry.swift +++ b/app/xcode/Sources/VCamBridge/TrackingMappingEntry.swift @@ -1,7 +1,5 @@ import Foundation -import SwiftUI import simd -import VCamLocalization public struct TrackingMappingEntry: Codable, Sendable, Hashable, Identifiable { public let id: UUID @@ -106,15 +104,7 @@ public extension TrackingMappingEntry { } public extension TrackingMappingEntry.Key { - var isVCamKey: Bool { key.hasPrefix("_") } var id: String { key } - var nameKey: LocalizedStringKey { - if isVCamKey { - L10n.key("trackingInput_\(key)").key - } else { - "\(key)" - } - } } private enum RangeKeyCodingKeys: String, CodingKey { diff --git a/app/xcode/Sources/VCamData/DisplayParameter.swift b/app/xcode/Sources/VCamData/DisplayParameter.swift index 20a9706..6503ad6 100644 --- a/app/xcode/Sources/VCamData/DisplayParameter.swift +++ b/app/xcode/Sources/VCamData/DisplayParameter.swift @@ -1,7 +1,6 @@ import Foundation import SwiftUI import AppKit -import VCamLocalization public struct DisplayParameter: Codable, Identifiable, Equatable { public struct Value: Codable, Equatable { @@ -66,7 +65,7 @@ public struct DisplayParameter: Codable, Identifiable, Equatable { public let id: String public var value: Value - public init(name: String = L10n.newPreset.text, id: String = UUID().uuidString, value: Value = Value()) { + public init(name: String = "", id: String = UUID().uuidString, value: Value = Value()) { self.name = name self.id = id self.value = value @@ -159,7 +158,7 @@ public final class DisplayParameterPresets { // MARK: - DisplayParameterPreset (for UI compatibility) public struct DisplayParameterPreset: Hashable, Identifiable, CustomStringConvertible, Sendable { - public static let newPreset = Self.init(id: "", description: L10n.newPreset.text) + public static let newPreset = Self.init(id: "", description: "") public let id: String public var description: String diff --git a/app/xcode/Sources/VCamData/VCamSceneDataStore.swift b/app/xcode/Sources/VCamData/VCamSceneDataStore.swift index f42eff1..b98f123 100644 --- a/app/xcode/Sources/VCamData/VCamSceneDataStore.swift +++ b/app/xcode/Sources/VCamData/VCamSceneDataStore.swift @@ -1,6 +1,5 @@ import Foundation import VCamEntity -import VCamLocalization import VCamBridge public struct VCamSceneDataStore { @@ -76,8 +75,8 @@ extension VCamSceneDataStore { public func makeNewScene() -> VCamScene { try? addSceneIdIfNeeded() - return .init(id: sceneId, name: L10n.scene.text, objects: [ - .init(id: SceneObject.avatarID, name: L10n.model.text, type: .avatar(state: .zero), isHidden: false, isLocked: false) + return .init(id: sceneId, name: "", objects: [ + .init(id: SceneObject.avatarID, name: "", type: .avatar(state: .zero), isHidden: false, isLocked: false) ], aspectRatio: MainTexture.shared.aspectRatio) } diff --git a/app/xcode/Sources/VCamEntity/SceneObject.swift b/app/xcode/Sources/VCamEntity/SceneObject.swift index 850d6af..8b068af 100644 --- a/app/xcode/Sources/VCamEntity/SceneObject.swift +++ b/app/xcode/Sources/VCamEntity/SceneObject.swift @@ -1,13 +1,5 @@ -// -// SceneObject.swift -// -// -// Created by Tatsuya Tanaka on 2023/03/24. -// - import Foundation import CoreGraphics -import VCamLocalization import simd public protocol SceneObjectCroppableTexture: AnyObject { @@ -19,7 +11,7 @@ public struct SceneObject: Identifiable { public init(id: Int32 = .random(in: 0.. ArgumentsLocalizedString { - ArgumentsLocalizedString("aboutApp", "aboutApp \(String(describing: p1))", String(describing: p1)) - } - /// Account Management... - public static let accountManagement = LocalizedString(lookupKey: "accountManagement") - /// Acquire License... - public static let acquireLicense = LocalizedString(lookupKey: "acquireLicense") - /// Action - public static let action = LocalizedString(lookupKey: "action") - /// Add - public static let add = LocalizedString(lookupKey: "add") - /// Add Image - public static let addImage = LocalizedString(lookupKey: "addImage") - /// Add Screen - public static let addScreenCapture = LocalizedString(lookupKey: "addScreenCapture") - /// Add icon in macOS menu bar - public static let addToMacOSMenuBar = LocalizedString(lookupKey: "addToMacOSMenuBar") - /// Add Video Capture - public static let addVideoCapture = LocalizedString(lookupKey: "addVideoCapture") - /// Add Web - public static let addWeb = LocalizedString(lookupKey: "addWeb") - /// Add Wind - public static let addWind = LocalizedString(lookupKey: "addWind") - /// Allow access to %@ - public static func allowFor(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("allowFor %@", "allowFor \(String(describing: p1))", String(describing: p1)) - } - /// Always on Top - public static let alwaysOnTop = LocalizedString(lookupKey: "alwaysOnTop") - /// Ambient light color - public static let ambientLightColor = LocalizedString(lookupKey: "ambientLightColor") - /// Ambient light intensity - public static let ambientLightIntensity = LocalizedString(lookupKey: "ambientLightIntensity") - /// Anamorphic ratio - public static let anamorphicRatio = LocalizedString(lookupKey: "anamorphicRatio") - /// Apply - public static let apply = LocalizedString(lookupKey: "apply") - /// - Horizontal - public static let asHorizontalVideo = LocalizedString(lookupKey: "asHorizontalVideo") - /// - Vertical - public static let asVerticalVideo = LocalizedString(lookupKey: "asVerticalVideo") - /// Authentication Error - public static let authenticationError = LocalizedString(lookupKey: "authenticationError") - /// Background - public static let background = LocalizedString(lookupKey: "background") - /// Bloom - public static let bloom = LocalizedString(lookupKey: "bloom") - /// Blur - public static let blur = LocalizedString(lookupKey: "blur") - /// Bye - public static let bye = LocalizedString(lookupKey: "bye") - /// Calibrate - public static let calibrate = LocalizedString(lookupKey: "calibrate") - /// Camera - public static let camera = LocalizedString(lookupKey: "camera") - /// Camera Exposure (EV) - public static let cameraExposure = LocalizedString(lookupKey: "cameraExposure") - /// The virtual camera is not allowed. Please allow it from the 'Login Items & Extensions' of 'General' section in the settings app. - public static let cameraExtensionAwaitingUserApproval = LocalizedString(lookupKey: "cameraExtensionAwaitingUserApproval") - /// The virtual camera is NOT working. - public static let cameraExtensionNotWorking = LocalizedString(lookupKey: "cameraExtensionNotWorking") - /// The virtual camera is working. - public static let cameraExtensionWorking = LocalizedString(lookupKey: "cameraExtensionWorking") - /// Cancel - public static let cancel = LocalizedString(lookupKey: "cancel") - /// Capture Preference - public static let capturePreference = LocalizedString(lookupKey: "capturePreference") - /// Capture Type - public static let captureType = LocalizedString(lookupKey: "captureType") - /// Change Thumbnail - public static let changeThumbnail = LocalizedString(lookupKey: "changeThumbnail") - /// Change the direction of the wind randomly - public static let changeWindDirection = LocalizedString(lookupKey: "changeWindDirection") - /// Check for Updates... - public static let checkForUpdates = LocalizedString(lookupKey: "checkForUpdates") - /// Checking License... - public static let checkingLicense = LocalizedString(lookupKey: "checkingLicense") - /// Cheer - public static let cheer = LocalizedString(lookupKey: "cheer") - /// Chroma Keying - public static let chromaKeying = LocalizedString(lookupKey: "chromaKeying") - /// Clipboard - public static let clipboard = LocalizedString(lookupKey: "clipboard") - /// Close - public static let close = LocalizedString(lookupKey: "close") - /// Color - public static let color = LocalizedString(lookupKey: "color") - /// Color Filter - public static let colorFilter = LocalizedString(lookupKey: "colorFilter") - /// Color temperature - public static let colorTemperature = LocalizedString(lookupKey: "colorTemperature") - /// Commercial license is active. - public static let commercialLicenseActive = LocalizedString(lookupKey: "commercialLicenseActive") - /// Commercial license is not active. - public static let commercialLicenseNotActive = LocalizedString(lookupKey: "commercialLicenseNotActive") - /// A commercial license is required for commercial use. - public static let commercialLicenseRequired = LocalizedString(lookupKey: "commercialLicenseRequired") - /// Uninstallation is complete. - public static let completeUninstalling = LocalizedString(lookupKey: "completeUninstalling") - /// Are you sure you want to delete "%@"? - public static func confirmDeleteModel(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("confirmDeleteModel %@", "confirmDeleteModel \(String(describing: p1))", String(describing: p1)) - } - /// Are you sure you want to sign out? - public static let confirmSignOut = LocalizedString(lookupKey: "confirmSignOut") - /// Connect - public static let connect = LocalizedString(lookupKey: "connect") - /// Connected - public static let connected = LocalizedString(lookupKey: "connected") - /// Connecting... - public static let connecting = LocalizedString(lookupKey: "connecting") - /// Contrast - public static let contrast = LocalizedString(lookupKey: "contrast") - /// Copy - public static let copy = LocalizedString(lookupKey: "copy") - /// Create Shortcut - public static let createShortcut = LocalizedString(lookupKey: "createShortcut") - /// Current Version: %@ - public static func currentVersion(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("currentVersion %@", "currentVersion \(String(describing: p1))", String(describing: p1)) - } - /// Cut - public static let cut = LocalizedString(lookupKey: "cut") - /// Default - public static let `default` = LocalizedString(lookupKey: "default") - /// Delete - public static let delete = LocalizedString(lookupKey: "delete") - /// Delete the Old Virtual Camera - public static let deleteOldDALPlugin = LocalizedString(lookupKey: "deleteOldDALPlugin") - /// The old virtual camera is no longer supported, so it'll be deleted now. - public static let deleteOldDALPluginMessage = LocalizedString(lookupKey: "deleteOldDALPluginMessage") - /// Delete %@ - public static func deleteOne(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("deleteOne %@", "deleteOne \(String(describing: p1))", String(describing: p1)) - } - /// Delete the virtual camera plugin. - public static let deletePlugin = LocalizedString(lookupKey: "deletePlugin") - /// Delete Selected Object - public static let deleteSelectedObject = LocalizedString(lookupKey: "deleteSelectedObject") - /// Destination - public static let destinationToSave = LocalizedString(lookupKey: "destinationToSave") - /// Developing... - public static let developing = LocalizedString(lookupKey: "developing") - /// Diffusion - public static let diffusion = LocalizedString(lookupKey: "diffusion") - /// Disconnect - public static let disconnect = LocalizedString(lookupKey: "disconnect") - /// Disconnected - public static let disconnected = LocalizedString(lookupKey: "disconnected") - /// Display - public static let display = LocalizedString(lookupKey: "display") - /// https://docs.vcamapp.com/v/en/virtual-camera/virtualcamera - public static let docsURLForVirtualCamera = LocalizedString(lookupKey: "docsURLForVirtualCamera") - /// Done - public static let done = LocalizedString(lookupKey: "done") - /// Download - public static let download = LocalizedString(lookupKey: "download") - /// Download for Supporters - public static let downloadSupporterVersion = LocalizedString(lookupKey: "downloadSupporterVersion") - /// Duplicate - public static let duplicate = LocalizedString(lookupKey: "duplicate") - /// Finger closing sensitivity - public static let easeOfCloseFingers = LocalizedString(lookupKey: "easeOfCloseFingers") - /// Finger opening sensitivity - public static let easeOfOpeningFingers = LocalizedString(lookupKey: "easeOfOpeningFingers") - /// Edit - public static let edit = LocalizedString(lookupKey: "edit") - /// Edit Model - public static let editModel = LocalizedString(lookupKey: "editModel") - /// Edit Output Bounds - public static let editOutputBounds = LocalizedString(lookupKey: "editOutputBounds") - /// Set the minimum and maximum values for the output range. - public static let editOutputBoundsMessage = LocalizedString(lookupKey: "editOutputBoundsMessage") - /// Emoji - public static let emoji = LocalizedString(lookupKey: "emoji") - /// Enable - public static let enable = LocalizedString(lookupKey: "enable") - /// Convert VRM 0.x to VRM 1.x - public static let enableAutoConvertingToVRM1 = LocalizedString(lookupKey: "enableAutoConvertingToVRM1") - /// Enable VSync - public static let enableVSync = LocalizedString(lookupKey: "enableVSync") - /// Entire Display - public static let entireDisplay = LocalizedString(lookupKey: "entireDisplay") - /// No permission. Please allow screen recording in the Security & Privacy of the System Preferences. - public static let errorScreenCapturePermission = LocalizedString(lookupKey: "errorScreenCapturePermission") - /// A new version %@ is available! - public static func existsNewAppVersion(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("existsNewAppVersion %@", "existsNewAppVersion \(String(describing: p1))", String(describing: p1)) - } - /// Experiment - public static let experiment = LocalizedString(lookupKey: "experiment") - /// The supporter version of the app can be downloaded from the following link: - public static let experimentAdvertisement = LocalizedString(lookupKey: "experimentAdvertisement") - /// These are experimental features and may have bugs. - public static let experimentDisclaimer = LocalizedString(lookupKey: "experimentDisclaimer") - /// These features are available for our supporters, thank you for your supporting! - public static let experimentThanks = LocalizedString(lookupKey: "experimentThanks") - /// Expiry Date: - public static let expiryDate = LocalizedString(lookupKey: "expiryDate") - /// Installing the virtual camera.\nClick on 'Open Security Preferences' and then click 'Allow'. - public static let explainAboutInstallingCameraExtension = LocalizedString(lookupKey: "explainAboutInstallingCameraExtension") - /// The virtual camera will be reinstalled for the update - public static let explainAboutReinstallingCameraExtension = LocalizedString(lookupKey: "explainAboutReinstallingCameraExtension") - /// Horizontal sensitivity - public static let eyesHorizontalSensitivity = LocalizedString(lookupKey: "eyesHorizontalSensitivity") - /// Vertical sensitivity - public static let eyesVerticalSensitivity = LocalizedString(lookupKey: "eyesVerticalSensitivity") - /// Face / Eye / Mouth - public static let faceEyeMouth = LocalizedString(lookupKey: "faceEyeMouth") - /// Facial Expression - public static let facialExpression = LocalizedString(lookupKey: "facialExpression") - /// The installation of the virtual camera failed. Please install it from this app’s settings if you want to use it. - public static let failedToInstallCameraExtension = LocalizedString(lookupKey: "failedToInstallCameraExtension") - /// Failed to install the virtual camera. Please reinstall the virtual camera in this app’s settings. - public static let failedToInstallCameraPlugin = LocalizedString(lookupKey: "failedToInstallCameraPlugin") - /// Failure - public static let failure = LocalizedString(lookupKey: "failure") - /// File - public static let file = LocalizedString(lookupKey: "file") - /// Filter - public static let filter = LocalizedString(lookupKey: "filter") - /// Finger - public static let finger = LocalizedString(lookupKey: "finger") - /// Flip screen of the virtual camera - public static let flipScreen = LocalizedString(lookupKey: "flipScreen") - /// FPS (tracking) - public static let fpsCamera = LocalizedString(lookupKey: "fpsCamera") - /// FPS (screen) - public static let fpsScreen = LocalizedString(lookupKey: "fpsScreen") - /// General - public static let general = LocalizedString(lookupKey: "general") - /// Hand - public static let hand = LocalizedString(lookupKey: "hand") - /// Height - public static let height = LocalizedString(lookupKey: "height") - /// Help - public static let help = LocalizedString(lookupKey: "help") - /// If the movement is out of sync with the actual movement, press this button while facing forward to the camera and looking at the camera. - public static let helpCalibrate = LocalizedString(lookupKey: "helpCalibrate") - /// Reduce the load on the app by merging meshes, etc. If you have problems viewing the model, turn it off and reload the model. - public static let helpMesh = LocalizedString(lookupKey: "helpMesh") - /// The port in the PC connection settings on the mocopi side should be "12351". - public static let helpMocopIP = LocalizedString(lookupKey: "helpMocopIP") - /// Hi - public static let hi = LocalizedString(lookupKey: "hi") - /// Hide - public static let hide = LocalizedString(lookupKey: "hide") - /// Hue Shift - public static let hueShift = LocalizedString(lookupKey: "hueShift") - /// Image - public static let image = LocalizedString(lookupKey: "image") - /// Independent Window - public static let independentWindow = LocalizedString(lookupKey: "independentWindow") - /// Install - public static let install = LocalizedString(lookupKey: "install") - /// Install %@ - public static func installOne(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("installOne %@", "installOne \(String(describing: p1))", String(describing: p1)) - } - /// %@ a virtual camera plugin - public static func installPlugin(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("installPlugin %@", "installPlugin \(String(describing: p1))", String(describing: p1)) - } - /// Install the Virtual Camera - public static let installVirtualCamera = LocalizedString(lookupKey: "installVirtualCamera") - /// Integration - public static let integration = LocalizedString(lookupKey: "integration") - /// Intensity - public static let intensity = LocalizedString(lookupKey: "intensity") - /// Interact - public static let interact = LocalizedString(lookupKey: "interact") - /// %@ is not found - public static func isNotFound(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("isNotFound %@", "isNotFound \(String(describing: p1))", String(describing: p1)) - } - /// %@ is not set yet. - public static func isNotSetYet(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("isNotSetYet %@", "isNotSetYet \(String(describing: p1))", String(describing: p1)) - } - /// Jump - public static let jump = LocalizedString(lookupKey: "jump") - /// Language of the device - public static let languageOfDevice = LocalizedString(lookupKey: "languageOfDevice") - /// Lens flare - public static let lensFlare = LocalizedString(lookupKey: "lensFlare") - /// Lens flare intensity - public static let lensFlareIntensity = LocalizedString(lookupKey: "lensFlareIntensity") - /// License - public static let license = LocalizedString(lookupKey: "license") - /// If you have already acquired a commercial license, please verify your license. [Check License Status...](vcam2d://auth/checkLicense) - public static let licenseCheckIfAlreadyAcquired = LocalizedString(lookupKey: "licenseCheckIfAlreadyAcquired") - /// Your license has expired. - public static let licenseExpired = LocalizedString(lookupKey: "licenseExpired") - /// Your license is no longer active. - public static let licenseNoLongerActive = LocalizedString(lookupKey: "licenseNoLongerActive") - /// Your license is now active. - public static let licenseNowActive = LocalizedString(lookupKey: "licenseNowActive") - /// License Status Changed - public static let licenseStatusChanged = LocalizedString(lookupKey: "licenseStatusChanged") - /// Lip-sync - public static let lipSync = LocalizedString(lookupKey: "lipSync") - /// Lip-sync sensitivity (mic) - public static let lipSyncSensitivity = LocalizedString(lookupKey: "lipSyncSensitivity") - /// Load - public static let loadModel = LocalizedString(lookupKey: "loadModel") - /// Load Model File - public static let loadModelFile = LocalizedString(lookupKey: "loadModelFile") - /// Load Avatar on VRoid Hub - public static let loadOnVRoidHub = LocalizedString(lookupKey: "loadOnVRoidHub") - /// Load Scene - public static let loadScene = LocalizedString(lookupKey: "loadScene") - /// Load VRM File - public static let loadVRMFile = LocalizedString(lookupKey: "loadVRMFile") - /// Local File - public static let localFile = LocalizedString(lookupKey: "localFile") - /// Lock - public static let lock = LocalizedString(lookupKey: "lock") - /// Main - public static let main = LocalizedString(lookupKey: "main") - /// Manage Account and Subscription - public static let manageAccountAndSubscription = LocalizedString(lookupKey: "manageAccountAndSubscription") - /// Manage Objects - public static let manageObjects = LocalizedString(lookupKey: "manageObjects") - /// Maximum - public static let maximum = LocalizedString(lookupKey: "maximum") - /// Message - public static let message = LocalizedString(lookupKey: "message") - /// Microphone - public static let mic = LocalizedString(lookupKey: "mic") - /// Mic or Camera - public static let micOrCamera = LocalizedString(lookupKey: "micOrCamera") - /// Sync offset for mic [ms] - public static let micSyncOffset = LocalizedString(lookupKey: "micSyncOffset") - /// Migrate to New Virtual Camera - public static let migrateToNewVirtualCamera = LocalizedString(lookupKey: "migrateToNewVirtualCamera") - /// This app will migrate to a virtual camera optimized for the latest macOS.\nPlease follow the instructions to delete the old plugin and install the new virtual camera. - public static let migrateToNewVirtualCameraMessage = LocalizedString(lookupKey: "migrateToNewVirtualCameraMessage") - /// Minimum - public static let minimum = LocalizedString(lookupKey: "minimum") - /// Network Interpolation - public static let mocapNetworkInterpolation = LocalizedString(lookupKey: "mocapNetworkInterpolation") - /// Reduces jitter from packet drops (adds latency). Applies to VCamMocap and iFacialMocap. - public static let mocapNetworkInterpolationHelp = LocalizedString(lookupKey: "mocapNetworkInterpolationHelp") - /// Model - public static let model = LocalizedString(lookupKey: "model") - /// Model List - public static let modelList = LocalizedString(lookupKey: "modelList") - /// Missing - public static let modelMissing = LocalizedString(lookupKey: "modelMissing") - /// Motion - public static let motion = LocalizedString(lookupKey: "motion") - /// Reset position - public static let moveInitialPosition = LocalizedString(lookupKey: "moveInitialPosition") - /// New preset - public static let newPreset = LocalizedString(lookupKey: "newPreset") - /// No - public static let no = LocalizedString(lookupKey: "no") - /// Nod - public static let nod = LocalizedString(lookupKey: "nod") - /// No models found - public static let noModelsFound = LocalizedString(lookupKey: "noModelsFound") - /// None - public static let `none` = LocalizedString(lookupKey: "none") - /// Normal - public static let normal = LocalizedString(lookupKey: "normal") - /// Restart this app once after installation. - public static let noteEnableNewCameraExtension = LocalizedString(lookupKey: "noteEnableNewCameraExtension") - /// No Title - public static let notitle = LocalizedString(lookupKey: "notitle") - /// Not Supported - public static let notSupported = LocalizedString(lookupKey: "notSupported") - /// Object - public static let object = LocalizedString(lookupKey: "object") - /// Official Website - public static let officialWebsite = LocalizedString(lookupKey: "officialWebsite") - /// OK - public static let ok = LocalizedString(lookupKey: "ok") - /// Open File - public static let openFile = LocalizedString(lookupKey: "openFile") - /// Open Model List - public static let openModelList = LocalizedString(lookupKey: "openModelList") - /// Open preferences - public static let openPreference = LocalizedString(lookupKey: "openPreference") - /// Open %@ - public static func openVCam(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("openVCam", "openVCam \(String(describing: p1))", String(describing: p1)) - } - /// Optimize meshes (Recommended) - public static let optimizeMeshes = LocalizedString(lookupKey: "optimizeMeshes") - /// Paste - public static let paste = LocalizedString(lookupKey: "paste") - /// Pick - public static let pick = LocalizedString(lookupKey: "pick") - /// Play idle motions - public static let playIdleMotions = LocalizedString(lookupKey: "playIdleMotions") - /// Please reauthenticate. - public static let pleaseReauthenticate = LocalizedString(lookupKey: "pleaseReauthenticate") - /// Please restart the app and try again. - public static let pleaseRestartAppAndTryAgain = LocalizedString(lookupKey: "pleaseRestartAppAndTryAgain") - /// Restarting Mac may resolve the issue. - public static let pleaseRestartMacToFix = LocalizedString(lookupKey: "pleaseRestartMacToFix") - /// Pose - public static let pose = LocalizedString(lookupKey: "pose") - /// Preset - public static let preset = LocalizedString(lookupKey: "preset") - /// Preview the capture - public static let previewCapture = LocalizedString(lookupKey: "previewCapture") - /// Beautiful - public static let qualityBeautiful = LocalizedString(lookupKey: "qualityBeautiful") - /// Fantastic - public static let qualityFantastic = LocalizedString(lookupKey: "qualityFantastic") - /// Fast - public static let qualityFast = LocalizedString(lookupKey: "qualityFast") - /// Fastest - public static let qualityFastest = LocalizedString(lookupKey: "qualityFastest") - /// Good - public static let qualityGood = LocalizedString(lookupKey: "qualityGood") - /// Simple - public static let qualitySimple = LocalizedString(lookupKey: "qualitySimple") - /// Quit %@ - public static func quitVCam(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("quitVCam", "quitVCam \(String(describing: p1))", String(describing: p1)) - } - /// Reauthenticate... - public static let reauthenticate = LocalizedString(lookupKey: "reauthenticate") - /// Record desktop audio [β] - public static let recordDesktopAudio = LocalizedString(lookupKey: "recordDesktopAudio") - /// Recording - public static let recording = LocalizedString(lookupKey: "recording") - /// Recording... - public static let recordingShortcutKey = LocalizedString(lookupKey: "recordingShortcutKey") - /// At least one modifier key must be set. - public static let recordingShortcutKeyError = LocalizedString(lookupKey: "recordingShortcutKeyError") - /// Refresh Screen - public static let refreshScreen = LocalizedString(lookupKey: "refreshScreen") - /// Reinstall - public static let reinstall = LocalizedString(lookupKey: "reinstall") - /// Release Notes: - public static let releaseNotes = LocalizedString(lookupKey: "releaseNotes") - /// Reload - public static let reload = LocalizedString(lookupKey: "reload") - /// Remove this app from the capture - public static let removeVCamFromCapture = LocalizedString(lookupKey: "removeVCamFromCapture") - /// Rename - public static let rename = LocalizedString(lookupKey: "rename") - /// Rendering - public static let rendering = LocalizedString(lookupKey: "rendering") - /// Rendering Quality - public static let renderingQuality = LocalizedString(lookupKey: "renderingQuality") - /// Reset All to Default - public static let resetAllToDefault = LocalizedString(lookupKey: "resetAllToDefault") - /// Reset Model Position - public static let resetModelPosition = LocalizedString(lookupKey: "resetModelPosition") - /// Reset to Default - public static let resetToDefault = LocalizedString(lookupKey: "resetToDefault") - /// Reset Window Size - public static let resetWindowSize = LocalizedString(lookupKey: "resetWindowSize") - /// Setup is complete. Please restart Zoom or other clients. - public static let restartAfterInstalling = LocalizedString(lookupKey: "restartAfterInstalling") - /// Roundness - public static let roundness = LocalizedString(lookupKey: "roundness") - /// Run - public static let run = LocalizedString(lookupKey: "run") - /// Run - public static let runCode = LocalizedString(lookupKey: "runCode") - /// Saturation - public static let saturation = LocalizedString(lookupKey: "saturation") - /// Save - public static let save = LocalizedString(lookupKey: "save") - /// Scene - public static let scene = LocalizedString(lookupKey: "scene") - /// Screen - public static let screen = LocalizedString(lookupKey: "screen") - /// Screen - public static let screenCapture = LocalizedString(lookupKey: "screenCapture") - /// Screen Effect - public static let screenEffect = LocalizedString(lookupKey: "screenEffect") - /// Screen resolution - public static let screenResolution = LocalizedString(lookupKey: "screenResolution") - /// s - public static let seconds = LocalizedString(lookupKey: "seconds") - /// For more information, see this documentation. - public static let seeDocumentation = LocalizedString(lookupKey: "seeDocumentation") - /// Select All - public static let selectAll = LocalizedString(lookupKey: "selectAll") - /// Set As Background - public static let setAsBackground = LocalizedString(lookupKey: "setAsBackground") - /// Settings - public static let settings = LocalizedString(lookupKey: "settings") - /// Set up - public static let setUp = LocalizedString(lookupKey: "setUp") - /// Shortcut Key - public static let shortcutKey = LocalizedString(lookupKey: "shortcutKey") - /// Weight of shoulder rotation - public static let shoulderRotationWeight = LocalizedString(lookupKey: "shoulderRotationWeight") - /// Show - public static let show = LocalizedString(lookupKey: "show") - /// Shudder - public static let shudder = LocalizedString(lookupKey: "shudder") - /// Sign Out - public static let signOut = LocalizedString(lookupKey: "signOut") - /// Failed to sign out: - public static let signOutFailed = LocalizedString(lookupKey: "signOutFailed") - /// Simulate shadows (Use high power) - public static let simulateShadows = LocalizedString(lookupKey: "simulateShadows") - /// Skip This Version - public static let skipThisVersion = LocalizedString(lookupKey: "skipThisVersion") - /// Smoothing - public static let smoothing = LocalizedString(lookupKey: "smoothing") - /// Smoothness - public static let smoothness = LocalizedString(lookupKey: "smoothness") - /// Soft Knee - public static let softKnee = LocalizedString(lookupKey: "softKnee") - /// Start recording [β] - public static let startRecording = LocalizedString(lookupKey: "startRecording") - /// Sticker - public static let sticker = LocalizedString(lookupKey: "sticker") - /// Stop recording - public static let stopRecording = LocalizedString(lookupKey: "stopRecording") - /// Success - public static let success = LocalizedString(lookupKey: "success") - /// Support Developer - public static let supportDeveloperLabel = LocalizedString(lookupKey: "supportDeveloperLabel") - /// If you’d like to support the ongoing improvement of this app, your support would mean a lot! - public static let supportVCamMessage = LocalizedString(lookupKey: "supportVCamMessage") - /// Elbow offset - public static let swivelOffset = LocalizedString(lookupKey: "swivelOffset") - /// Take a photo - public static let takePhoto = LocalizedString(lookupKey: "takePhoto") - /// Threshold - public static let threshold = LocalizedString(lookupKey: "threshold") - /// Threshold - public static let thresholdScreenEffect = LocalizedString(lookupKey: "thresholdScreenEffect") - /// Time to take photos - public static let timeToTakePhoto = LocalizedString(lookupKey: "timeToTakePhoto") - /// Tint - public static let tint = LocalizedString(lookupKey: "tint") - /// Title - public static let title = LocalizedString(lookupKey: "title") - /// Track eyes - public static let trackEyes = LocalizedString(lookupKey: "trackEyes") - /// Tracking - public static let tracking = LocalizedString(lookupKey: "tracking") - /// Tracking Adjustment - public static let trackingAdjustment = LocalizedString(lookupKey: "trackingAdjustment") - /// Response - public static let trackingFilterResponse = LocalizedString(lookupKey: "trackingFilterResponse") - /// Smooth - public static let trackingFilterSmooth = LocalizedString(lookupKey: "trackingFilterSmooth") - /// Blink Left - public static let trackingInputBlinkL = LocalizedString(lookupKey: "trackingInput__blinkL") - /// Blink Right - public static let trackingInputBlinkR = LocalizedString(lookupKey: "trackingInput__blinkR") - /// Eye Movement X - public static let trackingInputEyeX = LocalizedString(lookupKey: "trackingInput__eyeX") - /// Eye Movement Y - public static let trackingInputEyeY = LocalizedString(lookupKey: "trackingInput__eyeY") - /// Head Rotation X - public static let trackingInputHeadX = LocalizedString(lookupKey: "trackingInput__headX") - /// Head Rotation Y - public static let trackingInputHeadY = LocalizedString(lookupKey: "trackingInput__headY") - /// Head Rotation Z - public static let trackingInputHeadZ = LocalizedString(lookupKey: "trackingInput__headZ") - /// Mouth - public static let trackingInputMouth = LocalizedString(lookupKey: "trackingInput__mouth") - /// Position X - public static let trackingInputPosX = LocalizedString(lookupKey: "trackingInput__posX") - /// Position Y - public static let trackingInputPosY = LocalizedString(lookupKey: "trackingInput__posY") - /// Position Z - public static let trackingInputPosZ = LocalizedString(lookupKey: "trackingInput__posZ") - /// Vowel - public static let trackingInputVowel = LocalizedString(lookupKey: "trackingInput__vowel") - /// Input - public static let trackingMappingInput = LocalizedString(lookupKey: "trackingMappingInput") - /// Output - public static let trackingMappingOutput = LocalizedString(lookupKey: "trackingMappingOutput") - /// Save feature will be added in a future update. - public static let trackingMappingSaveComingSoon = LocalizedString(lookupKey: "trackingMappingSaveComingSoon") - /// Tracking Mode - public static let trackingMode = LocalizedString(lookupKey: "trackingMode") - /// Smoothing - public static let trackingSmoothing = LocalizedString(lookupKey: "trackingSmoothing") - /// Type%@ - public static func typeNo(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("typeNo %@", "typeNo \(String(describing: p1))", String(describing: p1)) - } - /// Uninstall - public static let uninstall = LocalizedString(lookupKey: "uninstall") - /// Uninstall Virtual Camera Plugin - public static let uninstallPlugin = LocalizedString(lookupKey: "uninstallPlugin") - /// Unlock - public static let unlock = LocalizedString(lookupKey: "unlock") - /// Update - public static let update = LocalizedString(lookupKey: "update") - /// You're up-to-date! - public static let upToDate = LocalizedString(lookupKey: "upToDate") - /// %@ is currently the latest version - public static func upToDateMessage(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("upToDateMessage %@", "upToDateMessage \(String(describing: p1))", String(describing: p1)) - } - /// Use emotion by %@ [β] (Use high power) - public static func useEmotionBy(_ p1: Any) -> ArgumentsLocalizedString { - ArgumentsLocalizedString("useEmotionBy %@", "useEmotionBy \(String(describing: p1))", String(describing: p1)) - } - /// Use vowel estimation by camera - public static let useVowelEstimation = LocalizedString(lookupKey: "useVowelEstimation") - /// VCam Tracking 2.0 (New Tracking System) - public static let vcamTrackingV2 = LocalizedString(lookupKey: "vcamTrackingV2") - /// Video Capture - public static let videoCapture = LocalizedString(lookupKey: "videoCapture") - /// Video Capture Device - public static let videoCaptureDevice = LocalizedString(lookupKey: "videoCaptureDevice") - /// Format - public static let videoFormat = LocalizedString(lookupKey: "videoFormat") - /// hevc (Transparent) - public static let videoFormatHEVC = LocalizedString(lookupKey: "videoFormatHEVC") - /// View Documentation - public static let viewDocumentation = LocalizedString(lookupKey: "viewDocumentation") - /// Vignette - public static let vignette = LocalizedString(lookupKey: "vignette") - /// Virtual Camera - public static let virtualCamera = LocalizedString(lookupKey: "virtualCamera") - /// Wait - public static let wait = LocalizedString(lookupKey: "wait") - /// Web - public static let web = LocalizedString(lookupKey: "web") - /// What!? - public static let what = LocalizedString(lookupKey: "what") - /// White balance - public static let whiteBalance = LocalizedString(lookupKey: "whiteBalance") - /// Width - public static let width = LocalizedString(lookupKey: "width") - /// Wind - public static let wind = LocalizedString(lookupKey: "wind") - /// Window - public static let window = LocalizedString(lookupKey: "window") -} - -extension L10n { - nonisolated(unsafe) private static var bundles: [String: Bundle] = [:] - fileprivate static func tr(_ table: String, _ key: String, _ args: any CVarArg...) -> String { - let bundle = currentBundle() - return String(format: NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: ""), arguments: args) - } - - fileprivate static func tr(_ table: String, _ key: String, args: [any CVarArg]) -> String { - let bundle = currentBundle() - return String(format: NSLocalizedString(key, tableName: nil, bundle: bundle, value: key, comment: ""), arguments: args) - } - - private static func currentBundle() -> Bundle { - let locale = LocalizationEnvironment.currentLocaleIdentifier() - return bundles[locale] ?? { - let code = LanguageList(locale: locale).language.languageCode - let path = BundleToken.bundle.path(forResource: code, ofType: "lproj")! - let bundle = Bundle(path: path)! - bundles[locale] = bundle - return bundle - }() - } - - public static func key(_ name: String) -> LocalizedString { - LocalizedString(lookupKey: name) - } -} - -public struct LocalizedString: Sendable { - let lookupKey: String - - public var key: LocalizedStringKey { - LocalizedStringKey(lookupKey) - } - - public var text: String { - L10n.tr("Localizable", lookupKey) - } -} - -public struct ArgumentsLocalizedString { - internal init(_ lookupKey: String, _ key: LocalizedStringKey, _ arguments: any CVarArg...) { - self.lookupKey = lookupKey - self.localizedKey = key - self.arguments = arguments - } - - internal let lookupKey: String - internal let localizedKey: LocalizedStringKey - internal let arguments: [any CVarArg] - - public var key: LocalizedStringKey { - localizedKey - } - - public var text: String { - L10n.tr("Localizable", lookupKey, args: arguments) - } -} - - -private final class BundleToken { - static let bundle: Bundle = { - #if SWIFT_PACKAGE - return Bundle.module - #else - return Bundle(for: BundleToken.self) - #endif - }() -} diff --git a/app/xcode/Sources/VCamLocalization/Internal.swift b/app/xcode/Sources/VCamLocalization/Internal.swift deleted file mode 100644 index 1219ec4..0000000 --- a/app/xcode/Sources/VCamLocalization/Internal.swift +++ /dev/null @@ -1,15 +0,0 @@ -// -// Internal.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/18. -// - -import Foundation - -public extension Bundle { - /// Use only for localization - static var localize: Bundle { - Bundle.module - } -} diff --git a/app/xcode/Sources/VCamLocalization/Language.swift b/app/xcode/Sources/VCamLocalization/Language.swift deleted file mode 100644 index ad239fa..0000000 --- a/app/xcode/Sources/VCamLocalization/Language.swift +++ /dev/null @@ -1,57 +0,0 @@ -// -// Language.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/06. -// - -import Foundation -import SwiftUI - -public enum LanguageList: String, CaseIterable, Equatable, Identifiable { - case `default` = "", japanese = "ja_JP", english = "en_US" - - public var id: Self { self } - - public init(locale: String) { - self = LanguageList(rawValue: locale) ?? .default - } - - public var name: String { - switch self { - case .default: - return L10n.languageOfDevice.text - case .japanese: - return "日本語" - case .english: - return "English" - } - } - - public var language: Language { - switch self { - case .default where Locale.current.identifier == LanguageList.japanese.rawValue, - .japanese: - return .japanese - default: - return .english - } - } -} - -public enum Language: String { - case japanese = "ja_JP", english = "en_US" - - public var languageCode: String { - switch self { - case .japanese: - return "ja" - case .english: - return "en" - } - } - - public var locale: Locale { - Locale(identifier: rawValue) - } -} diff --git a/app/xcode/Sources/VCamLocalization/LocalizationEnvironment.swift b/app/xcode/Sources/VCamLocalization/LocalizationEnvironment.swift deleted file mode 100644 index 6fb55dd..0000000 --- a/app/xcode/Sources/VCamLocalization/LocalizationEnvironment.swift +++ /dev/null @@ -1,9 +0,0 @@ -import Foundation - -public struct LocalizationEnvironment { - nonisolated(unsafe) public static var currentLocaleIdentifier: @Sendable () -> String = { "" } - - public static var language: Language { - LanguageList(locale: currentLocaleIdentifier()).language - } -} diff --git a/app/xcode/Sources/VCamLocalization/VCamResources/en.lproj/Localizable.strings b/app/xcode/Sources/VCamLocalization/VCamResources/en.lproj/Localizable.strings deleted file mode 100644 index 86efed9..0000000 --- a/app/xcode/Sources/VCamLocalization/VCamResources/en.lproj/Localizable.strings +++ /dev/null @@ -1,385 +0,0 @@ -/* - Localizable.strings - VCam - - Created by Tatsuya Tanaka on 2022/04/06. - -*/ - -// MARK: - Common - -"ok" = "OK"; -"default" = "Default"; -"cancel" = "Cancel"; -"close" = "Close"; -"done" = "Done"; -"edit" = "Edit"; -"pick" = "Pick"; -"general" = "General"; -"normal" = "Normal"; -"apply" = "Apply"; -"delete" = "Delete"; -"duplicate" = "Duplicate"; -"rename" = "Rename"; -"changeThumbnail" = "Change Thumbnail"; -"title" = "Title"; -"notitle" = "No Title"; -"object" = "Object"; -"model" = "Model"; -"image" = "Image"; -"screen" = "Screen"; -"clipboard" = "Clipboard"; -"camera" = "Camera"; -"mic" = "Microphone"; -"virtualCamera" = "Virtual Camera"; -"scene" = "Scene"; -"web" = "Web"; -"message" = "Message"; -"destinationToSave" = "Destination"; -"update" = "Update"; -"download" = "Download"; -"install" = "Install"; -"uninstall" = "Uninstall"; -"reinstall" = "Reinstall"; -"openFile" = "Open File"; -"reload" = "Reload"; -"enable" = "Enable"; -"show" = "Show"; -"hide" = "Hide"; -"lock" = "Lock"; -"unlock" = "Unlock"; -"filter" = "Filter"; -"threshold" = "Threshold"; -"cut" = "Cut"; -"copy" = "Copy"; -"paste" = "Paste"; -"selectAll" = "Select All"; -"runCode" = "Run"; -"width" = "Width"; -"height" = "Height"; -"seconds" = "s"; -"notSupported" = "Not Supported"; -"resetAllToDefault" = "Reset All to Default"; -"resetToDefault" = "Reset to Default"; - -// MARK: - Menu - -"main" = "Main"; -"message" = "Message"; -"settings" = "Settings"; -"tracking" = "Tracking"; -"screenEffect" = "Screen Effect"; -"recording" = "Recording"; -"integration" = "Integration"; - -// MARK: - Motion - -"motion" = "Motion"; -"hi" = "Hi"; -"bye" = "Bye"; -"jump" = "Jump"; -"cheer" = "Cheer"; -"what" = "What!?"; -"pose" = "Pose"; -"nod" = "Nod"; -"no" = "No"; -"shudder" = "Shudder"; -"run" = "Run"; -"facialExpression" = "Facial Expression"; - -// MARK: - Expression -"_expauto_default_" = "Default"; - -// MARK: - Emoji - -"emoji" = "Emoji"; -"sticker" = "Sticker"; - -// MARK: - Wind - -"wind" = "Wind"; -"changeWindDirection" = "Change the direction of the wind randomly"; - -// MARK: - Object - -"manageObjects" = "Manage Objects"; -"addImage" = "Add Image"; -"addScreenCapture" = "Add Screen"; -"addVideoCapture" = "Add Video Capture"; -"addWeb" = "Add Web"; -"addWind" = "Add Wind"; -"screenCapture" = "Screen"; -"videoCapture" = "Video Capture"; -"deleteSelectedObject" = "Delete Selected Object"; -"interact" = "Interact"; -"localFile" = "Local File"; -"setAsBackground" = "Set As Background"; - -"moveInitialPosition" = "Reset position"; - -// MARK: - Preference - -"playIdleMotions" = "Play idle motions"; -"simulateShadows" = "Simulate shadows (Use high power)"; -"optimizeMeshes" = "Optimize meshes (Recommended)"; -"enableAutoConvertingToVRM1" = "Convert VRM 0.x to VRM 1.x"; -"helpMesh" = "Reduce the load on the app by merging meshes, etc. If you have problems viewing the model, turn it off and reload the model."; -"flipScreen" = "Flip screen of the virtual camera"; -"addToMacOSMenuBar" = "Add icon in macOS menu bar"; -"background" = "Background"; -"lipSyncSensitivity" = "Lip-sync sensitivity (mic)"; -"fpsScreen" = "FPS (screen)"; -"fpsCamera" = "FPS (tracking)"; -"screenResolution" = "Screen resolution"; -"asHorizontalVideo" = " - Horizontal"; -"asVerticalVideo" = " - Vertical"; -"renderingQuality" = "Rendering Quality"; -"qualityFastest" = "Fastest"; -"qualityFast" = "Fast"; -"qualitySimple" = "Simple"; -"qualityGood" = "Good"; -"qualityBeautiful" = "Beautiful"; -"qualityFantastic" = "Fantastic"; -"rendering" = "Rendering"; -"experiment" = "Experiment"; -"experimentDisclaimer" = "These are experimental features and may have bugs."; -"experimentThanks" = "These features are available for our supporters, thank you for your supporting!"; -"experimentAdvertisement" = "The supporter version of the app can be downloaded from the following link:"; -"enableVSync" = "Enable VSync"; -"vcamTrackingV2" = "VCam Tracking 2.0 (New Tracking System)"; -"installVirtualCamera" = "Install the Virtual Camera"; -"explainAboutReinstallingCameraExtension" = "The virtual camera will be reinstalled for the update"; -"explainAboutInstallingCameraExtension" = "Installing the virtual camera.\nClick on 'Open Security Preferences' and then click 'Allow'."; -"noteEnableNewCameraExtension" = "Restart this app once after installation."; -"cameraExtensionWorking" = "The virtual camera is working."; -"cameraExtensionNotWorking" = "The virtual camera is NOT working."; -"pleaseRestartMacToFix" = "Restarting Mac may resolve the issue."; -"cameraExtensionAwaitingUserApproval" = "The virtual camera is not allowed. Please allow it from the 'Login Items & Extensions' of 'General' section in the settings app."; -"failedToInstallCameraExtension" = "The installation of the virtual camera failed. Please install it from this app’s settings if you want to use it."; -"seeDocumentation" = "For more information, see this documentation."; -"docsURLForVirtualCamera" = "https://docs.vcamapp.com/v/en/virtual-camera/virtualcamera"; -"officialWebsite" = "Official Website"; -"supportVCamMessage" = "If you’d like to support the ongoing improvement of this app, your support would mean a lot!"; -"supportDeveloperLabel" = "Support Developer"; - -// MARK: - Tracking - -"micOrCamera" = "Mic or Camera"; -"helpCalibrate" = "If the movement is out of sync with the actual movement, press this button while facing forward to the camera and looking at the camera."; -"useEmotionBy %@" = "Use emotion by %@ [β] (Use high power)"; -"useVowelEstimation" = "Use vowel estimation by camera"; -"isNotFound %@" = "%@ is not found"; -"lipSync" = "Lip-sync"; -"trackEyes" = "Track eyes"; -"eyesHorizontalSensitivity" = "Horizontal sensitivity"; -"eyesVerticalSensitivity" = "Vertical sensitivity"; -"easeOfOpeningFingers" = "Finger opening sensitivity"; -"easeOfCloseFingers" = "Finger closing sensitivity"; -"shoulderRotationWeight" = "Weight of shoulder rotation"; -"swivelOffset" = "Elbow offset"; -"trackingSmoothing" = "Smoothing"; -"mocapNetworkInterpolation" = "Network Interpolation"; -"mocapNetworkInterpolationHelp" = "Reduces jitter from packet drops (adds latency). Applies to VCamMocap and iFacialMocap. "; -"faceEyeMouth" = "Face / Eye / Mouth"; -"hand" = "Hand"; -"finger" = "Finger"; - -// MARK: - Screen effect - -"newPreset" = "New preset"; -"preset" = "Preset"; -"save" = "Save"; -"ambientLightIntensity" = "Ambient light intensity"; -"ambientLightColor" = "Ambient light color"; -"cameraExposure" = "Camera Exposure (EV)"; -"colorFilter" = "Color Filter"; -"saturation" = "Saturation"; -"hueShift" = "Hue Shift"; -"contrast" = "Contrast"; -"whiteBalance" = "White balance"; -"colorTemperature" = "Color temperature"; -"tint" = "Tint"; -"bloom" = "Bloom"; -"intensity" = "Intensity"; -"thresholdScreenEffect" = "Threshold"; -"softKnee" = "Soft Knee"; -"diffusion" = "Diffusion"; -"anamorphicRatio" = "Anamorphic ratio"; -"color" = "Color"; -"lensFlare" = "Lens flare"; -"lensFlareIntensity" = "Lens flare intensity"; -"vignette" = "Vignette"; -"smoothness" = "Smoothness"; -"smoothing" = "Smoothing"; -"roundness" = "Roundness"; -"none" = "None"; -"typeNo %@" = "Type%@"; - -// MARK: - Filter -"chromaKeying" = "Chroma Keying"; -"blur" = "Blur"; -"trackingFilterSmooth" = "Smooth"; -"trackingFilterResponse" = "Response"; - -// MARK: - Permission - -"allowFor %@" = "Allow access to %@"; -"openPreference" = "Open preferences"; - -// MARK: - Recording - -"takePhoto" = "Take a photo"; -"timeToTakePhoto" = "Time to take photos"; -"startRecording" = "Start recording [β]"; -"stopRecording" = "Stop recording"; -"videoFormat" = "Format"; -"recordDesktopAudio" = "Record desktop audio [β]"; -"micSyncOffset" = "Sync offset for mic [ms]"; -"developing" = "Developing..."; -"videoFormatHEVC" = "hevc (Transparent)"; - -// MARK: - Capture - -"capturePreference" = "Capture Preference"; -"captureType" = "Capture Type"; -"entireDisplay" = "Entire Display"; -"independentWindow" = "Independent Window"; -"display" = "Display"; -"removeVCamFromCapture" = "Remove this app from the capture"; -"window" = "Window"; -"videoCaptureDevice" = "Video Capture Device"; -"previewCapture" = "Preview the capture"; -"errorScreenCapturePermission" = "No permission. Please allow screen recording in the Security & Privacy of the System Preferences."; -"refreshScreen" = "Refresh Screen"; - -// MARK: - Integration -"connect" = "Connect"; -"connecting" = "Connecting..."; -"connected" = "Connected"; -"disconnect" = "Disconnect"; -"disconnected" = "Disconnected"; -"helpMocopIP" = "The port in the PC connection settings on the mocopi side should be \"12351\"."; - -// MARK: - License -"license" = "License"; -"licenseCheckIfAlreadyAcquired" = "If you have already acquired a commercial license, please verify your license. [Check License Status...](vcam2d://auth/checkLicense)"; -"accountManagement" = "Account Management..."; -"manageAccountAndSubscription" = "Manage Account and Subscription"; -"signOut" = "Sign Out"; -"confirmSignOut" = "Are you sure you want to sign out?"; -"checkingLicense" = "Checking License..."; -"commercialLicenseNotActive" = "Commercial license is not active."; -"commercialLicenseRequired" = "A commercial license is required for commercial use."; -"commercialLicenseActive" = "Commercial license is active."; -"expiryDate" = "Expiry Date: "; -"pleaseReauthenticate" = "Please reauthenticate."; -"licenseExpired" = "Your license has expired."; -"acquireLicense" = "Acquire License..."; -"reauthenticate" = "Reauthenticate..."; -"signOutFailed" = "Failed to sign out: "; -"licenseStatusChanged" = "License Status Changed"; -"licenseNoLongerActive" = "Your license is no longer active."; -"licenseNowActive" = "Your license is now active."; - -// MARK: - Language - -"languageOfDevice" = "Language of the device"; - -// MARK: - Application Menu - -"uninstallPlugin" = "Uninstall Virtual Camera Plugin"; -"setUp" = "Set up"; -"aboutApp" = "About %@"; -"checkForUpdates" = "Check for Updates..."; -"file" = "File"; -"openModelList" = "Open Model List"; -"loadVRMFile" = "Load VRM File"; -"loadOnVRoidHub" = "Load Avatar on VRoid Hub"; -"loadModelFile" = "Load Model File"; -"resetModelPosition" = "Reset Model Position"; -"alwaysOnTop" = "Always on Top"; -"resetWindowSize" = "Reset Window Size"; -"help" = "Help"; -"viewDocumentation" = "View Documentation"; -"quitVCam" = "Quit %@"; -"openVCam" = "Open %@"; - -"editModel" = "Edit Model"; -"calibrate" = "Calibrate"; - -"update" = "Update"; -"add" = "Add"; -"installPlugin %@" = "%@ a virtual camera plugin"; -"installOne %@" = "Install %@"; -"success" = "Success"; -"restartAfterInstalling" = "Setup is complete. Please restart Zoom or other clients."; -"failure" = "Failure"; -"deletePlugin" = "Delete the virtual camera plugin."; -"deleteOne %@" = "Delete %@"; -"completeUninstalling" = "Uninstallation is complete."; - -// MARK: - Updates - -"existsNewAppVersion %@" = "A new version %@ is available!"; -"currentVersion %@" = "Current Version: %@"; -"releaseNotes" = "Release Notes:"; -"downloadSupporterVersion" = "Download for Supporters"; -"skipThisVersion" = "Skip This Version"; -"upToDate" = "You're up-to-date!"; -"upToDateMessage %@" = "%@ is currently the latest version"; - -// MARK: - Migration - -"failedToInstallCameraPlugin" = "Failed to install the virtual camera. Please reinstall the virtual camera in this app’s settings."; -"deleteOldDALPlugin" = "Delete the Old Virtual Camera"; -"deleteOldDALPluginMessage" = "The old virtual camera is no longer supported, so it'll be deleted now."; -"migrateToNewVirtualCamera" = "Migrate to New Virtual Camera"; -"migrateToNewVirtualCameraMessage" = "This app will migrate to a virtual camera optimized for the latest macOS.\nPlease follow the instructions to delete the old plugin and install the new virtual camera."; - -// MARK: - Shortcut - -"createShortcut" = "Create Shortcut"; -"shortcutKey" = "Shortcut Key"; -"action" = "Action"; -"isNotSetYet %@" = "%@ is not set yet."; -"wait" = "Wait"; -"loadScene" = "Load Scene"; -"recordingShortcutKey" = "Recording..."; -"recordingShortcutKeyError" = "At least one modifier key must be set."; - -// MARK: - Authentication - -"authenticationError" = "Authentication Error"; -"pleaseRestartAppAndTryAgain" = "Please restart the app and try again."; - -// MARK: - Tracking Mapping - -"trackingAdjustment" = "Tracking Adjustment"; -"trackingMode" = "Tracking Mode"; -"trackingMappingSaveComingSoon" = "Save feature will be added in a future update."; -"trackingInput__posX" = "Position X"; -"trackingInput__posY" = "Position Y"; -"trackingInput__posZ" = "Position Z"; -"trackingInput__headX" = "Head Rotation X"; -"trackingInput__headY" = "Head Rotation Y"; -"trackingInput__headZ" = "Head Rotation Z"; -"trackingInput__eyeX" = "Eye Movement X"; -"trackingInput__eyeY" = "Eye Movement Y"; -"trackingInput__blinkL" = "Blink Left"; -"trackingInput__blinkR" = "Blink Right"; -"trackingInput__mouth" = "Mouth"; -"trackingInput__vowel" = "Vowel"; -"trackingMappingInput" = "Input"; -"trackingMappingOutput" = "Output"; -"editOutputBounds" = "Edit Output Bounds"; -"editOutputBoundsMessage" = "Set the minimum and maximum values for the output range."; -"minimum" = "Minimum"; -"maximum" = "Maximum"; - -// MARK: - Model List - -"modelList" = "Model List"; -"noModelsFound" = "No models found"; -"loadModel" = "Load"; -"confirmDeleteModel %@" = "Are you sure you want to delete \"%@\"?"; -"modelMissing" = "Missing"; diff --git a/app/xcode/Sources/VCamLocalization/VCamResources/ja.lproj/Localizable.strings b/app/xcode/Sources/VCamLocalization/VCamResources/ja.lproj/Localizable.strings deleted file mode 100644 index 3a42940..0000000 --- a/app/xcode/Sources/VCamLocalization/VCamResources/ja.lproj/Localizable.strings +++ /dev/null @@ -1,385 +0,0 @@ -/* - Localizable.strings - VCam - - Created by Tatsuya Tanaka on 2022/04/06. - -*/ - -// MARK: - Common - -"ok" = "OK"; -"default" = "デフォルト"; -"cancel" = "キャンセル"; -"close" = "閉じる"; -"done" = "完了"; -"edit" = "編集"; -"pick" = "選択"; -"general" = "一般"; -"normal" = "通常"; -"apply" = "適用"; -"delete" = "削除"; -"duplicate" = "複製"; -"rename" = "名前を変更"; -"changeThumbnail" = "サムネイルを変更"; -"title" = "タイトル"; -"notitle" = "タイトルなし"; -"object" = "オブジェクト"; -"model" = "モデル"; -"image" = "画像"; -"screen" = "画面"; -"web" = "ウェブ"; -"clipboard" = "クリップボード"; -"camera" = "カメラ"; -"mic" = "マイク"; -"virtualCamera" = "仮想カメラ"; -"scene" = "シーン"; -"message" = "メッセージ"; -"destinationToSave" = "保存先"; -"update" = "アップデート"; -"download" = "ダウンロード"; -"install" = "インストール"; -"uninstall" = "アンインストール"; -"reinstall" = "再インストール"; -"openFile" = "ファイルを開く"; -"reload" = "再読み込み"; -"enable" = "有効にする"; -"show" = "表示する"; -"hide" = "非表示にする"; -"lock" = "ロックする"; -"unlock" = "ロックを解除する"; -"filter" = "フィルタ"; -"threshold" = "しきい値"; -"cut" = "切り取り"; -"copy" = "コピー"; -"paste" = "貼り付け"; -"selectAll" = "すべてを選択"; -"runCode" = "実行"; -"width" = "幅"; -"height" = "高さ"; -"seconds" = "秒"; -"notSupported" = "サポートされていません"; -"resetAllToDefault" = "すべてを初期値に戻す"; -"resetToDefault" = "初期値に戻す"; - -// MARK: - Menu - -"main" = "メイン"; -"message" = "メッセージ"; -"settings" = "設定"; -"tracking" = "トラッキング"; -"screenEffect" = "画面効果"; -"recording" = "撮影"; -"integration" = "連携"; - -// MARK: - Motion - -"motion" = "モーション"; -"hi" = "こんにちは"; -"bye" = "バイバイ"; -"jump" = "ジャンプ"; -"cheer" = "エイエイオー!"; -"what" = "What!?"; -"pose" = "やったね"; -"nod" = "うんうん"; -"no" = "首を振る"; -"shudder" = "ブルブル"; -"run" = "走る"; -"facialExpression" = "表情"; - -// MARK: - Expression -"_expauto_default_" = "デフォルト"; - -// MARK: - Emoji - -"emoji" = "絵文字"; -"sticker" = "スタンプ"; - -// MARK: - Wind - -"wind" = "風"; -"changeWindDirection" = "風の向きを変える (ランダム)"; - -// MARK: - Object - -"manageObjects" = "オブジェクト操作"; -"addImage" = "画像を追加"; -"addScreenCapture" = "画面キャプチャを追加"; -"addVideoCapture" = "映像キャプチャを追加"; -"addWeb" = "ウェブを追加"; -"addWind" = "風を追加"; -"screenCapture" = "画面キャプチャ"; -"videoCapture" = "映像キャプチャ"; -"deleteSelectedObject" = "選択中のオブジェクトを削除する"; -"interact" = "操作"; -"localFile" = "ローカルファイル"; -"setAsBackground" = "背景に設定する"; - -"moveInitialPosition" = "カメラを初期位置に戻す"; - -// MARK: - Preference - -"playIdleMotions" = "待機モーションをランダム再生する"; -"simulateShadows" = "影をシミュレーションする (負荷増)"; -"optimizeMeshes" = "モデルのメッシュを最適化する (推奨)"; -"enableAutoConvertingToVRM1" = "VRM0.x系のモデルを1.0系に自動変換する"; -"helpMesh" = "メッシュの結合等によりアプリの負荷を大幅に下げられます。モデルの表示に問題がある場合はオフにした後、モデルを再読込してください。"; -"flipScreen" = "仮想カメラの画面を左右反転する"; -"addToMacOSMenuBar" = "macOSのメニューバーに追加する"; -"background" = "背景"; -"lipSyncSensitivity" = "リップシンクの感度 (マイク)"; -"fpsScreen" = "FPS (画面の更新頻度)"; -"fpsCamera" = "カメラFPS (トラッキングの更新頻度)"; -"screenResolution" = "画面解像度"; -"asHorizontalVideo" = "(横長)"; -"asVerticalVideo" = "(縦長)"; -"renderingQuality" = "描画品質"; -"qualityFastest" = "最低負荷"; -"qualityFast" = "低負荷"; -"qualitySimple" = "普通"; -"qualityGood" = "良品質"; -"qualityBeautiful" = "高品質"; -"qualityFantastic" = "最高品質"; -"rendering" = "レンダリング"; -"experiment" = "実験的な機能"; -"experimentDisclaimer" = "これらは実験的な機能のため、不具合があるかもしれません。"; -"experimentThanks" = "これらの機能はサポーター向けに提供しています。応援ありがとうございます!"; -"experimentAdvertisement" = "これらの機能はサポーター向けに提供しています。サポーター版は以下からDLできます。"; -"enableVSync" = "VSyncを有効にする"; -"vcamTrackingV2" = "VCamトラッキング2.0 (新しいトラッキングシステム)"; -"installVirtualCamera" = "仮想カメラのインストール"; -"explainAboutReinstallingCameraExtension" = "仮想カメラの更新のため、仮想カメラの再インストールを行います"; -"explainAboutInstallingCameraExtension" = "仮想カメラをインストールします。\n「システム設定を開く」をクリックして、「許可」をクリックしてください。"; -"noteEnableNewCameraExtension" = "インストール後はアプリを一度再起動してください"; -"cameraExtensionWorking" = "仮想カメラは動作しています。"; -"cameraExtensionNotWorking" = "仮想カメラは動作していません。"; -"pleaseRestartMacToFix" = "Macを再起動すると不具合が改善される場合があります。"; -"cameraExtensionAwaitingUserApproval" = "仮想カメラが許可されていません。設定アプリの「一般」→「ログイン項目と拡張機能」から許可してください。"; -"failedToInstallCameraExtension" = "仮想カメラのインストールに失敗しました。利用する場合はこのアプリの設定からインストールしてください。"; -"seeDocumentation" = "詳細はこちらのページをご覧ください。"; -"docsURLForVirtualCamera" = "https://docs.vcamapp.com/virtual-camera/virtualcamera"; -"officialWebsite" = "公式サイト"; -"supportVCamMessage" = "もし、このアプリの継続的な改善を支えたい!と思っていただけましたら、応援していただけるととっても嬉しいです!"; -"supportDeveloperLabel" = "開発者を応援する"; - -// MARK: - Tracking - -"micOrCamera" = "マイクまたはカメラ"; -"helpCalibrate" = "実際の動きとずれている場合は、カメラに対して正面を向いた状態でカメラ目線でこのボタンを押してください"; -"useEmotionBy %@" = "表情を%@で推定して反映する [β] (負荷増)"; -"useVowelEstimation" = "カメラで母音を推定する"; -"isNotFound %@" = "%@が見つかりません"; -"lipSync" = "リップシンク"; -"trackEyes" = "目をトラッキングする"; -"eyesHorizontalSensitivity" = "目の左右の動きの感度"; -"eyesVerticalSensitivity" = "目の上下の動きの感度"; -"easeOfOpeningFingers" = "指の開きやすさ"; -"easeOfCloseFingers" = "指の閉じやすさ"; -"shoulderRotationWeight" = "肩の回転の大きさ"; -"swivelOffset" = "肘の調整"; -"trackingSmoothing" = "動きの滑らかさ (スムージング)"; -"mocapNetworkInterpolation" = "通信補間"; -"mocapNetworkInterpolationHelp" = "通信途切れのカクつきを緩和します(遅延が増えます)。VCamMocapとiFacialMocapに適用されます。"; -"faceEyeMouth" = "顔・目・口"; -"hand" = "手"; -"finger" = "指"; - -// MARK: - Screen effect - -"newPreset" = "新しいプリセット"; -"preset" = "プリセット"; -"save" = "上書き保存"; -"ambientLightIntensity" = "環境光の強さ"; -"ambientLightColor" = "環境光の色"; -"cameraExposure" = "カメラの露出 (EV)"; -"colorFilter" = "色フィルタ"; -"saturation" = "彩度"; -"hueShift" = "色相シフト (Hue Shift)"; -"contrast" = "コントラスト"; -"whiteBalance" = "ホワイトバランス"; -"colorTemperature" = "色温度"; -"tint" = "色合い"; -"bloom" = "ブルーム (Bloom)"; -"intensity" = "強さ"; -"thresholdScreenEffect" = "閾値 (適用する輝度の最小値)"; -"softKnee" = "柔らかさ (Soft Knee)"; -"diffusion" = "光の拡散"; -"anamorphicRatio" = "歪み (アナモルフィック)"; -"color" = "色"; -"lensFlare" = "レンズフレア"; -"lensFlareIntensity" = "レンズフレアの強さ"; -"vignette" = "ビネット効果"; -"smoothness" = "滑らかさ"; -"smoothing" = "スムージング"; -"roundness" = "丸み"; -"none" = "なし"; -"typeNo %@" = "タイプ%@"; - -// MARK: - Filter -"chromaKeying" = "クロマキー合成"; -"blur" = "ブラー / ぼかし"; -"trackingFilterSmooth" = "なめらかさ"; -"trackingFilterResponse" = "反応"; - -// MARK: - Permission - -"allowFor %@" = "%@へのアクセスを許可してください"; -"openPreference" = "設定を開く"; - -// MARK: - Recording - -"takePhoto" = "写真を撮る"; -"timeToTakePhoto" = "撮影までの待ち時間"; -"startRecording" = "録画開始 [β]"; -"stopRecording" = "録画停止"; -"videoFormat" = "形式"; -"recordDesktopAudio" = "PCの音声を録音 [β]"; -"micSyncOffset" = "マイク音の同期オフセット (ミリ秒)"; -"developing" = "開発中..."; -"videoFormatHEVC" = "hevc (透過)"; - -// MARK: - Capture - -"capturePreference" = "キャプチャ設定"; -"captureType" = "キャプチャ方法"; -"entireDisplay" = "全画面"; -"independentWindow" = "特定のウィンドウ"; -"display" = "ディスプレイ"; -"removeVCamFromCapture" = "画面キャプチャからこのアプリを除外"; -"window" = "ウィンドウ"; -"videoCaptureDevice" = "映像デバイス"; -"previewCapture" = "映像をプレビューする"; -"errorScreenCapturePermission" = "画面収録の権限がありません。システム環境設定のセキュリティとプライバシーにて画面収録を許可してください。"; -"refreshScreen" = "画面を更新"; - -// MARK: - Integration -"connect" = "接続"; -"connecting" = "接続中..."; -"connected" = "接続済"; -"disconnect" = "接続解除"; -"disconnected" = "未接続"; -"helpMocopIP" = "mocopi側のPC接続設定でのポートは「12351」にしてください"; - -// MARK: - License -"license" = "ライセンス"; -"licenseCheckIfAlreadyAcquired" = "すでに商用利用ライセンスを取得している場合は、ライセンスの状態を確認してください。 [ライセンスの状態を確認する...](vcam2d://auth/checkLicense)"; -"accountManagement" = "アカウント管理..."; -"manageAccountAndSubscription" = "アカウントとサブスクリプションの管理"; -"signOut" = "ログアウト"; -"confirmSignOut" = "ログアウトしても良いですか?"; -"checkingLicense" = "ライセンスの確認中..."; -"commercialLicenseNotActive" = "商用利用ライセンスが有効ではありません。"; -"commercialLicenseRequired" = "商用利用にはライセンスの取得が必要です。"; -"commercialLicenseActive" = "商用利用ライセンスが有効です。"; -"expiryDate" = "有効期限: "; -"pleaseReauthenticate" = "再認証してください。"; -"licenseExpired" = "ライセンスの有効期限が切れています。"; -"acquireLicense" = "ライセンスを取得する..."; -"reauthenticate" = "再認証する..."; -"signOutFailed" = "ログアウトに失敗しました: "; -"licenseStatusChanged" = "ライセンス状態の変更"; -"licenseNoLongerActive" = "ライセンスが有効ではなくなりました。"; -"licenseNowActive" = "ライセンスが有効になりました。"; - -// MARK: - Language - -"languageOfDevice" = "端末の設定に従う"; - -// MARK: - Application Menu - -"uninstallPlugin" = "プラグインのアンインストール"; -"setUp" = "初期設定"; -"aboutApp" = "このアプリについて"; -"checkForUpdates" = "アップデート確認"; -"file" = "ファイル"; -"openModelList" = "モデル一覧を開く"; -"loadVRMFile" = "VRMファイルを読み込む"; -"loadOnVRoidHub" = "VRoid Hubからモデルを選ぶ"; -"loadModelFile" = "モデルを読み込む"; -"resetModelPosition" = "モデルの位置をリセット"; -"alwaysOnTop" = "ウィンドウを常に最前面にする"; -"resetWindowSize" = "ウィンドウサイズを初期値に戻す"; -"help" = "ヘルプ"; -"viewDocumentation" = "使い方を見る"; -"quitVCam" = "%@を終了"; -"openVCam" = "%@を開く"; - -"editModel" = "モデルの編集"; -"calibrate" = "キャリブレーション"; - -"update" = "更新"; -"add" = "追加"; -"installPlugin %@" = "仮想カメラプラグインを%@します"; -"installOne %@" = "%@が設置されます"; -"success" = "やったね"; -"restartAfterInstalling" = "セットアップが完了しました、Zoom等のクライアントを再起動してください"; -"failure" = "ごめんなさい"; -"deletePlugin" = "仮想カメラプラグインを削除します"; -"deleteOne %@" = "%@が削除されます"; -"completeUninstalling" = "アンインストールが完了しました"; - -// MARK: - Updates - -"existsNewAppVersion %@" = "新しいバージョン %@ があります"; -"currentVersion %@" = "現在のバージョン: %@"; -"releaseNotes" = "リリースノート:"; -"downloadSupporterVersion" = "サポーター版のダウンロード"; -"skipThisVersion" = "このバージョンはスキップ"; -"upToDate" = "最新版です"; -"upToDateMessage %@" = "%@ は最新バージョンです。"; - -// MARK: - Migration - -"failedToInstallCameraPlugin" = "仮想カメラのインストールに失敗しました。このアプリの設定で仮想カメラを再インストールしてください。"; -"deleteOldDALPlugin" = "古い仮想カメラの削除"; -"deleteOldDALPluginMessage" = "古い仮想カメラはサポート終了となりましたので、削除します。"; -"migrateToNewVirtualCamera" = "新しい仮想カメラへの移行"; -"migrateToNewVirtualCameraMessage" = "最新のmacOSに最適化した仮想カメラへ移行します。\n古いプラグインを削除し、新しい仮想カメラをインストールしてください。"; - -// MARK: - Shortcut - -"createShortcut" = "ショートカット作成"; -"shortcutKey" = "ショートカットキー"; -"action" = "アクション"; -"isNotSetYet %@" = "%@が設定されていません"; -"wait" = "待機"; -"loadScene" = "シーン読み込み"; -"recordingShortcutKey" = "修飾キーと文字を入力してください"; -"recordingShortcutKeyError" = "一つ以上の修飾キーと文字を組み合わせてください"; - -// MARK: - Authentication - -"authenticationError" = "認証エラー"; -"pleaseRestartAppAndTryAgain" = "アプリを再起動してもう一度お試しください。"; - -// MARK: - Tracking Mapping - -"trackingAdjustment" = "トラッキング調整"; -"trackingMode" = "トラッキングモード"; -"trackingMappingSaveComingSoon" = "設定の保存機能は今後追加されます"; -"trackingInput__posX" = "位置 X"; -"trackingInput__posY" = "位置 Y"; -"trackingInput__posZ" = "位置 Z"; -"trackingInput__headX" = "頭の回転 X"; -"trackingInput__headY" = "頭の回転 Y"; -"trackingInput__headZ" = "頭の回転 Z"; -"trackingInput__eyeX" = "目の動き X"; -"trackingInput__eyeY" = "目の動き Y"; -"trackingInput__blinkL" = "まばたき 左"; -"trackingInput__blinkR" = "まばたき 右"; -"trackingInput__mouth" = "口"; -"trackingInput__vowel" = "母音"; -"trackingMappingInput" = "入力"; -"trackingMappingOutput" = "出力"; -"editOutputBounds" = "出力範囲を編集"; -"editOutputBoundsMessage" = "出力範囲の最小値と最大値を設定します。"; -"minimum" = "最小値"; -"maximum" = "最大値"; - -// MARK: - Model List - -"modelList" = "モデル一覧"; -"noModelsFound" = "モデルが見つかりません"; -"loadModel" = "読み込む"; -"confirmDeleteModel %@" = "「%@」を削除してもよろしいですか?"; -"modelMissing" = "見つかりません"; diff --git a/app/xcode/Sources/VCamMedia/AudioDevice+.swift b/app/xcode/Sources/VCamMedia/AudioDevice+.swift index 3c06373..a15d527 100644 --- a/app/xcode/Sources/VCamMedia/AudioDevice+.swift +++ b/app/xcode/Sources/VCamMedia/AudioDevice+.swift @@ -75,7 +75,6 @@ public extension AudioDevice { let value = name as? String ?? "" return value -// return value.hasPrefix("CADefaultDevice") ? L10n.default.text : value } func bufferSize() -> UInt32 { diff --git a/app/xcode/Sources/VCamUI/AppMenu.swift b/app/xcode/Sources/VCamUI/AppMenu.swift index f5a7444..cc99386 100644 --- a/app/xcode/Sources/VCamUI/AppMenu.swift +++ b/app/xcode/Sources/VCamUI/AppMenu.swift @@ -58,11 +58,11 @@ public final class AppMenu: NSObject { } private func setupEditMenu(subMenu: NSMenu) { - Self.makeSubMenu(menu: subMenu, title: L10n.edit.text, items: [ - NSMenuItem(title: L10n.cut.text, action: #selector(NSText.copy(_:)), keyEquivalent: "x"), - NSMenuItem(title: L10n.copy.text, action: #selector(NSText.copy(_:)), keyEquivalent: "c"), - NSMenuItem(title: L10n.paste.text, action: #selector(NSText.paste(_:)), keyEquivalent: "v"), - NSMenuItem(title: L10n.selectAll.text, action: #selector(NSText.selectAll(_:)), keyEquivalent: "a"), + Self.makeSubMenu(menu: subMenu, title: String(localized: .edit), items: [ + NSMenuItem(title: String(localized: .cut), action: #selector(NSText.copy(_:)), keyEquivalent: "x"), + NSMenuItem(title: String(localized: .copy), action: #selector(NSText.copy(_:)), keyEquivalent: "c"), + NSMenuItem(title: String(localized: .paste), action: #selector(NSText.paste(_:)), keyEquivalent: "v"), + NSMenuItem(title: String(localized: .selectAll), action: #selector(NSText.selectAll(_:)), keyEquivalent: "a"), ]) } } @@ -70,15 +70,15 @@ public final class AppMenu: NSObject { // MARK: - Main private extension AppMenu { private func setupMainMenu(subMenu: NSMenu) { - let quitItem = makeMenuItem(title: L10n.quitVCam(Bundle.main.displayName).text, action: #selector(quit), keyEquivalent: "q") + let quitItem = makeMenuItem(title: String(localized: .quitVCam(Bundle.main.displayName)), action: #selector(quit), keyEquivalent: "q") subMenu.items.insert(quitItem, at: 0) subMenu.items.insert(.separator(), at: 0) - let updateItem = makeMenuItem(title: L10n.checkForUpdates.text, action: #selector(checkUpdates)) + let updateItem = makeMenuItem(title: String(localized: .checkForUpdates), action: #selector(checkUpdates)) subMenu.items.insert(updateItem, at: 0) subMenu.items.insert(.separator(), at: 0) - let preferenceItem = makeMenuItem(title: L10n.settings.text, action: #selector(openPreferences), keyEquivalent: ",") + let preferenceItem = makeMenuItem(title: String(localized: .settings), action: #selector(openPreferences), keyEquivalent: ",") subMenu.items.insert(preferenceItem, at: 0) - let aboutItem = makeMenuItem(title: L10n.aboutApp(Bundle.main.displayName).text, action: #selector(about)) + let aboutItem = makeMenuItem(title: String(localized: .aboutApp(Bundle.main.displayName)), action: #selector(about)) subMenu.items.insert(aboutItem, at: 0) } @@ -106,15 +106,15 @@ private extension AppMenu { private extension AppMenu { private func setupFileMenu(subMenu: NSMenu) { var items: [NSMenuItem] = [ - makeMenuItem(title: L10n.openModelList.text, action: #selector(openModelList)), + makeMenuItem(title: String(localized: .openModelList), action: #selector(openModelList)), ] #if FEATURE_3 items.append(contentsOf: [ .separator(), - makeMenuItem(title: L10n.loadOnVRoidHub.text, action: #selector(openVRoidHub)), + makeMenuItem(title: String(localized: .loadOnVRoidHub), action: #selector(openVRoidHub)), ]) #endif - Self.makeSubMenu(menu: subMenu, title: L10n.file.text, items: items) + Self.makeSubMenu(menu: subMenu, title: String(localized: .file), items: items) } @objc private func openModelList() { @@ -134,24 +134,24 @@ private extension AppMenu { private func setupObjectMenu(subMenu: NSMenu) { #if FEATURE_3 let items: [NSMenuItem] = [ - makeMenuItem(title: L10n.addImage.text, action: #selector(addImage)), - makeMenuItem(title: L10n.addScreenCapture.text, action: #selector(addScreenCapture)), - makeMenuItem(title: L10n.addVideoCapture.text, action: #selector(addVideoCapture)), - makeMenuItem(title: L10n.addWeb.text, action: #selector(addWeb)), + makeMenuItem(title: String(localized: .addImage), action: #selector(addImage)), + makeMenuItem(title: String(localized: .addScreenCapture), action: #selector(addScreenCapture)), + makeMenuItem(title: String(localized: .addVideoCapture), action: #selector(addVideoCapture)), + makeMenuItem(title: String(localized: .addWeb), action: #selector(addWeb)), .separator(), - makeMenuItem(title: L10n.addWind.text, action: #selector(addWind)), + makeMenuItem(title: String(localized: .addWind), action: #selector(addWind)), ] #else let items: [NSMenuItem] = [ - makeMenuItem(title: L10n.resetModelPosition.text, action: #selector(resetModelPosition)), + makeMenuItem(title: String(localized: .resetModelPosition), action: #selector(resetModelPosition)), .separator(), - makeMenuItem(title: L10n.addImage.text, action: #selector(addImage)), - makeMenuItem(title: L10n.addScreenCapture.text, action: #selector(addScreenCapture)), - makeMenuItem(title: L10n.addVideoCapture.text, action: #selector(addVideoCapture)), - makeMenuItem(title: L10n.addWeb.text, action: #selector(addWeb)), + makeMenuItem(title: String(localized: .addImage), action: #selector(addImage)), + makeMenuItem(title: String(localized: .addScreenCapture), action: #selector(addScreenCapture)), + makeMenuItem(title: String(localized: .addVideoCapture), action: #selector(addVideoCapture)), + makeMenuItem(title: String(localized: .addWeb), action: #selector(addWeb)), ] #endif - Self.makeSubMenu(menu: subMenu, title: L10n.object.text, items: items) + Self.makeSubMenu(menu: subMenu, title: String(localized: .object), items: items) } @objc private func addImage() { @@ -186,11 +186,11 @@ private extension AppMenu { // MARK: - Model private extension AppMenu { private func setupModelMenu(subMenu: NSMenu) { - Self.makeSubMenu(menu: subMenu, title: L10n.model.text, items: [ - makeMenuItem(title: L10n.editModel.text, action: #selector(editModel)), + Self.makeSubMenu(menu: subMenu, title: String(localized: .model), items: [ + makeMenuItem(title: String(localized: .editModel), action: #selector(editModel)), .separator(), - makeMenuItem(title: L10n.calibrate.text, action: #selector(resetCalibration)), - makeMenuItem(title: L10n.resetModelPosition.text, action: #selector(resetModelPosition)), + makeMenuItem(title: String(localized: .calibrate), action: #selector(resetCalibration)), + makeMenuItem(title: String(localized: .resetModelPosition), action: #selector(resetModelPosition)), ]) } @@ -211,12 +211,12 @@ private extension AppMenu { // MARK: - Window private extension AppMenu { private func setupWindowMenu(subMenu: NSMenu) { - let alwaysOnTop = makeMenuItem(title: L10n.alwaysOnTop.text, action: #selector(toggleAlwaysOnTop)) + let alwaysOnTop = makeMenuItem(title: String(localized: .alwaysOnTop), action: #selector(toggleAlwaysOnTop)) alwaysOnTop.state = UserDefaults.standard.value(for: .alwaysOnTopEnabled) ? .on : .off - Self.makeSubMenu(menu: subMenu, title: L10n.window.text, items: [ + Self.makeSubMenu(menu: subMenu, title: String(localized: .window), items: [ alwaysOnTop, .separator(), - makeMenuItem(title: L10n.resetWindowSize.text, action: #selector(resetWindowSize)), + makeMenuItem(title: String(localized: .resetWindowSize), action: #selector(resetWindowSize)), ]) } @@ -234,8 +234,8 @@ private extension AppMenu { // MARK: - Help private extension AppMenu { private func setupHelpMenu(subMenu: NSMenu) { - Self.makeSubMenu(menu: subMenu, title: L10n.help.text, items: [ - makeMenuItem(title: L10n.viewDocumentation.text, action: #selector(help)), + Self.makeSubMenu(menu: subMenu, title: String(localized: .help), items: [ + makeMenuItem(title: String(localized: .viewDocumentation), action: #selector(help)), ]) } diff --git a/app/xcode/Sources/VCamUI/AppUpdater+UI.swift b/app/xcode/Sources/VCamUI/AppUpdater+UI.swift index 6cf4ad0..d582eff 100644 --- a/app/xcode/Sources/VCamUI/AppUpdater+UI.swift +++ b/app/xcode/Sources/VCamUI/AppUpdater+UI.swift @@ -1,14 +1,6 @@ -// -// AppUpdater+UI.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/23. -// - import SwiftUI import VCamEntity import VCamData -import VCamLocalization struct AppUpdateInformationView: View { let release: AppUpdater.LatestRelease @@ -19,11 +11,11 @@ struct AppUpdateInformationView: View { var body: some View { VStack(alignment: .leading) { - Text(L10n.existsNewAppVersion(release.version.description).key, bundle: .localize) + Text(.existsNewAppVersion(release.version.description)) .font(.title) .fontWeight(.bold) - Text(L10n.currentVersion(Version.current.description).key, bundle: .localize) - Text(L10n.releaseNotes.key, bundle: .localize) + Text(.currentVersion(Version.current.description)) + Text(.releaseNotes) .fontWeight(.bold) .padding(.top) ScrollView { @@ -39,26 +31,25 @@ struct AppUpdateInformationView: View { skipThisVersion = release.version.description nsWindow?.close() } label: { - Text(L10n.skipThisVersion.key, bundle: .localize) + Text(.skipThisVersion) } .keyboardShortcut(.cancelAction) Spacer() Button { - switch LocalizationEnvironment.language { - case .japanese: + if Bundle.module.preferredLocalizations.first == "ja" { NSWorkspace.shared.open(URL(string: "https://tattn.fanbox.cc/posts/3541433")!) - case .english: + } else { NSWorkspace.shared.open(URL(string: "https://www.patreon.com/posts/64958634")!) } } label: { - Text(L10n.downloadSupporterVersion.key, bundle: .localize) + Text(.downloadSupporterVersion) } Button { NSWorkspace.shared.open(release.downloadURL) } label: { - Text(L10n.download.key, bundle: .localize) + Text(.download) } .keyboardShortcut(.defaultAction) } @@ -70,14 +61,14 @@ struct AppUpdateInformationView: View { } extension AppUpdateInformationView: MacWindow { - var windowTitle: String { L10n.update.text } + var windowTitle: String { String(localized: .update) } } extension AppUpdater { @MainActor func presentUpdateAlert() async { guard let release = try? await check() else { - await VCamAlert.showModal(title: L10n.upToDate.text, message: L10n.upToDateMessage(Version.current.description).text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .upToDate), message: String(localized: .upToDateMessage(Version.current.description)), canCancel: false) return } diff --git a/app/xcode/Sources/VCamUI/CaptureDeviceRenderer+UI.swift b/app/xcode/Sources/VCamUI/CaptureDeviceRenderer+UI.swift index 34e53b4..d8f0e61 100644 --- a/app/xcode/Sources/VCamUI/CaptureDeviceRenderer+UI.swift +++ b/app/xcode/Sources/VCamUI/CaptureDeviceRenderer+UI.swift @@ -8,7 +8,7 @@ import VCamLogger public func showCaptureDeviceSelectView(didSelect: @escaping (AVCaptureDevice, CGRect) -> Void) { guard Camera.hasCamera else { return } // Calling the following will crash if there's no camera. showSheet( - title: L10n.capturePreference.text, + title: String(localized: .capturePreference), view: { close in CaptureDeviceSelectView(didSelect: didSelect, close: close) } @@ -27,7 +27,7 @@ private struct CaptureDeviceSelectView: View { @State private var cropPreviewWidth: CGFloat = 1 var body: some View { - ModalSheet(doneTitle: L10n.addVideoCapture.text) { + ModalSheet(doneTitle: String(localized: .addVideoCapture)) { dismiss() } done: { dismiss() @@ -39,12 +39,12 @@ private struct CaptureDeviceSelectView: View { } content: { VStack { Form { - Picker(L10n.videoCaptureDevice.text, selection: $captureDevice) { + Picker(.videoCaptureDevice, selection: $captureDevice) { ForEach(Camera.cameras(type: nil)) { device in Text(device.localizedName).tag(device) } } - Toggle(L10n.previewCapture.text, isOn: $previewable) + Toggle(.previewCapture, isOn: $previewable) } if previewable, let preview = preview { Image(nsImage: preview) diff --git a/app/xcode/Sources/VCamUI/DeviceAuthorization.swift b/app/xcode/Sources/VCamUI/DeviceAuthorization.swift index 130bb54..39baab0 100644 --- a/app/xcode/Sources/VCamUI/DeviceAuthorization.swift +++ b/app/xcode/Sources/VCamUI/DeviceAuthorization.swift @@ -8,8 +8,8 @@ public enum DeviceAuthorization { public var name: String { switch self { - case .camera: return L10n.camera.text - case .mic: return L10n.mic.text + case .camera: return String(localized: .camera) + case .mic: return String(localized: .mic) } } @@ -62,7 +62,7 @@ public enum DeviceAuthorization { @MainActor private static func showAuthorizationError(type: AuthorizationType) async { - switch await VCamAlert.showModal(title: "", message: L10n.allowFor(type.name).text, canCancel: true, okTitle: L10n.openPreference.text) { + switch await VCamAlert.showModal(title: "", message: String(localized: .allowFor(type.name)), canCancel: true, okTitle: String(localized: .openPreference)) { case .ok: type.openPreference() case .cancel: () diff --git a/app/xcode/Sources/VCamUI/Exporeted.swift b/app/xcode/Sources/VCamUI/Exporeted.swift deleted file mode 100644 index 37e9b0d..0000000 --- a/app/xcode/Sources/VCamUI/Exporeted.swift +++ /dev/null @@ -1,8 +0,0 @@ -// -// Exported.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/18. -// - -@_exported import VCamLocalization diff --git a/app/xcode/Sources/VCamUI/Extensions/ImageFilterConfiguration+.swift b/app/xcode/Sources/VCamUI/Extensions/ImageFilterConfiguration+.swift index b7529e2..d22f9b1 100644 --- a/app/xcode/Sources/VCamUI/Extensions/ImageFilterConfiguration+.swift +++ b/app/xcode/Sources/VCamUI/Extensions/ImageFilterConfiguration+.swift @@ -1,10 +1,3 @@ -// -// ImageFilterConfiguration+.swift -// -// -// Created by Tatsuya Tanaka on 2022/06/18. -// - import Foundation import VCamEntity @@ -14,9 +7,9 @@ extension ImageFilterConfiguration.FilterType: Identifiable { public var name: String { switch self { case .chromaKey: - return L10n.chromaKeying.text + return String(localized: .chromaKeying) case .blur: - return L10n.blur.text + return String(localized: .blur) } } } diff --git a/app/xcode/Sources/VCamUI/Extensions/LensFlare+.swift b/app/xcode/Sources/VCamUI/Extensions/LensFlare+.swift new file mode 100644 index 0000000..2c3aca4 --- /dev/null +++ b/app/xcode/Sources/VCamUI/Extensions/LensFlare+.swift @@ -0,0 +1,19 @@ +import Foundation +import VCamBridge + +extension LensFlare { + var localizedName: LocalizedStringResource { + switch self { + case .none: + .none + case .type1: + .typeNo("1") + case .type2: + .typeNo("2") + case .type3: + .typeNo("3") + case .type4: + .typeNo("4") + } + } +} diff --git a/app/xcode/Sources/VCamUI/Extensions/LipSyncType+.swift b/app/xcode/Sources/VCamUI/Extensions/LipSyncType+.swift index 7504dee..b94b20f 100644 --- a/app/xcode/Sources/VCamUI/Extensions/LipSyncType+.swift +++ b/app/xcode/Sources/VCamUI/Extensions/LipSyncType+.swift @@ -1,21 +1,13 @@ -// -// LipSyncType+.swift -// -// -// Created by Tatsuya Tanaka on 2022/07/30. -// - import VCamEntity -import VCamLocalization import SwiftUI public extension LipSyncType { - var name: LocalizedStringKey { + var name: LocalizedStringResource { switch self { case .mic: - return L10n.mic.key + return .mic case .camera: - return L10n.camera.key + return .camera } } } diff --git a/app/xcode/Sources/VCamUI/Extensions/QualityLevel+.swift b/app/xcode/Sources/VCamUI/Extensions/QualityLevel+.swift index 5a64ece..a7bab0a 100644 --- a/app/xcode/Sources/VCamUI/Extensions/QualityLevel+.swift +++ b/app/xcode/Sources/VCamUI/Extensions/QualityLevel+.swift @@ -1,30 +1,22 @@ -// -// QualityLevel+.swift -// -// -// Created by Tatsuya Tanaka on 2022/08/13. -// - import Foundation import VCamEntity -import VCamLocalization import SwiftUI public extension QualityLevel { - var localizedName: LocalizedStringKey { + var localizedName: LocalizedStringResource { switch self { case .fastest: - return L10n.qualityFastest.key + return .qualityFastest case .fast: - return L10n.qualityFast.key + return .qualityFast case .simple: - return L10n.qualitySimple.key + return .qualitySimple case .good: - return L10n.qualityGood.key + return .qualityGood case .beautiful: - return L10n.qualityBeautiful.key + return .qualityBeautiful case .fantastic: - return L10n.qualityFantastic.key + return .qualityFantastic } } } diff --git a/app/xcode/Sources/VCamUI/Extensions/SceneObject+.swift b/app/xcode/Sources/VCamUI/Extensions/SceneObject+.swift new file mode 100644 index 0000000..97ce90f --- /dev/null +++ b/app/xcode/Sources/VCamUI/Extensions/SceneObject+.swift @@ -0,0 +1,21 @@ +import Foundation +import VCamEntity + +extension SceneObject.ObjectType { + var localizedName: String { + switch self { + case .avatar: + String(localized: .model) + case .image: + String(localized: .image) + case .screen: + String(localized: .screen) + case .videoCapture: + String(localized: .videoCapture) + case .web: + String(localized: .web) + case .wind: + String(localized: .wind) + } + } +} diff --git a/app/xcode/Sources/VCamUI/Extensions/TrackingMappingEntry+.swift b/app/xcode/Sources/VCamUI/Extensions/TrackingMappingEntry+.swift new file mode 100644 index 0000000..fa10885 --- /dev/null +++ b/app/xcode/Sources/VCamUI/Extensions/TrackingMappingEntry+.swift @@ -0,0 +1,12 @@ +import Foundation +import VCamBridge + +extension TrackingMappingEntry.Key { + var localizedTitle: String { + guard key.hasPrefix("_") else { + return key + } + + return String(localized: String.LocalizationValue(stringLiteral: "trackingInput_" + key), bundle: .module) + } +} diff --git a/app/xcode/Sources/VCamUI/Extensions/VCamAvatarMotion+.swift b/app/xcode/Sources/VCamUI/Extensions/VCamAvatarMotion+.swift index 699c3b7..894eccc 100644 --- a/app/xcode/Sources/VCamUI/Extensions/VCamAvatarMotion+.swift +++ b/app/xcode/Sources/VCamUI/Extensions/VCamAvatarMotion+.swift @@ -1,10 +1,3 @@ -// -// VCamAvatarMotion+.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import SwiftUI import VCamEntity @@ -12,25 +5,25 @@ extension VCamAvatarMotion: CustomStringConvertible { public var description: String { switch self { case .hi: - return L10n.hi.text + return String(localized: .hi) case .bye: - return L10n.bye.text + return String(localized: .bye) case .jump: - return L10n.jump.text + return String(localized: .jump) case .cheer: - return L10n.cheer.text + return String(localized: .cheer) case .what: - return L10n.what.text + return String(localized: .what) case .pose: - return L10n.pose.text + return String(localized: .pose) case .nod: - return L10n.nod.text + return String(localized: .nod) case .no: - return L10n.no.text + return String(localized: .no) case .shudder: - return L10n.shudder.text + return String(localized: .shudder) case .run: - return L10n.run.text + return String(localized: .run) } } } diff --git a/app/xcode/Sources/VCamUI/Extensions/VCamScene+.swift b/app/xcode/Sources/VCamUI/Extensions/VCamScene+.swift new file mode 100644 index 0000000..052ba21 --- /dev/null +++ b/app/xcode/Sources/VCamUI/Extensions/VCamScene+.swift @@ -0,0 +1,8 @@ +import Foundation +import VCamEntity + +extension VCamScene { + var localizedDisplayName: String { + name.isEmpty ? String(localized: .scene) : name + } +} diff --git a/app/xcode/Sources/VCamUI/Extensions/VideoFormat+.swift b/app/xcode/Sources/VCamUI/Extensions/VideoFormat+.swift new file mode 100644 index 0000000..869da7b --- /dev/null +++ b/app/xcode/Sources/VCamUI/Extensions/VideoFormat+.swift @@ -0,0 +1,17 @@ +import Foundation +import VCamEntity + +extension VideoFormat { + var localizedName: String { + switch self { + case .mp4: + "mp4" + case .mov: + "mov" + case .m4v: + "m4v" + case .hevcWithAlpha: + String(localized: .videoFormatHEVC) + } + } +} diff --git a/app/xcode/Sources/VCamUI/ImageFilterView.swift b/app/xcode/Sources/VCamUI/ImageFilterView.swift index 9b84edb..3783ffa 100644 --- a/app/xcode/Sources/VCamUI/ImageFilterView.swift +++ b/app/xcode/Sources/VCamUI/ImageFilterView.swift @@ -4,7 +4,7 @@ import VCamEntity @MainActor public func showImageFilterView(image: NSImage, configuration: ImageFilterConfiguration?, completion: @escaping (ImageFilter) -> Void) { showSheet( - title: L10n.filter.text, + title: String(localized: .filter), view: { close in ImageFilterView(image: image.ciImage ?? .empty(), configuration: configuration, close: close, completion: completion) } @@ -22,7 +22,7 @@ public struct ImageFilterView: View { @State private var preview = NSImage() public var body: some View { - ModalSheet(doneTitle: L10n.apply.text) { + ModalSheet(doneTitle: String(localized: .apply)) { dismiss() } done: { dismiss() @@ -128,13 +128,13 @@ struct ImageFilterParameterView: View { switch filter?.type { case let .chromaKey(chromaKey): Form { - ColorEditField(L10n.color.key, value: .init(value: color) { color in + ColorEditField(.color, value: .init(value: color) { color in var chromaKey = chromaKey chromaKey.color = VCamColor(color: color) filter?.type = .chromaKey(chromaKey) self.color = color }) - ValueEditField(L10n.threshold.key, value: .init(value: CGFloat(chromaKey.threshold), set: { threshold in + ValueEditField(.threshold, value: .init(value: CGFloat(chromaKey.threshold), set: { threshold in var chromaKey = chromaKey chromaKey.threshold = Float(threshold) filter?.type = .chromaKey(chromaKey) @@ -146,7 +146,7 @@ struct ImageFilterParameterView: View { } case let .blur(blur): Form { - ValueEditField(L10n.intensity.key, value: .init(value: CGFloat(blur.radius), set: { radius in + ValueEditField(.intensity, value: .init(value: CGFloat(blur.radius), set: { radius in var blur = blur blur.radius = Float(radius) filter?.type = .blur(blur) diff --git a/app/xcode/Sources/VCamUI/LegacyPluginHelper.swift b/app/xcode/Sources/VCamUI/LegacyPluginHelper.swift index 7fd10ef..154838f 100644 --- a/app/xcode/Sources/VCamUI/LegacyPluginHelper.swift +++ b/app/xcode/Sources/VCamUI/LegacyPluginHelper.swift @@ -44,8 +44,8 @@ public struct LegacyPluginHelper { Logger.log(event: .installPlugin) guard await VCamAlert.showModal( - title: L10n.installPlugin(isUpdate ? L10n.update.text : L10n.add.text).text, - message: L10n.installOne(pluginPath.path).text, canCancel: true) == .ok + title: String(localized: .installPlugin(isUpdate ? String(localized: .update) : String(localized: .add))), + message: String(localized: .installOne(pluginPath.path)), canCancel: true) == .ok else { Logger.log("cancel") return @@ -57,17 +57,17 @@ public struct LegacyPluginHelper { let cp = "cp -r \\\"\(sourcePluginPath.path)\\\" \\\"\(pluginPath.path)\\\"" try await NSAppleScript.execute("do shell script \"\(rm) && \(cp)\" with administrator privileges") - await VCamAlert.showModal(title: L10n.success.text, message: L10n.restartAfterInstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .restartAfterInstalling), canCancel: false) UserDefaults.standard.set(pluginVersion, for: .pluginVersion) } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: error.localizedDescription, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: error.localizedDescription, canCancel: false) Logger.log("error") } } @MainActor public static func uninstallPlugin(canCancel: Bool = true) async { - guard await VCamAlert.showModal(title: L10n.deletePlugin.text, message: L10n.deleteOne(pluginPath).text, canCancel: canCancel) == .ok else { + guard await VCamAlert.showModal(title: String(localized: .deletePlugin), message: String(localized: .deleteOne(pluginPath.path)), canCancel: canCancel) == .ok else { return } do { @@ -75,9 +75,9 @@ public struct LegacyPluginHelper { let rm = "rm -r \\\"\(pluginPath.path)\\\"" try await NSAppleScript.execute("do shell script \"\(rm)\" with administrator privileges") - await VCamAlert.showModal(title: L10n.success.text, message: L10n.completeUninstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .completeUninstalling), canCancel: false) } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: error.localizedDescription, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: error.localizedDescription, canCancel: false) } } } diff --git a/app/xcode/Sources/VCamUI/MacWindowManager.swift b/app/xcode/Sources/VCamUI/MacWindowManager.swift index b7ab29d..2774759 100644 --- a/app/xcode/Sources/VCamUI/MacWindowManager.swift +++ b/app/xcode/Sources/VCamUI/MacWindowManager.swift @@ -105,11 +105,8 @@ private struct WindowContainer: View { let content: Content let nsWindow: NSWindow - @AppStorage(key: .locale) var locale - var body: some View { content - .environment(\.locale, locale.isEmpty ? .current : Locale(identifier: locale)) .environment(\.nsWindow, nsWindow) } } diff --git a/app/xcode/Sources/VCamUI/Migration.swift b/app/xcode/Sources/VCamUI/Migration.swift index 8730b33..5aeeee8 100644 --- a/app/xcode/Sources/VCamUI/Migration.swift +++ b/app/xcode/Sources/VCamUI/Migration.swift @@ -40,7 +40,7 @@ extension Migration { @concurrent static func migrationFirst(previousVersion: String) async throws { guard previousVersion.isEmpty else { return } - await VCamAlert.showModal(title: L10n.installVirtualCamera.text, message: L10n.explainAboutInstallingCameraExtension.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .installVirtualCamera), message: String(localized: .explainAboutInstallingCameraExtension), canCancel: false) Task { do { if CoreMediaSinkStream.isInstalled { @@ -48,9 +48,9 @@ extension Migration { } try await CameraExtension().installExtension() _ = await VirtualCameraManager.shared.installAndStartCameraExtension() - await VCamAlert.showModal(title: L10n.success.text, message: L10n.restartAfterInstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .restartAfterInstalling), canCancel: false) } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: L10n.failedToInstallCameraExtension.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: String(localized: .failedToInstallCameraExtension), canCancel: false) } } } @@ -95,8 +95,8 @@ extension Migration { let isNewCameraInstalled = CoreMediaSinkStream.isInstalled await VCamAlert.showModal( - title: isNewCameraInstalled ? L10n.deleteOldDALPlugin.text : L10n.migrateToNewVirtualCamera.text, - message: isNewCameraInstalled ? L10n.deleteOldDALPluginMessage.text : L10n.migrateToNewVirtualCameraMessage.text, + title: isNewCameraInstalled ? String(localized: .deleteOldDALPlugin) : String(localized: .migrateToNewVirtualCamera), + message: isNewCameraInstalled ? String(localized: .deleteOldDALPluginMessage) : String(localized: .migrateToNewVirtualCameraMessage), canCancel: false ) @@ -116,8 +116,8 @@ extension Migration { Logger.log("Migrating to 0.13.1 from \(version.map(String.init).joined(separator: "."))") await VCamAlert.showModal( - title: L10n.update.text, - message: L10n.explainAboutReinstallingCameraExtension.text, + title: String(localized: .update), + message: String(localized: .explainAboutReinstallingCameraExtension), canCancel: false ) @@ -126,9 +126,9 @@ extension Migration { NSWorkspace.shared.open(.cameraExtension) try await CameraExtension().installExtension() _ = await VirtualCameraManager.shared.installAndStartCameraExtension() - await VCamAlert.showModal(title: L10n.success.text, message: L10n.restartAfterInstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .restartAfterInstalling), canCancel: false) } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: L10n.failedToInstallCameraExtension.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: String(localized: .failedToInstallCameraExtension), canCancel: false) Logger.error(error) } } diff --git a/app/xcode/Sources/VCamUI/ModelListView.swift b/app/xcode/Sources/VCamUI/ModelListView.swift index 3e0825b..77066a4 100644 --- a/app/xcode/Sources/VCamUI/ModelListView.swift +++ b/app/xcode/Sources/VCamUI/ModelListView.swift @@ -2,7 +2,6 @@ import SwiftUI import VCamUIFoundation import VCamData import VCamBridge -import VCamLocalization public struct ModelListView: View { @Bindable private var modelManager: ModelManager @@ -47,22 +46,22 @@ public struct ModelListView: View { selectedModel = lastModel } } - .alert(L10n.delete.text, isPresented: $showDeleteConfirmation) { + .alert(.delete, isPresented: $showDeleteConfirmation) { Button(role: .cancel) { modelToDelete = nil } label: { - Text(L10n.cancel.key, bundle: .localize) + Text(.cancel) } Button(role: .destructive) { if let model = modelToDelete { deleteModel(model) } } label: { - Text(L10n.delete.key, bundle: .localize) + Text(.delete) } } message: { if let model = modelToDelete { - Text(L10n.confirmDeleteModel(model.model.localizedName).key, bundle: .localize) + Text(.confirmDeleteModel(model.model.localizedName)) } } } @@ -72,7 +71,7 @@ public struct ModelListView: View { if modelManager.modelItems.isEmpty { ContentUnavailableView { Label { - Text(L10n.noModelsFound.key, bundle: .localize) + Text(.noModelsFound) } icon: { Image(systemName: "figure.arms.open") } @@ -102,20 +101,20 @@ public struct ModelListView: View { modelToRename = item } label: { Image(systemName: "pencil") - Text(L10n.rename.key, bundle: .localize) + Text(.rename) } Button { changeThumbnail(item) } label: { Image(systemName: "photo") - Text(L10n.changeThumbnail.key, bundle: .localize) + Text(.changeThumbnail) } if item.status == .valid { Button { duplicateModel(item) } label: { Image(systemName: "doc.on.doc") - Text(L10n.duplicate.key, bundle: .localize) + Text(.duplicate) } } Divider() @@ -124,7 +123,7 @@ public struct ModelListView: View { showDeleteConfirmation = true } label: { Image(systemName: "trash") - Text(L10n.delete.key, bundle: .localize) + Text(.delete) } .disabled(modelManager.modelItems.count <= 1) } @@ -144,7 +143,7 @@ public struct ModelListView: View { Button { loadSelectedModel() } label: { - Text(L10n.loadModel.key, bundle: .localize) + Text(.loadModel) } .disabled(selectedModel == nil || selectedModel?.status == .missing) .keyboardShortcut(.return, modifiers: []) @@ -233,7 +232,7 @@ struct ModelRowView: View { VStack(alignment: .leading, spacing: 2) { HStack { if shouldEdit { - TextField("", text: $editingName) + TextField(text: $editingName) { EmptyView() } .font(.body) .textFieldStyle(.plain) .focused($isFocused) @@ -254,7 +253,7 @@ struct ModelRowView: View { } } if item.status == .missing { - Text("(\(L10n.modelMissing.text))") + Text(verbatim: "(\(String(localized: .modelMissing)))") .font(.caption) .foregroundStyle(.red) } @@ -308,7 +307,7 @@ struct ModelRowView: View { } extension ModelListView: MacWindow { - public var windowTitle: String { L10n.modelList.text } + public var windowTitle: String { String(localized: .modelList) } public func configureWindow(_ window: NSWindow) -> NSWindow { window.level = .floating @@ -316,7 +315,7 @@ extension ModelListView: MacWindow { } } -#if DEBUG +#if DEBUG && FEATURE_3 #Preview("Empty") { ModelListView() diff --git a/app/xcode/Sources/VCamUI/Resources/Localizable.xcstrings b/app/xcode/Sources/VCamUI/Resources/Localizable.xcstrings new file mode 100644 index 0000000..a732d62 --- /dev/null +++ b/app/xcode/Sources/VCamUI/Resources/Localizable.xcstrings @@ -0,0 +1,4800 @@ +{ + "sourceLanguage": "en", + "strings": { + "aboutApp": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "About %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "このアプリについて" + } + } + } + }, + "accountManagement": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Account Management..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アカウント管理..." + } + } + } + }, + "acquireLicense": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Acquire License..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ライセンスを取得する..." + } + } + } + }, + "action": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Action" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アクション" + } + } + } + }, + "add": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "追加" + } + } + } + }, + "addImage": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Image" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画像を追加" + } + } + } + }, + "addScreenCapture": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Screen" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面キャプチャを追加" + } + } + } + }, + "addToMacOSMenuBar": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add icon in macOS menu bar" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "macOSのメニューバーに追加する" + } + } + } + }, + "addVideoCapture": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Video Capture" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "映像キャプチャを追加" + } + } + } + }, + "addWeb": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Web" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ウェブを追加" + } + } + } + }, + "addWind": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Add Wind" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "風を追加" + } + } + } + }, + "allowFor %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Allow access to %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@へのアクセスを許可してください" + } + } + } + }, + "alwaysOnTop": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Always on Top" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ウィンドウを常に最前面にする" + } + } + } + }, + "ambientLightColor": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Ambient light color" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "環境光の色" + } + } + } + }, + "ambientLightIntensity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Ambient light intensity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "環境光の強さ" + } + } + } + }, + "anamorphicRatio": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Anamorphic ratio" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "歪み (アナモルフィック)" + } + } + } + }, + "apply": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Apply" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "適用" + } + } + } + }, + "asHorizontalVideo": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": " - Horizontal" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "(横長)" + } + } + } + }, + "asVerticalVideo": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": " - Vertical" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "(縦長)" + } + } + } + }, + "background": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Background" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "背景" + } + } + } + }, + "bloom": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Bloom" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ブルーム (Bloom)" + } + } + } + }, + "blur": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blur" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ブラー / ぼかし" + } + } + } + }, + "bye": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Bye" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "バイバイ" + } + } + } + }, + "calibrate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Calibrate" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "キャリブレーション" + } + } + } + }, + "camera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カメラ" + } + } + } + }, + "cameraExposure": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Camera Exposure (EV)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カメラの露出 (EV)" + } + } + } + }, + "cameraExtensionAwaitingUserApproval": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The virtual camera is not allowed. Please allow it from the 'Login Items & Extensions' of 'General' section in the settings app." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラが許可されていません。設定アプリの「一般」→「ログイン項目と拡張機能」から許可してください。" + } + } + } + }, + "cameraExtensionNotWorking": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The virtual camera is NOT working." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラは動作していません。" + } + } + } + }, + "cameraExtensionWorking": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The virtual camera is working." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラは動作しています。" + } + } + } + }, + "cancel": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cancel" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "キャンセル" + } + } + } + }, + "capturePreference": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Capture Preference" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "キャプチャ設定" + } + } + } + }, + "captureType": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Capture Type" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "キャプチャ方法" + } + } + } + }, + "changeThumbnail": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Change Thumbnail" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サムネイルを変更" + } + } + } + }, + "changeWindDirection": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Change the direction of the wind randomly" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "風の向きを変える (ランダム)" + } + } + } + }, + "checkForUpdates": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Check for Updates..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アップデート確認" + } + } + } + }, + "checkingLicense": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Checking License..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ライセンスの確認中..." + } + } + } + }, + "cheer": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cheer" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "エイエイオー!" + } + } + } + }, + "chromaKeying": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Chroma Keying" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "クロマキー合成" + } + } + } + }, + "clipboard": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Clipboard" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "クリップボード" + } + } + } + }, + "close": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Close" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "閉じる" + } + } + } + }, + "color": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Color" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "色" + } + } + } + }, + "colorFilter": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Color Filter" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "色フィルタ" + } + } + } + }, + "colorTemperature": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Color temperature" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "色温度" + } + } + } + }, + "commercialLicenseActive": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Commercial license is active." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "商用利用ライセンスが有効です。" + } + } + } + }, + "commercialLicenseNotActive": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Commercial license is not active." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "商用利用ライセンスが有効ではありません。" + } + } + } + }, + "commercialLicenseRequired": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "A commercial license is required for commercial use." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "商用利用にはライセンスの取得が必要です。" + } + } + } + }, + "completeUninstalling": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Uninstallation is complete." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アンインストールが完了しました" + } + } + } + }, + "confirmDeleteModel %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you sure you want to delete \"%@\"?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "「%@」を削除してもよろしいですか?" + } + } + } + }, + "confirmSignOut": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Are you sure you want to sign out?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ログアウトしても良いですか?" + } + } + } + }, + "connect": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connect" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "接続" + } + } + } + }, + "connected": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connected" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "接続済" + } + } + } + }, + "connecting": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Connecting..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "接続中..." + } + } + } + }, + "contrast": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Contrast" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "コントラスト" + } + } + } + }, + "copy": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Copy" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "コピー" + } + } + } + }, + "createShortcut": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Create Shortcut" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ショートカット作成" + } + } + } + }, + "currentVersion %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Current Version: %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "現在のバージョン: %@" + } + } + } + }, + "cut": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Cut" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "切り取り" + } + } + } + }, + "default": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Default" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "デフォルト" + } + } + } + }, + "delete": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "削除" + } + } + } + }, + "deleteOldDALPlugin": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete the Old Virtual Camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "古い仮想カメラの削除" + } + } + } + }, + "deleteOldDALPluginMessage": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The old virtual camera is no longer supported, so it'll be deleted now." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "古い仮想カメラはサポート終了となりましたので、削除します。" + } + } + } + }, + "deleteOne %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@が削除されます" + } + } + } + }, + "deletePlugin": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Delete the virtual camera plugin." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラプラグインを削除します" + } + } + } + }, + "destinationToSave": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Destination" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "保存先" + } + } + } + }, + "diffusion": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Diffusion" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "光の拡散" + } + } + } + }, + "disconnect": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Disconnect" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "接続解除" + } + } + } + }, + "disconnected": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Disconnected" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "未接続" + } + } + } + }, + "display": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Display" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ディスプレイ" + } + } + } + }, + "docsURLForVirtualCamera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "https://docs.vcamapp.com/v/en/virtual-camera/virtualcamera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "https://docs.vcamapp.com/virtual-camera/virtualcamera" + } + } + } + }, + "done": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Done" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "完了" + } + } + } + }, + "download": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ダウンロード" + } + } + } + }, + "downloadSupporterVersion": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Download for Supporters" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サポーター版のダウンロード" + } + } + } + }, + "duplicate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Duplicate" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "複製" + } + } + } + }, + "easeOfCloseFingers": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Finger closing sensitivity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "指の閉じやすさ" + } + } + } + }, + "easeOfOpeningFingers": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Finger opening sensitivity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "指の開きやすさ" + } + } + } + }, + "edit": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Edit" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "編集" + } + } + } + }, + "editModel": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Edit Model" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデルの編集" + } + } + } + }, + "editOutputBounds": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Edit Output Bounds" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "出力範囲を編集" + } + } + } + }, + "editOutputBoundsMessage": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Set the minimum and maximum values for the output range." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "出力範囲の最小値と最大値を設定します。" + } + } + } + }, + "emoji": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Emoji" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "絵文字" + } + } + } + }, + "enable": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Enable" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "有効にする" + } + } + } + }, + "enableAutoConvertingToVRM1": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Convert VRM 0.x to VRM 1.x" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "VRM0.x系のモデルを1.0系に自動変換する" + } + } + } + }, + "entireDisplay": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Entire Display" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "全画面" + } + } + } + }, + "errorScreenCapturePermission": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No permission. Please allow screen recording in the Security & Privacy of the System Preferences." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面収録の権限がありません。システム環境設定のセキュリティとプライバシーにて画面収録を許可してください。" + } + } + } + }, + "existsNewAppVersion %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "A new version %@ is available!" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "新しいバージョン %@ があります" + } + } + } + }, + "experiment": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Experiment" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "実験的な機能" + } + } + } + }, + "expiryDate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Expiry Date: " + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "有効期限: " + } + } + } + }, + "explainAboutInstallingCameraExtension": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Installing the virtual camera.\nClick on 'Open Security Preferences' and then click 'Allow'." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラをインストールします。\n「システム設定を開く」をクリックして、「許可」をクリックしてください。" + } + } + } + }, + "explainAboutReinstallingCameraExtension": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The virtual camera will be reinstalled for the update" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラの更新のため、仮想カメラの再インストールを行います" + } + } + } + }, + "eyesHorizontalSensitivity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Horizontal sensitivity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "目の左右の動きの感度" + } + } + } + }, + "eyesVerticalSensitivity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Vertical sensitivity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "目の上下の動きの感度" + } + } + } + }, + "faceEyeMouth": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Face / Eye / Mouth" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "顔・目・口" + } + } + } + }, + "facialExpression": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Facial Expression" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "表情" + } + } + } + }, + "failedToInstallCameraExtension": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The installation of the virtual camera failed. Please install it from this app’s settings if you want to use it." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラのインストールに失敗しました。利用する場合はこのアプリの設定からインストールしてください。" + } + } + } + }, + "failure": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Failure" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ごめんなさい" + } + } + } + }, + "file": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "File" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ファイル" + } + } + } + }, + "filter": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Filter" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "フィルタ" + } + } + } + }, + "finger": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Finger" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "指" + } + } + } + }, + "flipScreen": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Flip screen of the virtual camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラの画面を左右反転する" + } + } + } + }, + "fpsCamera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "FPS (tracking)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カメラFPS (トラッキングの更新頻度)" + } + } + } + }, + "fpsScreen": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "FPS (screen)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "FPS (画面の更新頻度)" + } + } + } + }, + "general": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "General" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "一般" + } + } + } + }, + "hand": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hand" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "手" + } + } + } + }, + "height": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Height" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "高さ" + } + } + } + }, + "help": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Help" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ヘルプ" + } + } + } + }, + "helpCalibrate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "If the movement is out of sync with the actual movement, press this button while facing forward to the camera and looking at the camera." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "実際の動きとずれている場合は、カメラに対して正面を向いた状態でカメラ目線でこのボタンを押してください" + } + } + } + }, + "helpMesh": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reduce the load on the app by merging meshes, etc. If you have problems viewing the model, turn it off and reload the model." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "メッシュの結合等によりアプリの負荷を大幅に下げられます。モデルの表示に問題がある場合はオフにした後、モデルを再読込してください。" + } + } + } + }, + "helpMocopIP": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "The port in the PC connection settings on the mocopi side should be \"12351\"." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "mocopi側のPC接続設定でのポートは「12351」にしてください" + } + } + } + }, + "hi": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hi" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "こんにちは" + } + } + } + }, + "hide": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hide" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "非表示にする" + } + } + } + }, + "hueShift": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Hue Shift" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "色相シフト (Hue Shift)" + } + } + } + }, + "image": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Image" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画像" + } + } + } + }, + "independentWindow": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Independent Window" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "特定のウィンドウ" + } + } + } + }, + "install": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Install" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "インストール" + } + } + } + }, + "installOne %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Install %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@が設置されます" + } + } + } + }, + "installPlugin %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ a virtual camera plugin" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラプラグインを%@します" + } + } + } + }, + "installVirtualCamera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Install the Virtual Camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラのインストール" + } + } + } + }, + "integration": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Integration" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "連携" + } + } + } + }, + "intensity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Intensity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "強さ" + } + } + } + }, + "interact": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Interact" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "操作" + } + } + } + }, + "isNotFound %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ is not found" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@が見つかりません" + } + } + } + }, + "isNotSetYet %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ is not set yet." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@が設定されていません" + } + } + } + }, + "jump": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Jump" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ジャンプ" + } + } + } + }, + "language": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Language" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "言語" + } + } + } + }, + "lensFlare": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Lens flare" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "レンズフレア" + } + } + } + }, + "lensFlareIntensity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Lens flare intensity" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "レンズフレアの強さ" + } + } + } + }, + "license": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "License" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ライセンス" + } + } + } + }, + "licenseCheckIfAlreadyAcquired": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "If you have already acquired a commercial license, please verify your license. [Check License Status...](vcam2d://auth/checkLicense)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "すでに商用利用ライセンスを取得している場合は、ライセンスの状態を確認してください。 [ライセンスの状態を確認する...](vcam2d://auth/checkLicense)" + } + } + } + }, + "licenseExpired": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Your license has expired." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ライセンスの有効期限が切れています。" + } + } + } + }, + "lipSync": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Lip-sync" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リップシンク" + } + } + } + }, + "lipSyncSensitivity": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Lip-sync sensitivity (mic)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リップシンクの感度 (マイク)" + } + } + } + }, + "loadModel": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Load" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "読み込む" + } + } + } + }, + "loadOnVRoidHub": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Load Avatar on VRoid Hub" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "VRoid Hubからモデルを選ぶ" + } + } + } + }, + "loadScene": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Load Scene" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "シーン読み込み" + } + } + } + }, + "localFile": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Local File" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ローカルファイル" + } + } + } + }, + "lock": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Lock" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ロックする" + } + } + } + }, + "main": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Main" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "メイン" + } + } + } + }, + "manageAccountAndSubscription": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Manage Account and Subscription" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アカウントとサブスクリプションの管理" + } + } + } + }, + "maximum": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Maximum" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最大値" + } + } + } + }, + "message": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Message" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "メッセージ" + } + } + } + }, + "mic": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Microphone" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "マイク" + } + } + } + }, + "micSyncOffset": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sync offset for mic [ms]" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "マイク音の同期オフセット (ミリ秒)" + } + } + } + }, + "migrateToNewVirtualCamera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Migrate to New Virtual Camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "新しい仮想カメラへの移行" + } + } + } + }, + "migrateToNewVirtualCameraMessage": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "This app will migrate to a virtual camera optimized for the latest macOS.\nPlease follow the instructions to delete the old plugin and install the new virtual camera." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最新のmacOSに最適化した仮想カメラへ移行します。\n古いプラグインを削除し、新しい仮想カメラをインストールしてください。" + } + } + } + }, + "minimum": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Minimum" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最小値" + } + } + } + }, + "mocapNetworkInterpolation": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Network Interpolation" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "通信補間" + } + } + } + }, + "mocapNetworkInterpolationHelp": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reduces jitter from packet drops (adds latency). Applies to VCamMocap and iFacialMocap. " + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "通信途切れのカクつきを緩和します(遅延が増えます)。VCamMocapとiFacialMocapに適用されます。" + } + } + } + }, + "model": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Model" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデル" + } + } + } + }, + "modelList": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Model List" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデル一覧" + } + } + } + }, + "modelMissing": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Missing" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "見つかりません" + } + } + } + }, + "motion": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Motion" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モーション" + } + } + } + }, + "moveInitialPosition": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset position" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カメラを初期位置に戻す" + } + } + } + }, + "newPreset": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "New preset" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "新しいプリセット" + } + } + } + }, + "no": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "首を振る" + } + } + } + }, + "nod": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Nod" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "うんうん" + } + } + } + }, + "noModelsFound": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No models found" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデルが見つかりません" + } + } + } + }, + "none": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "None" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "なし" + } + } + } + }, + "normal": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Normal" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "通常" + } + } + } + }, + "noteEnableNewCameraExtension": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Restart this app once after installation." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "インストール後はアプリを一度再起動してください" + } + } + } + }, + "notitle": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "No Title" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タイトルなし" + } + } + } + }, + "notSupported": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Not Supported" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "サポートされていません" + } + } + } + }, + "object": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Object" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "オブジェクト" + } + } + } + }, + "ok": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "OK" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "OK" + } + } + } + }, + "openFile": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open File" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ファイルを開く" + } + } + } + }, + "openLanguageSettings": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Language Settings" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "macOSの言語設定を開く" + } + } + } + }, + "openModelList": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open Model List" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデル一覧を開く" + } + } + } + }, + "openPreference": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open preferences" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "設定を開く" + } + } + } + }, + "openVCam": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Open %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@を開く" + } + } + } + }, + "optimizeMeshes": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Optimize meshes (Recommended)" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデルのメッシュを最適化する (推奨)" + } + } + } + }, + "paste": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Paste" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "貼り付け" + } + } + } + }, + "pick": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pick" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "選択" + } + } + } + }, + "playIdleMotions": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Play idle motions" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "待機モーションをランダム再生する" + } + } + } + }, + "pleaseReauthenticate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Please reauthenticate." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "再認証してください。" + } + } + } + }, + "pleaseRestartMacToFix": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Restarting Mac may resolve the issue." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "Macを再起動すると不具合が改善される場合があります。" + } + } + } + }, + "pose": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Pose" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "やったね" + } + } + } + }, + "preset": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Preset" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "プリセット" + } + } + } + }, + "previewCapture": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Preview the capture" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "映像をプレビューする" + } + } + } + }, + "qualityBeautiful": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Beautiful" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "高品質" + } + } + } + }, + "qualityFantastic": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fantastic" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最高品質" + } + } + } + }, + "qualityFast": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fast" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "低負荷" + } + } + } + }, + "qualityFastest": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Fastest" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最低負荷" + } + } + } + }, + "qualityGood": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Good" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "良品質" + } + } + } + }, + "qualitySimple": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Simple" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "普通" + } + } + } + }, + "quitVCam": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Quit %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@を終了" + } + } + } + }, + "reauthenticate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reauthenticate..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "再認証する..." + } + } + } + }, + "recordDesktopAudio": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Record desktop audio [β]" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "PCの音声を録音 [β]" + } + } + } + }, + "recording": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Recording" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "撮影" + } + } + } + }, + "recordingShortcutKey": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Recording..." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "修飾キーと文字を入力してください" + } + } + } + }, + "recordingShortcutKeyError": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "At least one modifier key must be set." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "一つ以上の修飾キーと文字を組み合わせてください" + } + } + } + }, + "refreshScreen": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Refresh Screen" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面を更新" + } + } + } + }, + "reinstall": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reinstall" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "再インストール" + } + } + } + }, + "releaseNotes": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Release Notes:" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "リリースノート:" + } + } + } + }, + "reload": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reload" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "再読み込み" + } + } + } + }, + "removeVCamFromCapture": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Remove this app from the capture" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面キャプチャからこのアプリを除外" + } + } + } + }, + "rename": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Rename" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "名前を変更" + } + } + } + }, + "rendering": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Rendering" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "レンダリング" + } + } + } + }, + "renderingQuality": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Rendering Quality" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "描画品質" + } + } + } + }, + "resetAllToDefault": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset All to Default" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "すべてを初期値に戻す" + } + } + } + }, + "resetModelPosition": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset Model Position" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "モデルの位置をリセット" + } + } + } + }, + "resetToDefault": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset to Default" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "初期値に戻す" + } + } + } + }, + "resetWindowSize": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Reset Window Size" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ウィンドウサイズを初期値に戻す" + } + } + } + }, + "restartAfterInstalling": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Setup is complete. Please restart Zoom or other clients." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "セットアップが完了しました、Zoom等のクライアントを再起動してください" + } + } + } + }, + "roundness": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Roundness" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "丸み" + } + } + } + }, + "run": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Run" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "走る" + } + } + } + }, + "runCode": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Run" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "実行" + } + } + } + }, + "saturation": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Saturation" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "彩度" + } + } + } + }, + "save": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Save" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "上書き保存" + } + } + } + }, + "scene": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Scene" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "シーン" + } + } + } + }, + "screen": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Screen" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面" + } + } + } + }, + "screenEffect": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Screen Effect" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面効果" + } + } + } + }, + "screenResolution": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Screen resolution" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "画面解像度" + } + } + } + }, + "seconds": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "s" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "秒" + } + } + } + }, + "seeDocumentation": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "For more information, see this documentation." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "詳細はこちらのページをご覧ください。" + } + } + } + }, + "selectAll": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Select All" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "すべてを選択" + } + } + } + }, + "setAsBackground": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Set As Background" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "背景に設定する" + } + } + } + }, + "settings": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Settings" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "設定" + } + } + } + }, + "shortcutKey": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Shortcut Key" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ショートカットキー" + } + } + } + }, + "shoulderRotationWeight": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Weight of shoulder rotation" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "肩の回転の大きさ" + } + } + } + }, + "show": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Show" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "表示する" + } + } + } + }, + "showLanguageSettingsHelp": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "See How to Change the Language" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "変更方法を見る" + } + } + } + }, + "shudder": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Shudder" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ブルブル" + } + } + } + }, + "signOut": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Sign Out" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ログアウト" + } + } + } + }, + "signOutFailed": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Failed to sign out: " + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ログアウトに失敗しました: " + } + } + } + }, + "skipThisVersion": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Skip This Version" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "このバージョンはスキップ" + } + } + } + }, + "smoothing": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Smoothing" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "スムージング" + } + } + } + }, + "smoothness": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Smoothness" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "滑らかさ" + } + } + } + }, + "softKnee": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Soft Knee" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "柔らかさ (Soft Knee)" + } + } + } + }, + "startRecording": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Start recording [β]" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "録画開始 [β]" + } + } + } + }, + "stopRecording": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Stop recording" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "録画停止" + } + } + } + }, + "success": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Success" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "やったね" + } + } + } + }, + "supportedLanguages": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Supported Languages" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "対応言語" + } + } + } + }, + "swivelOffset": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Elbow offset" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "肘の調整" + } + } + } + }, + "takePhoto": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Take a photo" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "写真を撮る" + } + } + } + }, + "threshold": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Threshold" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "しきい値" + } + } + } + }, + "thresholdScreenEffect": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Threshold" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "閾値 (適用する輝度の最小値)" + } + } + } + }, + "timeToTakePhoto": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Time to take photos" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "撮影までの待ち時間" + } + } + } + }, + "tint": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tint" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "色合い" + } + } + } + }, + "title": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Title" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タイトル" + } + } + } + }, + "trackEyes": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Track eyes" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "目をトラッキングする" + } + } + } + }, + "tracking": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tracking" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "トラッキング" + } + } + } + }, + "trackingAdjustment": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tracking Adjustment" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "トラッキング調整" + } + } + } + }, + "trackingFilterResponse": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Response" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "反応" + } + } + } + }, + "trackingFilterSmooth": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Smooth" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "なめらかさ" + } + } + } + }, + "trackingInput__blinkL": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blink Left" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "まばたき 左" + } + } + } + }, + "trackingInput__blinkR": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Blink Right" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "まばたき 右" + } + } + } + }, + "trackingInput__eyeX": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Eye Movement X" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "目の動き X" + } + } + } + }, + "trackingInput__eyeY": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Eye Movement Y" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "目の動き Y" + } + } + } + }, + "trackingInput__headX": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Head Rotation X" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "頭の回転 X" + } + } + } + }, + "trackingInput__headY": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Head Rotation Y" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "頭の回転 Y" + } + } + } + }, + "trackingInput__headZ": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Head Rotation Z" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "頭の回転 Z" + } + } + } + }, + "trackingInput__mouth": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Mouth" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "口" + } + } + } + }, + "trackingInput__posX": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Position X" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "位置 X" + } + } + } + }, + "trackingInput__posY": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Position Y" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "位置 Y" + } + } + } + }, + "trackingInput__posZ": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Position Z" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "位置 Z" + } + } + } + }, + "trackingInput__vowel": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Vowel" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "母音" + } + } + } + }, + "trackingMappingInput": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Input" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "入力" + } + } + } + }, + "trackingMappingOutput": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Output" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "出力" + } + } + } + }, + "trackingMappingSaveComingSoon": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Save feature will be added in a future update." + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "設定の保存機能は今後追加されます" + } + } + } + }, + "trackingMode": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Tracking Mode" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "トラッキングモード" + } + } + } + }, + "trackingSmoothing": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Smoothing" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "動きの滑らかさ (スムージング)" + } + } + } + }, + "typeNo %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Type %@" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "タイプ %@" + } + } + } + }, + "uninstall": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Uninstall" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "アンインストール" + } + } + } + }, + "uninstallPlugin": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Uninstall Virtual Camera Plugin" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "プラグインのアンインストール" + } + } + } + }, + "unlock": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Unlock" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ロックを解除する" + } + } + } + }, + "update": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Update" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "更新" + } + } + } + }, + "upToDate": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "You're up-to-date!" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "最新版です" + } + } + } + }, + "upToDateMessage %@": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "%@ is currently the latest version" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "%@ は最新バージョンです。" + } + } + } + }, + "useVowelEstimation": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Use vowel estimation by camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "カメラで母音を推定する" + } + } + } + }, + "videoCapture": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Video Capture" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "映像キャプチャ" + } + } + } + }, + "videoCaptureDevice": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Video Capture Device" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "映像デバイス" + } + } + } + }, + "videoFormat": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Format" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "形式" + } + } + } + }, + "videoFormatHEVC": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "HEVC with Alpha" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "HEVC(アルファ付き)" + } + } + } + }, + "viewDocumentation": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "View Documentation" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "使い方を見る" + } + } + } + }, + "vignette": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Vignette" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ビネット効果" + } + } + } + }, + "virtualCamera": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Virtual Camera" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "仮想カメラ" + } + } + } + }, + "wait": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Wait" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "待機" + } + } + } + }, + "web": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Web" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ウェブ" + } + } + } + }, + "what": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "What!?" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "What!?" + } + } + } + }, + "whiteBalance": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "White balance" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ホワイトバランス" + } + } + } + }, + "width": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Width" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "幅" + } + } + } + }, + "wind": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Wind" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "風" + } + } + } + }, + "window": { + "extractionState": "manual", + "localizations": { + "en": { + "stringUnit": { + "state": "translated", + "value": "Window" + } + }, + "ja": { + "stringUnit": { + "state": "translated", + "value": "ウィンドウ" + } + } + } + } + }, + "version": "1.1" +} diff --git a/app/xcode/Sources/VCamUI/RootView.swift b/app/xcode/Sources/VCamUI/RootView.swift index 6e62cb1..7dc3354 100644 --- a/app/xcode/Sources/VCamUI/RootView.swift +++ b/app/xcode/Sources/VCamUI/RootView.swift @@ -15,8 +15,6 @@ public struct RootView: View { let uniState: UniState @State private var isLaunchScreenPresented = true - @AppStorage(key: .locale) var locale - public var body: some View { RootViewContent(unityView: unityView) .background(.regularMaterial) @@ -29,7 +27,6 @@ public struct RootView: View { } } } - .environment(\.locale, locale.isEmpty ? .current : Locale(identifier: locale)) .rootView(state: state, uniState: uniState) } } @@ -96,7 +93,7 @@ private struct UnityView: View { var body: some View { UnityContainerView(unityView: unityView) - // .help(L10n.helpMouseHover.text) + // .help(String(localized: .helpMouseHover)) .frame(maxWidth: .infinity, maxHeight: .infinity) .aspectRatio(1280 / 720, contentMode: .fit) } diff --git a/app/xcode/Sources/VCamUI/SceneObjectManager.swift b/app/xcode/Sources/VCamUI/SceneObjectManager.swift index c316fa1..26528b9 100644 --- a/app/xcode/Sources/VCamUI/SceneObjectManager.swift +++ b/app/xcode/Sources/VCamUI/SceneObjectManager.swift @@ -1,6 +1,5 @@ import SwiftUI import VCamEntity -import VCamLocalization import VCamBridge import VCamData import VCamLogger diff --git a/app/xcode/Sources/VCamUI/ScreenRecorderPreferenceView.swift b/app/xcode/Sources/VCamUI/ScreenRecorderPreferenceView.swift index 64194e9..5dc8c97 100644 --- a/app/xcode/Sources/VCamUI/ScreenRecorderPreferenceView.swift +++ b/app/xcode/Sources/VCamUI/ScreenRecorderPreferenceView.swift @@ -6,7 +6,7 @@ import Combine @MainActor public func showScreenRecorderPreferenceView(capture: @escaping (ScreenRecorder) -> Void) { showSheet( - title: L10n.capturePreference.text, + title: String(localized: .capturePreference), view: { close in ScreenRecorderPreferenceView(close: close, capture: capture) } @@ -35,7 +35,7 @@ public struct ScreenRecorderPreferenceView: View { } public var body: some View { - ModalSheet(doneTitle: L10n.addScreenCapture.text, doneDisabled: !screenRecorder.isRecording) { + ModalSheet(doneTitle: String(localized: .addScreenCapture), doneDisabled: !screenRecorder.isRecording) { dismiss() } done: { error = nil @@ -51,26 +51,26 @@ public struct ScreenRecorderPreferenceView: View { var content: some View { ScrollView { Form { - Picker(L10n.captureType.text, selection: $captureConfig.captureType) { - Text(L10n.entireDisplay.text) + Picker(.captureType, selection: $captureConfig.captureType) { + Text(.entireDisplay) .tag(ScreenRecorder.CaptureType.display) - Text(L10n.independentWindow.text) + Text(.independentWindow) .tag(ScreenRecorder.CaptureType.independentWindow) } switch captureConfig.captureType { case .display: - Picker(L10n.display.text, selection: $captureConfig.display) { + Picker(.display, selection: $captureConfig.display) { ForEach(availableContent?.displays ?? []) { display in - Text("\(display.width) x \(display.height)") + Text(verbatim: "\(display.width) x \(display.height)") .tag(SCDisplay?.some(display)) } } - Toggle(L10n.removeVCamFromCapture.text, isOn: $captureConfig.filterOutOwningApplication) + Toggle(.removeVCamFromCapture, isOn: $captureConfig.filterOutOwningApplication) case .independentWindow: - Picker(L10n.window.text, selection: $captureConfig.window) { + Picker(.window, selection: $captureConfig.window) { ForEach(filteredWindows ?? []) { window in Text(window.displayName) .tag(SCWindow?.some(window)) @@ -87,7 +87,7 @@ public struct ScreenRecorderPreferenceView: View { if let error = error { Group { if error._code == -3801 { - Text(L10n.errorScreenCapturePermission.text) + Text(.errorScreenCapturePermission) } else { Text(error.localizedDescription) } diff --git a/app/xcode/Sources/VCamUI/Settings/LanguageSettingsSection.swift b/app/xcode/Sources/VCamUI/Settings/LanguageSettingsSection.swift new file mode 100644 index 0000000..e9c4ccc --- /dev/null +++ b/app/xcode/Sources/VCamUI/Settings/LanguageSettingsSection.swift @@ -0,0 +1,64 @@ +import AppKit +import SwiftUI + +enum VCamSupportURL { + static let changeLanguageOnMac = URL(string: "https://support.apple.com/guide/mac-help/mh26684/mac")! +} + +enum SupportedLanguages { + static let codes = ["ja", "en"] + + static var displayNames: String { + let names = codes.compactMap { code in + Locale(identifier: code).localizedString(forLanguageCode: code) + } + return ListFormatter.localizedString(byJoining: names) + } +} + +enum SystemSettingsLink { + private static let urls = [ + URL(string: "x-apple.systempreferences:com.apple.Localization-Settings.extension?Apps"), + URL(string: "x-apple.systempreferences:com.apple.Localization-Settings.extension"), + URL(string: "x-apple.systempreferences:com.apple.systempreferences.GeneralSettings"), + URL(fileURLWithPath: "/System/Applications/System Settings.app"), + ].compactMap { $0 } + + @MainActor + static func openAppLanguageSettings(workspace: NSWorkspace = .shared) { + for url in urls where workspace.open(url) { return } + } +} + +struct LanguageSettingsSection: View { + var body: some View { + Section { + LabeledContent { + Text(SupportedLanguages.displayNames) + } label: { + Text(.supportedLanguages) + } + + ViewThatFits(in: .horizontal) { + HStack(spacing: 12) { controls } + VStack(alignment: .leading, spacing: 8) { controls } + } + + } header: { + Text(.language) + } + } + + @ViewBuilder + private var controls: some View { + Button { + SystemSettingsLink.openAppLanguageSettings() + } label: { + Text(.openLanguageSettings) + } + Link(destination: VCamSupportURL.changeLanguageOnMac) { + Text(.showLanguageSettingsHelp) + } + .buttonStyle(.link) + } +} diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingGeneralView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingGeneralView.swift index 5a86711..b9cd71c 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingGeneralView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingGeneralView.swift @@ -1,12 +1,4 @@ -// -// VCamSettingGeneralView.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/14. -// - import SwiftUI -import VCamLocalization import VCamData public struct VCamSettingGeneralView: View { @@ -14,8 +6,6 @@ public struct VCamSettingGeneralView: View { @AppStorage(key: .useHMirror) var useHMirror @AppStorage(key: .useAutoConvertVRM1) var useAutoConvertVRM1 - @AppStorage(key: .locale) var locale - @Environment(UniState.self) private var uniState public var body: some View { @@ -25,31 +15,25 @@ public struct VCamSettingGeneralView: View { Section { #if FEATURE_3 Toggle(isOn: $state.useAutoMode) { - Text(L10n.playIdleMotions.key, bundle: .localize) + Text(.playIdleMotions) } Toggle(isOn: $state.useCombineMesh) { - Text(L10n.optimizeMeshes.key, bundle: .localize) + Text(.optimizeMeshes) } - .help(L10n.helpMesh.text) + .help(.helpMesh) Toggle(isOn: $useAutoConvertVRM1) { - Text(L10n.enableAutoConvertingToVRM1.key, bundle: .localize) + Text(.enableAutoConvertingToVRM1) } #endif Toggle(isOn: $useHMirror) { - Text(L10n.flipScreen.key, bundle: .localize) + Text(.flipScreen) } Toggle(isOn: $state.useAddToMacOSMenuBar) { - Text(L10n.addToMacOSMenuBar.key, bundle: .localize) + Text(.addToMacOSMenuBar) } } - Section { - Picker("Language / 言語", selection: $locale.map(get: LanguageList.init(locale:), set: \.rawValue)) { - ForEach(LanguageList.allCases) { lang in - Text(lang.name).tag(lang.rawValue) - } - } - } + LanguageSettingsSection() } .formStyle(.grouped) .onChange(of: uniState.useAddToMacOSMenuBar) { _, newValue in diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingLicenseView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingLicenseView.swift index 4cf969c..dc8ceb0 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingLicenseView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingLicenseView.swift @@ -1,12 +1,4 @@ -// -// VCamSettingLicenseView.swift -// -// -// Created by tattn on 2025/11/17. -// - import SwiftUI -import VCamLocalization import VCamData import VCamEntity import VCamLogger @@ -49,7 +41,7 @@ struct VCamSettingLicenseView: View { } } footer: { if licenseState == .notLoggedIn { - Text(L10n.licenseCheckIfAlreadyAcquired.key, bundle: .localize) + Text(.licenseCheckIfAlreadyAcquired) .foregroundStyle(.secondary) .font(.footnote) .tint(.accentColor) @@ -63,14 +55,14 @@ struct VCamSettingLicenseView: View { licenseManager.openManagementPage() } label: { Label { - Text(L10n.accountManagement.key, bundle: .localize) + Text(.accountManagement) } icon: { Image(systemName: "gearshape.fill") } } .buttonStyle(.bordered) } label: { - Text(L10n.manageAccountAndSubscription.key, bundle: .localize) + Text(.manageAccountAndSubscription) } } } footer: { @@ -79,7 +71,7 @@ struct VCamSettingLicenseView: View { isSignOutAlertPresented = true } label: { Label { - Text(L10n.signOut.key, bundle: .localize) + Text(.signOut) } icon: { Image(systemName: "rectangle.portrait.and.arrow.right") } @@ -92,19 +84,19 @@ struct VCamSettingLicenseView: View { } .formStyle(.grouped) .disabled(licenseState == .loading) - .confirmationDialog(Text(L10n.signOut.key, bundle: .localize), isPresented: $isSignOutAlertPresented) { + .confirmationDialog(Text(.signOut), isPresented: $isSignOutAlertPresented) { Button(role: .cancel) { } label: { - Text(L10n.cancel.key, bundle: .localize) + Text(.cancel) } Button(role: .destructive) { signOut() } label: { - Text(L10n.signOut.key, bundle: .localize) + Text(.signOut) } } message: { - Text(L10n.confirmSignOut.key, bundle: .localize) + Text(.confirmSignOut) } } @@ -115,16 +107,16 @@ struct VCamSettingLicenseView: View { HStack { ProgressView() .controlSize(.small) - Text(L10n.checkingLicense.key, bundle: .localize) + Text(.checkingLicense) .foregroundStyle(.secondary) } case .notLoggedIn: Label { VStack(alignment: .leading, spacing: 4) { - Text(L10n.commercialLicenseNotActive.key, bundle: .localize) + Text(.commercialLicenseNotActive) .font(.headline) - Text(L10n.commercialLicenseRequired.key, bundle: .localize) + Text(.commercialLicenseRequired) .font(.caption) .foregroundStyle(.secondary) } @@ -136,10 +128,10 @@ struct VCamSettingLicenseView: View { case .active: Label { VStack(alignment: .leading, spacing: 4) { - Text(L10n.commercialLicenseActive.key, bundle: .localize) + Text(.commercialLicenseActive) .font(.headline) if let expiryDate { - (Text(L10n.expiryDate.key, bundle: .localize) + Text(expiryDate, style: .date)) + (Text(.expiryDate) + Text(expiryDate, style: .date)) .font(.caption) .foregroundStyle(.secondary) } @@ -152,9 +144,9 @@ struct VCamSettingLicenseView: View { case .inactive: Label { VStack(alignment: .leading, spacing: 4) { - Text(L10n.commercialLicenseNotActive.key, bundle: .localize) + Text(.commercialLicenseNotActive) .font(.headline) - Text(L10n.pleaseReauthenticate.key, bundle: .localize) + Text(.pleaseReauthenticate) .font(.caption) .foregroundStyle(.secondary) } @@ -166,10 +158,10 @@ struct VCamSettingLicenseView: View { case .expired: Label { VStack(alignment: .leading, spacing: 4) { - Text(L10n.licenseExpired.key, bundle: .localize) + Text(.licenseExpired) .font(.headline) if let expiryDate { - (Text(L10n.expiryDate.key, bundle: .localize) + Text(expiryDate, style: .date)) + (Text(.expiryDate) + Text(expiryDate, style: .date)) .font(.caption) .foregroundStyle(.secondary) } @@ -188,7 +180,7 @@ struct VCamSettingLicenseView: View { EmptyView() case .notLoggedIn: Link(destination: licenseManager.licenseURL) { - Text(L10n.acquireLicense.key, bundle: .localize) + Text(.acquireLicense) } .buttonStyle(.bordered) case .active, .inactive, .expired: @@ -196,7 +188,7 @@ struct VCamSettingLicenseView: View { licenseManager.signIn() } label: { Label { - Text(L10n.reauthenticate.key, bundle: .localize) + Text(.reauthenticate) } icon: { Image(systemName: "arrow.clockwise") } @@ -211,7 +203,7 @@ struct VCamSettingLicenseView: View { errorMessage = nil } catch { Logger.error(error) - errorMessage = Text(L10n.signOutFailed.key, bundle: .localize) + errorMessage = Text(.signOutFailed) } } } @@ -223,7 +215,6 @@ struct VCamSettingLicenseView: View { .environment(\.licenseManager, LicenseManagerStub( licenseState: .notLoggedIn )) - .environment(\.locale, Locale(identifier: "ja_JP")) } #Preview("Logged In / Active") { @@ -259,7 +250,7 @@ struct VCamSettingLicenseView: View { #Preview("Error") { VCamSettingLicenseView( - errorMessage: Text("Network Error") + errorMessage: Text(verbatim: "Network Error") ) .environment(\.licenseManager, LicenseManagerStub( licenseState: .inactive diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingMappingTableView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingMappingTableView.swift index a20a0b9..c056b68 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingMappingTableView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingMappingTableView.swift @@ -2,7 +2,6 @@ import SwiftUI import AppKit import simd import VCamBridge -import VCamLocalization private enum MappingTableSection { case main @@ -35,7 +34,7 @@ struct VCamSettingMappingTableView: NSViewRepresentable { tableView.addTableColumn(enabledColumn) let inputColumn = NSTableColumn(identifier: .input) - inputColumn.title = L10n.trackingMappingInput.text + inputColumn.title = String(localized: .trackingMappingInput) inputColumn.width = 280 inputColumn.minWidth = 280 tableView.addTableColumn(inputColumn) @@ -48,13 +47,13 @@ struct VCamSettingMappingTableView: NSViewRepresentable { tableView.addTableColumn(arrowColumn) let outputColumn = NSTableColumn(identifier: .output) - outputColumn.title = L10n.trackingMappingOutput.text + outputColumn.title = String(localized: .trackingMappingOutput) outputColumn.width = 280 outputColumn.minWidth = 280 tableView.addTableColumn(outputColumn) let filterColumn = NSTableColumn(identifier: .filter) - filterColumn.title = L10n.smoothing.text + filterColumn.title = String(localized: .smoothing) filterColumn.width = 220 filterColumn.minWidth = 180 tableView.addTableColumn(filterColumn) @@ -65,19 +64,19 @@ struct VCamSettingMappingTableView: NSViewRepresentable { let menu = NSMenu() menu.autoenablesItems = true - let editBoundsItem = NSMenuItem(title: L10n.editOutputBounds.text, action: #selector(Coordinator.editOutputBounds(_:)), keyEquivalent: "") + let editBoundsItem = NSMenuItem(title: String(localized: .editOutputBounds), action: #selector(Coordinator.editOutputBounds(_:)), keyEquivalent: "") editBoundsItem.target = context.coordinator menu.addItem(editBoundsItem) menu.addItem(.separator()) - let resetItem = NSMenuItem(title: L10n.resetToDefault.text, action: #selector(Coordinator.resetToDefault(_:)), keyEquivalent: "") + let resetItem = NSMenuItem(title: String(localized: .resetToDefault), action: #selector(Coordinator.resetToDefault(_:)), keyEquivalent: "") resetItem.target = context.coordinator menu.addItem(resetItem) menu.addItem(.separator()) - let deleteItem = NSMenuItem(title: L10n.delete.text, action: #selector(Coordinator.deleteSelected(_:)), keyEquivalent: "") + let deleteItem = NSMenuItem(title: String(localized: .delete), action: #selector(Coordinator.deleteSelected(_:)), keyEquivalent: "") deleteItem.target = context.coordinator menu.addItem(deleteItem) tableView.menu = menu @@ -155,13 +154,13 @@ struct VCamSettingMappingTableView: NSViewRepresentable { if inputKeysChanged { inputKeyTitles = store.inputKeys.map { key in - key.isVCamKey ? L10n.key("trackingInput_\(key.key)").text : key.key + key.localizedTitle } } if outputKeysChanged { outputKeyTitles = store.outputKeys.map { key in - key.isVCamKey ? L10n.key("trackingInput_\(key.key)").text : key.key + key.localizedTitle } } @@ -409,15 +408,15 @@ struct VCamSettingMappingTableView: NSViewRepresentable { let entry = store.mappings[row] let alert = NSAlert() - alert.messageText = L10n.editOutputBounds.text - alert.informativeText = L10n.editOutputBoundsMessage.text - alert.addButton(withTitle: L10n.ok.text) - alert.addButton(withTitle: L10n.cancel.text) + alert.messageText = String(localized: .editOutputBounds) + alert.informativeText = String(localized: .editOutputBoundsMessage) + alert.addButton(withTitle: String(localized: .ok)) + alert.addButton(withTitle: String(localized: .cancel)) let minField = NSTextField(string: String(format: "%.2f", entry.outputKey.bounds.lowerBound)) - minField.placeholderString = L10n.minimum.text + minField.placeholderString = String(localized: .minimum) let maxField = NSTextField(string: String(format: "%.2f", entry.outputKey.bounds.upperBound)) - maxField.placeholderString = L10n.maximum.text + maxField.placeholderString = String(localized: .maximum) minField.translatesAutoresizingMaskIntoConstraints = false maxField.translatesAutoresizingMaskIntoConstraints = false @@ -661,7 +660,7 @@ private final class InputCell: NSView { let newKeyIDs = inputKeys.map(\.key) let titles = inputKeyTitles.count == inputKeys.count ? inputKeyTitles : inputKeys.map { key in - key.isVCamKey ? L10n.key("trackingInput_\(key.key)").text : key.key + key.localizedTitle } if newKeyIDs != inputKeyIDs { @@ -837,7 +836,7 @@ private final class OutputCell: NSView { if hasBlendShapeNames, let popupButton { let newKeyIDs = outputKeys.map(\.key) let titles = outputKeyTitles.count == outputKeys.count ? outputKeyTitles : outputKeys.map { key in - key.isVCamKey ? L10n.key("trackingInput_\(key.key)").text : key.key + key.localizedTitle } if newKeyIDs != outputKeyIDs { @@ -892,7 +891,7 @@ private final class FilterCell: NSView { init() { filterToggle = NSButton(checkboxWithTitle: "", target: nil, action: nil) - filterToggle.toolTip = L10n.smoothing.text + filterToggle.toolTip = String(localized: .smoothing) smoothLabel = NSTextField(labelWithString: "") smoothSlider = NSSlider() smoothValueLabel = NSTextField(labelWithString: "") @@ -1044,7 +1043,7 @@ private final class FilterCell: NSView { let smoothPercent = percentFromUnit(minCutoff) let responsePercent = percentFromUnit(beta) - smoothLabel.stringValue = L10n.trackingFilterSmooth.text + smoothLabel.stringValue = String(localized: .trackingFilterSmooth) smoothLabel.isHidden = false smoothSlider.minValue = 0 smoothSlider.maxValue = 100 @@ -1053,7 +1052,7 @@ private final class FilterCell: NSView { smoothValueLabel.stringValue = formatPercent(smoothPercent) smoothValueLabel.isHidden = false - responseLabel.stringValue = L10n.trackingFilterResponse.text + responseLabel.stringValue = String(localized: .trackingFilterResponse) responseLabel.isHidden = false responseSlider.minValue = 0 responseSlider.maxValue = 100 diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingRenderingView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingRenderingView.swift index 9b5925e..26fcaa8 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingRenderingView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingRenderingView.swift @@ -1,13 +1,5 @@ -// -// VCamSettingRenderingView.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/14. -// - import SwiftUI import VCamEntity -import VCamLocalization import VCamData public struct VCamSettingRenderingView: View { @@ -25,18 +17,19 @@ public struct VCamSettingRenderingView: View { .tag($0) } } label: { - Text(L10n.screenResolution.key, bundle: .localize) + Text(.screenResolution) } Picker(selection: $state.qualityLevel) { ForEach(QualityLevel.allCases) { - Text($0.localizedName, bundle: .localize) + Text($0.localizedName) .tag($0.rawValue) } } label: { - Text(L10n.renderingQuality.key, bundle: .localize) + Text(.renderingQuality) } + .accessibilityIdentifier("settings.rendering.quality") - ValueEditField(L10n.fpsScreen.key, value: $state.fps, type: .slider(10...60)) + ValueEditField(.fpsScreen, value: $state.fps, type: .slider(10...60)) .disabled(uniState.useVSync) } .formStyle(.grouped) @@ -49,7 +42,7 @@ private extension ScreenResolution { } private var videoType: String { - isLandscape ? L10n.asHorizontalVideo.text : L10n.asVerticalVideo.text + isLandscape ? String(localized: .asHorizontalVideo) : String(localized: .asVerticalVideo) } private var shortDescription: String { diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingMappingEditorView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingMappingEditorView.swift index 6cd7008..bfbbd61 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingMappingEditorView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingMappingEditorView.swift @@ -2,7 +2,6 @@ import SwiftUI import AppKit import VCamBridge import VCamData -import VCamLocalization import VCamTracking public struct VCamSettingTrackingMappingEditorView: View { @@ -47,8 +46,8 @@ public struct VCamSettingTrackingMappingEditorView: View { if supportsIPhoneMode { ToolbarItem(placement: .automatic) { - Picker(L10n.trackingMode.text, selection: $store.selectedMode) { - Text(L10n.normal.key, bundle: .localize).tag(TrackingMode.blendShape) + Picker(.trackingMode, selection: $store.selectedMode) { + Text(.normal).tag(TrackingMode.blendShape) Text(verbatim: "iPhone").tag(TrackingMode.perfectSync) } .pickerStyle(.segmented) @@ -65,7 +64,7 @@ public struct VCamSettingTrackingMappingEditorView: View { store.resetAllMappings() } label: { Image(systemName: "arrow.uturn.backward") - Text(L10n.resetAllToDefault.key, bundle: .localize) + Text(.resetAllToDefault) } .foregroundStyle(.red) } label: { @@ -90,7 +89,7 @@ public struct VCamSettingTrackingMappingEditorView: View { HStack { Image(systemName: "info.circle") .foregroundStyle(.secondary) - Text(L10n.trackingMappingSaveComingSoon.text) + Text(.trackingMappingSaveComingSoon) .font(.caption) .foregroundStyle(.secondary) } @@ -103,7 +102,7 @@ public struct VCamSettingTrackingMappingEditorView: View { extension VCamSettingTrackingMappingEditorView: MacWindow { public var windowTitle: String { - L10n.trackingAdjustment.text + String(localized: .trackingAdjustment) } public func configureWindow(_ window: NSWindow) -> NSWindow { diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingView.swift index 5a1db95..b8e27fd 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingTrackingView.swift @@ -1,10 +1,3 @@ -// -// VCamSettingTrackingView.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/14. -// - import SwiftUI import AVFoundation import VCamEntity @@ -40,14 +33,14 @@ public struct VCamSettingTrackingView: View { } Toggle(isOn: $useVowelEstimation) { - Text(L10n.useVowelEstimation.key, bundle: .localize) + Text(.useVowelEstimation) } Section { if uniState.currentLipSync == .mic { - ValueEditField(L10n.lipSyncSensitivity.key, value: $state.lipSyncMicIntensity, type: .slider(0.1...3)) + ValueEditField(.lipSyncSensitivity, value: $state.lipSyncMicIntensity, type: .slider(0.1...3)) } - ValueEditField(L10n.fpsCamera.key, value: $cameraFps.map(), type: .slider(1...60) { + ValueEditField(.fpsCamera, value: $cameraFps.map(), type: .slider(1...60) { guard !$0 else { return } Tracking.shared.avatarCameraManager.setFPS(cameraFps) }) @@ -55,8 +48,8 @@ public struct VCamSettingTrackingView: View { #if FEATURE_3 Section { - ValueEditField(L10n.shoulderRotationWeight.key, value: $state.shoulderRotationWeight, type: .slider(0.0...1)) - ValueEditField(L10n.swivelOffset.key, value: $state.swivelOffset, type: .slider(0.0...30)) + ValueEditField(.shoulderRotationWeight, value: $state.shoulderRotationWeight, type: .slider(0.0...1)) + ValueEditField(.swivelOffset, value: $state.swivelOffset, type: .slider(0.0...30)) } #if ENABLE_MOCOPI .disabled(integrationMocopi) @@ -64,25 +57,25 @@ public struct VCamSettingTrackingView: View { #endif #endif Section { - ValueEditField(L10n.trackingSmoothing.key, value: $state.trackingSmoothing, type: .slider(0...0.9)) { + ValueEditField(.trackingSmoothing, value: $state.trackingSmoothing, type: .slider(0...0.9)) { Text($0, format: .percent.precision(.fractionLength(2))) } } Section { Toggle(isOn: $useEyeTracking) { - Text(L10n.trackEyes.key, bundle: .localize) + Text(.trackEyes) } Group { - ValueEditField(L10n.eyesHorizontalSensitivity.key, value: $eyeTrackingIntensityX.map(), type: .slider(0...10)) - ValueEditField(L10n.eyesVerticalSensitivity.key, value: $eyeTrackingIntensityY.map(), type: .slider(0...10)) + ValueEditField(.eyesHorizontalSensitivity, value: $eyeTrackingIntensityX.map(), type: .slider(0...10)) + ValueEditField(.eyesVerticalSensitivity, value: $eyeTrackingIntensityY.map(), type: .slider(0...10)) } .disabled(!useEyeTracking) .opacity(useEyeTracking ? 1.0 : 0.5) } #if FEATURE_3 Section { - ValueEditField(L10n.easeOfOpeningFingers.key, value: $fingerTrackingOpenIntensity.map(), type: .slider(0.1...3)) - ValueEditField(L10n.easeOfCloseFingers.key, value: $fingerTrackingCloseIntensity.map(), type: .slider(0.1...3)) + ValueEditField(.easeOfOpeningFingers, value: $fingerTrackingOpenIntensity.map(), type: .slider(0.1...3)) + ValueEditField(.easeOfCloseFingers, value: $fingerTrackingCloseIntensity.map(), type: .slider(0.1...3)) } #endif } diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingView.swift index 56234b9..d97db67 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingView.swift @@ -1,14 +1,6 @@ -// -// VCamSettingView.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/12. -// - import SwiftUI import VCamEntity import VCamCamera -import VCamLocalization import AVFoundation public struct VCamSettingView: View { @@ -26,26 +18,26 @@ public struct VCamSettingView: View { public var id: Self { self } - var title: LocalizedStringKey { + var title: String { switch self { case .general: - L10n.general.key + String(localized: .general) case .rendering: - L10n.rendering.key + String(localized: .rendering) case .tracking: - L10n.tracking.key + String(localized: .tracking) case .virtualCamera: - L10n.virtualCamera.key + String(localized: .virtualCamera) case .integration: - L10n.integration.key + String(localized: .integration) case .experiment: - L10n.experiment.key + String(localized: .experiment) #if ENABLE_ACCOUNT case .account: - L10n.license.key + String(localized: .license) #endif case .vcam: - LocalizedStringKey(Bundle.main.displayName) + Bundle.main.displayName } } @@ -77,8 +69,6 @@ public struct VCamSettingView: View { @Bindable private var recorder = VideoRecorder.shared - @AppStorage(key: .locale) var locale - public init(tab: Tab = .general) { self._tab = State(initialValue: tab) } @@ -87,11 +77,12 @@ public struct VCamSettingView: View { HStack { List(Tab.allCases, selection: $tab) { tab in Label { - Text(tab.title, bundle: .localize) + Text(verbatim: tab.title) .font(.callout) } icon: { tab.icon } + .accessibilityIdentifier("settings.tab.\(tab)") } .listStyle(.sidebar) .frame(width: 150) @@ -120,14 +111,13 @@ public struct VCamSettingView: View { } .frame(minWidth: 500, maxHeight: .infinity, alignment: .top) } - .environment(\.locale, locale.isEmpty ? .current : Locale(identifier: locale)) .disabled(recorder.isRecording) .rootView() } } extension VCamSettingView: MacWindow { - public var windowTitle: String { L10n.settings.text } + public var windowTitle: String { String(localized: .settings) } public func configureWindow(_ window: NSWindow) -> NSWindow { window.level = .floating diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingVirtualCameraView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingVirtualCameraView.swift index bb79014..8b0a909 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingVirtualCameraView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingVirtualCameraView.swift @@ -1,12 +1,4 @@ -// -// VCamSettingVirtualCameraView.swift -// -// -// Created by Tatsuya Tanaka on 2023/08/16. -// - import SwiftUI -import VCamLocalization import VCamCamera public struct VCamSettingVirtualCameraView: View { @@ -24,12 +16,12 @@ public struct VCamSettingVirtualCameraView: View { VStack { HStack { Image(systemName: "info.circle") - Text(isCameraExtensionStarting ? L10n.cameraExtensionWorking.key : L10n.cameraExtensionNotWorking.key, bundle: .localize) + Text(isCameraExtensionStarting ? .cameraExtensionWorking : .cameraExtensionNotWorking) } .frame(maxWidth: .infinity) if !isCameraExtensionStarting, isCameraExtensionInstalled { - Text(L10n.pleaseRestartMacToFix.key, bundle: .localize) + Text(.pleaseRestartMacToFix) .font(.footnote) .opacity(0.5) } @@ -40,7 +32,7 @@ public struct VCamSettingVirtualCameraView: View { HStack { Image(systemName: "exclamationmark.triangle") Link(destination: .cameraExtension) { - Text(L10n.cameraExtensionAwaitingUserApproval.key, bundle: .localize) + Text(.cameraExtensionAwaitingUserApproval) } } .frame(maxWidth: .infinity) @@ -57,11 +49,11 @@ public struct VCamSettingVirtualCameraView: View { try await uninstallExtension(isAlertShown: false) try await installExtension() } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: error.localizedDescription, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: error.localizedDescription, canCancel: false) } } } label: { - Text(L10n.reinstall.key, bundle: .localize) + Text(.reinstall) } Button { @@ -70,11 +62,11 @@ public struct VCamSettingVirtualCameraView: View { do { try await uninstallExtension(isAlertShown: true) } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: error.localizedDescription, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: error.localizedDescription, canCancel: false) } } } label: { - Text(L10n.uninstall.key, bundle: .localize) + Text(.uninstall) } } else { Button { @@ -83,25 +75,25 @@ public struct VCamSettingVirtualCameraView: View { do { try await installExtension() } catch { - await VCamAlert.showModal(title: L10n.failure.text, message: error.localizedDescription, canCancel: false) + await VCamAlert.showModal(title: String(localized: .failure), message: error.localizedDescription, canCancel: false) } } } label: { - Text(L10n.install.key, bundle: .localize) + Text(.install) } } } .frame(maxWidth: .infinity) - Text(L10n.noteEnableNewCameraExtension.key, bundle: .localize) + Text(.noteEnableNewCameraExtension) .font(.footnote) .opacity(0.5) } } Section { - Link(destination: URL(string: L10n.docsURLForVirtualCamera.text)!) { - Text(L10n.seeDocumentation.key, bundle: .localize) + Link(destination: URL(string: String(localized: .docsURLForVirtualCamera))!) { + Text(.seeDocumentation) .font(.footnote) } } @@ -127,7 +119,7 @@ extension VCamSettingVirtualCameraView { try await CameraExtension().installExtension() isCameraExtensionInstalled = true isCameraExtensionStarting = await VirtualCameraManager.shared.installAndStartCameraExtension() - await VCamAlert.showModal(title: L10n.success.text, message: L10n.restartAfterInstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .restartAfterInstalling), canCancel: false) } @MainActor @@ -136,7 +128,7 @@ extension VCamSettingVirtualCameraView { isCameraExtensionInstalled = false isCameraExtensionStarting = await VirtualCameraManager.shared.installAndStartCameraExtension() if isAlertShown { - await VCamAlert.showModal(title: L10n.success.text, message: L10n.completeUninstalling.text, canCancel: false) + await VCamAlert.showModal(title: String(localized: .success), message: String(localized: .completeUninstalling), canCancel: false) } } } diff --git a/app/xcode/Sources/VCamUI/Settings/VCamSettingsIntegrationView.swift b/app/xcode/Sources/VCamUI/Settings/VCamSettingsIntegrationView.swift index 0192adb..3e076b1 100644 --- a/app/xcode/Sources/VCamUI/Settings/VCamSettingsIntegrationView.swift +++ b/app/xcode/Sources/VCamUI/Settings/VCamSettingsIntegrationView.swift @@ -1,14 +1,6 @@ -// -// VCamSettingsIntegrationView.swift -// -// -// Created by Tatsuya Tanaka on 2023/01/05. -// - import SwiftUI import VCamTracking import VCamBridge -import VCamLocalization import VCamData import Network @@ -21,11 +13,11 @@ public struct VCamSettingsIntegrationView: View { @Bindable private var facialMocapReceiver = Tracking.shared.iFacialMocapReceiver - private var facialMocapConnectTitle: LocalizedStringKey { + private var facialMocapConnectTitle: LocalizedStringResource { switch facialMocapReceiver.connectionStatus { - case .disconnected: return L10n.connect.key - case .connecting: return L10n.connecting.key - case .connected: return L10n.disconnect.key + case .disconnected: return .connect + case .connecting: return .connecting + case .connected: return .disconnect } } @@ -34,7 +26,7 @@ public struct VCamSettingsIntegrationView: View { if let ipAddress = NWInterface.InterfaceType.wiredEthernet.ipv4 ?? NWInterface.InterfaceType.wifi.ipv4 { FeatureView(title: "Info.") { HStack { - Text("IP:") + Text(verbatim: "IP:") Text(ipAddress) } } @@ -44,12 +36,12 @@ public struct VCamSettingsIntegrationView: View { VCamMotionReceiverStatusView() Toggle(isOn: $integrationVCamMocap) { - Text(L10n.enable.key, bundle: .localize) + Text(.enable) } .labelsHidden() .toggleStyle(.switch) } label: { - Text(L10n.enable.key, bundle: .localize) + Text(.enable) } .onChange(of: integrationVCamMocap) { _, newValue in Task { @@ -80,17 +72,17 @@ public struct VCamSettingsIntegrationView: View { } } } label: { - Text(facialMocapConnectTitle, bundle: .localize) + Text(facialMocapConnectTitle) } } label: { Text(verbatim: "IP") } } Section { - ValueEditField(L10n.mocapNetworkInterpolation.key, value: $mocapNetworkInterpolation.map(), type: .slider(0...1.0)) { + ValueEditField(.mocapNetworkInterpolation, value: $mocapNetworkInterpolation.map(), type: .slider(0...1.0)) { Text($0, format: .percent.precision(.fractionLength(2))) } - Text(L10n.mocapNetworkInterpolationHelp.key, bundle: .localize) + Text(.mocapNetworkInterpolationHelp) .font(.caption2) .foregroundStyle(.secondary) } @@ -108,16 +100,16 @@ public struct VCamSettingsIntegrationView: View { private struct ReceiverStatusView: View { let connectionStatus: ConnectionStatus - private var statusText: LocalizedStringKey { + private var statusText: LocalizedStringResource { switch connectionStatus { - case .disconnected: return L10n.disconnected.key - case .connecting: return L10n.connecting.key - case .connected: return L10n.connected.key + case .disconnected: return .disconnected + case .connecting: return .connecting + case .connected: return .connected } } var body: some View { - Text(statusText, bundle: .localize) + Text(statusText) .foregroundStyle(connectionStatus == .connected ? Color.accentColor : .secondary) .font(.callout) .fontWeight(.medium) @@ -148,10 +140,10 @@ private struct MocopiSettingView: View { var body: some View { VCamSettingsIntegrationView.FeatureView(title: "mocopi") { Toggle(isOn: $integrationMocopi) { - Text(L10n.enable.key, bundle: .localize) + Text(.enable) } } - .help(L10n.helpMocopIP.text) + .help(.helpMocopIP) .onChange(of: integrationMocopi) { _, newValue in UniBridge.shared.useFullTracking(newValue) Tracking.shared.setHandTrackingMethod(.mocopi) diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamAppleScriptAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamAppleScriptAction.swift index 4c0a1d4..61b8de4 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamAppleScriptAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamAppleScriptAction.swift @@ -1,13 +1,5 @@ -// -// VCamAppleScriptAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/16. -// - import AppKit import VCamEntity -import VCamLocalization import struct SwiftUI.Image public struct VCamAppleScriptAction: VCamAction { diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamBlendShapeAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamBlendShapeAction.swift index 4d23e72..e056bc8 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamBlendShapeAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamBlendShapeAction.swift @@ -1,14 +1,6 @@ -// -// VCamBlendShapeAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import AppKit import VCamEntity import VCamBridge -import VCamLocalization import struct SwiftUI.Image public struct VCamBlendShapeAction: VCamAction { @@ -17,13 +9,13 @@ public struct VCamBlendShapeAction: VCamAction { } public var configuration: VCamBlendShapeActionConfiguration - public var name: String { L10n.facialExpression.text } + public var name: String { String(localized: .facialExpression) } public var icon: Image { Image(systemName: "face.smiling") } @MainActor public func callAsFunction(context: VCamActionContext) async throws { guard !configuration.blendShape.isEmpty else { - throw VCamActionError(L10n.isNotSetYet(L10n.facialExpression.text).text) + throw VCamActionError(String(localized: .isNotSetYet(String(localized: .facialExpression)))) } UniBridge.applyExpression(name: configuration.blendShape) diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamEmojiAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamEmojiAction.swift index 40b86af..bf3ec3b 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamEmojiAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamEmojiAction.swift @@ -1,14 +1,6 @@ -// -// VCamEmojiAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/03/24. -// - import AppKit import VCamEntity import VCamBridge -import VCamLocalization import struct SwiftUI.Image public struct VCamEmojiAction: VCamAction { @@ -17,13 +9,13 @@ public struct VCamEmojiAction: VCamAction { } public var configuration: VCamEmojiActionConfiguration - public var name: String { L10n.emoji.text } + public var name: String { String(localized: .emoji) } public var icon: Image { Image(systemName: "smiley") } @MainActor public func callAsFunction(context: VCamActionContext) async throws { guard !configuration.emoji.isEmpty else { - throw VCamActionError(L10n.isNotSetYet(L10n.emoji.text).text) + throw VCamActionError(String(localized: .isNotSetYet(String(localized: .emoji)))) } let url = URL.temporaryDirectory.appending(path: "vcam_emoji.png") try configuration.emoji.drawImage().writeAsPNG(to: url) diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamLoadSceneAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamLoadSceneAction.swift index c3694cd..ea1060d 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamLoadSceneAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamLoadSceneAction.swift @@ -1,13 +1,5 @@ -// -// VCamLoadSceneAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/03. -// - import Foundation import VCamEntity -import VCamLocalization import struct SwiftUI.Image public struct VCamLoadSceneAction: VCamAction { @@ -16,7 +8,7 @@ public struct VCamLoadSceneAction: VCamAction { } public var configuration: VCamLoadSceneActionConfiguration - public var name: String { L10n.loadScene.text } + public var name: String { String(localized: .loadScene) } public var icon: Image { Image(systemName: "square.3.stack.3d.top.fill") } @MainActor diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMessageAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMessageAction.swift index 54cf94c..feb8268 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMessageAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMessageAction.swift @@ -1,13 +1,5 @@ -// -// VCamMessageAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/16. -// - import AppKit import VCamEntity -import VCamLocalization import VCamBridge import VCamData import struct SwiftUI.Image @@ -18,7 +10,7 @@ public struct VCamMessageAction: VCamAction { } public var configuration: VCamMessageActionConfiguration - public var name: String { L10n.message.text } + public var name: String { String(localized: .message) } public var icon: Image { Image(systemName: "text.bubble") } @MainActor diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMotionAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMotionAction.swift index d7c6f4c..a2e6f97 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMotionAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamMotionAction.swift @@ -1,13 +1,5 @@ -// -// VCamMotionAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/01. -// - import AppKit import VCamEntity -import VCamLocalization import VCamBridge import VCamData import SwiftUI @@ -18,7 +10,7 @@ public struct VCamMotionAction: VCamAction { } public var configuration: VCamMotionActionConfiguration - public var name: String { L10n.motion.text } + public var name: String { String(localized: .motion) } public var icon: Image { Image(systemName: "figure.wave") } @MainActor diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamResetCameraAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamResetCameraAction.swift index 28d9c4b..441588a 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamResetCameraAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamResetCameraAction.swift @@ -1,14 +1,6 @@ -// -// VCamResetCameraAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/03. -// - import Foundation import VCamEntity import VCamBridge -import VCamLocalization import struct SwiftUI.Image public struct VCamResetCameraAction: VCamAction { @@ -17,7 +9,7 @@ public struct VCamResetCameraAction: VCamAction { } public var configuration: VCamResetCameraActionConfiguration - public var name: String { L10n.resetModelPosition.text } + public var name: String { String(localized: .resetModelPosition) } public var icon: Image { Image(systemName: "arrow.triangle.2.circlepath.camera.fill") } @MainActor diff --git a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamWaitAction.swift b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamWaitAction.swift index d17ea15..972a16c 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/Action/VCamWaitAction.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/Action/VCamWaitAction.swift @@ -1,13 +1,5 @@ -// -// VCamWaitAction.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import Foundation import VCamEntity -import VCamLocalization import struct SwiftUI.Image public struct VCamWaitAction: VCamAction { @@ -16,7 +8,7 @@ public struct VCamWaitAction: VCamAction { } public var configuration: VCamWaitActionConfiguration - public var name: String { L10n.wait.text } + public var name: String { String(localized: .wait) } public var icon: Image { Image(systemName: "timer") } @MainActor diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorCodeEditor.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorCodeEditor.swift index 943de1c..0232ecf 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorCodeEditor.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorCodeEditor.swift @@ -16,10 +16,10 @@ struct VCamActionEditorCodeEditor: View { VStack { HStack { FlatButton(action: openScript) { - Text(L10n.openFile.key, bundle: .localize) + Text(.openFile) } FlatButton(action: loadScript) { - Text(L10n.reload.key, bundle: .localize) + Text(.reload) } } .font(.caption2) diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorDurationField.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorDurationField.swift index 2cc3401..0ff9886 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorDurationField.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorDurationField.swift @@ -1,10 +1,3 @@ -// -// VCamActionEditorDurationField.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import SwiftUI struct VCamActionEditorDurationField: View { @@ -12,10 +5,10 @@ struct VCamActionEditorDurationField: View { var body: some View { HStack(spacing: 4) { - TextField("", value: $value, format: .number) + TextField(value: $value, format: .number) { EmptyView() } .textFieldStyle(.roundedBorder) .multilineTextAlignment(.center) - Text(L10n.seconds.key, bundle: .localize) + Text(.seconds) } .frame(width: 80) } diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorPicker.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorPicker.swift index 91fe7df..023190e 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorPicker.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorPicker.swift @@ -1,21 +1,15 @@ -// -// VCamActionEditorPicker.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import SwiftUI -struct VCamActionEditorPicker: View { +struct VCamActionEditorPicker: View { @Binding var item: Item let items: [Candidate] let mapValue: (Candidate) -> Item + let displayName: (Candidate) -> String var body: some View { Picker(selection: $item) { ForEach(items.map(PickerItem.init)) { item in - Text(item.value.description) + Text(verbatim: displayName(item.value)) .tag(mapValue(item.value)) } } label: { @@ -25,10 +19,11 @@ struct VCamActionEditorPicker, items: [Candidate]) { + init(item: Binding, items: [Candidate], displayName: @escaping (Candidate) -> String) { self._item = item self.items = items mapValue = { $0 } + self.displayName = displayName } } @@ -39,6 +34,6 @@ private struct PickerItem: Identifiable { struct VCamActionEditorPicker_Previews: PreviewProvider { static var previews: some View { - VCamActionEditorPicker(item: .constant(""), items: ["hello"]) + VCamActionEditorPicker(item: .constant(""), items: ["hello"], displayName: { $0 }) } } diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorTextField.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorTextField.swift index 195c0bc..b8644da 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorTextField.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamActionEditorTextField.swift @@ -1,17 +1,10 @@ -// -// VCamActionEditorTextField.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/16. -// - import SwiftUI struct VCamActionEditorTextField: View { @Binding var value: String var body: some View { - TextField("", text: $value) + TextField(text: $value) { EmptyView() } .textFieldStyle(.roundedBorder) } } diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcut+View.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcut+View.swift index b15d6be..e3a5b46 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcut+View.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcut+View.swift @@ -1,10 +1,3 @@ -// -// VCamShortcut+View.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/02. -// - import Foundation import VCamEntity import SwiftUI @@ -22,7 +15,9 @@ public extension View { @ViewBuilder func keyboardShortcut(_ shortcutKey: VCamShortcut.ShortcutKey?, action: @escaping () -> Void) -> some View { if let shortcutKey { // Workaround to make shortcut keys work on any button - let hiddenButton = Button("", action: action) + let hiddenButton = Button(action: action) { + EmptyView() + } .frame(width: 0, height: 0) .opacity(0) .allowsHitTesting(false) diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutBuilderView.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutBuilderView.swift index bc224f8..49a1ec4 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutBuilderView.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutBuilderView.swift @@ -1,6 +1,5 @@ import SwiftUI import VCamEntity -import VCamLocalization import VCamBridge import VCamData @@ -18,7 +17,7 @@ public struct VCamShortcutBuilderView: View { List { HStack(spacing: 0) { TextField(text: $shortcut.title) { - Text(L10n.title.key, bundle: .localize) + Text(.title) } .textFieldStyle(.roundedBorder) @@ -52,7 +51,7 @@ public struct VCamShortcutBuilderView: View { .frame(minWidth: 280) VStack(spacing: 0) { - Text(L10n.action.key, bundle: .localize) + Text(.action) .bold() .padding() List(allActions, id: \.id) { action in @@ -144,15 +143,15 @@ struct VCamShortcutBuilderActionItemEditView: View { case let .message(configuration): VCamActionEditorTextField(value: .init(configuration, keyPath: \.message, to: $configuration)) case let .motion(configuration): - VCamActionEditorPicker(item: .init(configuration, keyPath: \.motion, to: $configuration), items: VCamAvatarMotion.allCases) + VCamActionEditorPicker(item: .init(configuration, keyPath: \.motion, to: $configuration), items: VCamAvatarMotion.allCases, displayName: \.description) case let .blendShape(configuration): - VCamActionEditorPicker(item: .init(configuration, keyPath: \.blendShape, to: $configuration), items: UniState.shared.expressions.map(\.name)) + VCamActionEditorPicker(item: .init(configuration, keyPath: \.blendShape, to: $configuration), items: UniState.shared.expressions.map(\.name), displayName: { $0 }) case let .wait(configuration): VCamActionEditorDurationField(value: .init(configuration, keyPath: \.duration, to: $configuration)) case .resetCamera: EmptyView() case let .loadScene(configuration): - VCamActionEditorPicker(item: .init(configuration, keyPath: \.sceneId, to: $configuration), items: SceneManager.shared.scenes, mapValue: \.id) + VCamActionEditorPicker(item: .init(configuration, keyPath: \.sceneId, to: $configuration), items: SceneManager.shared.scenes, mapValue: \.id, displayName: \.localizedDisplayName) case let .appleScript(configuration): VCamActionEditorCodeEditor(id: shortcut.id, actionId: configuration.id, name: VCamAppleScriptAction.scriptName) } @@ -182,7 +181,7 @@ private final class KeyPathBox: @unchecked Sendable { extension VCamShortcutBuilderView: MacWindow { public var windowTitle: String { - L10n.createShortcut.text + String(localized: .createShortcut) } public func configureWindow(_ window: NSWindow) -> NSWindow { diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutGridView.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutGridView.swift index 45692a1..3b17fc5 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutGridView.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutGridView.swift @@ -1,10 +1,3 @@ -// -// VCamShortcutGridView.swift -// -// -// Created by Tatsuya Tanaka on 2023/09/21. -// - import SwiftUI import VCamEntity import VCamLogger @@ -52,7 +45,7 @@ public struct VCamShortcutGridView: View { shortcut.icon Group { if shortcut.title.isEmpty { - Text(L10n.notitle.key, bundle: .localize) + Text(.notitle) } else { Text(shortcut.title) } @@ -73,14 +66,14 @@ public struct VCamShortcutGridView: View { editShortcut($shortcut) } label: { Image(systemName: "pencil") - Text(L10n.edit.key, bundle: .localize) + Text(.edit) } Divider() Button { VCamShortcutManager.shared.remove(shortcut) } label: { Image(systemName: "trash") - Text(L10n.delete.key, bundle: .localize) + Text(.delete) } } .onDragMove(item: shortcut, items: $shortcutManager.shortcuts, dragging: $dragging, onMove: shortcutManager.move) diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutKeyField.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutKeyField.swift index da22844..130d058 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutKeyField.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutKeyField.swift @@ -1,10 +1,3 @@ -// -// VCamShortcutKeyField.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/16. -// - import SwiftUI import VCamEntity @@ -26,7 +19,7 @@ struct VCamShortcutKeyField: View { Button { isKeyRecordingPresented = true } label: { - TextField("", text: .constant(keyWithPadding), prompt: Text(L10n.shortcutKey.key, bundle: .localize) + Text(" ")) + TextField(text: .constant(keyWithPadding), prompt: Text(.shortcutKey) + Text(verbatim: " ")) { EmptyView() } .textFieldStyle(.roundedBorder) .multilineTextAlignment(.leading) .allowsHitTesting(false) diff --git a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutManager.swift b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutManager.swift index 8dafa5a..6abd272 100644 --- a/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutManager.swift +++ b/app/xcode/Sources/VCamUI/Shortcut/VCamShortcutManager.swift @@ -69,6 +69,6 @@ public final class VCamShortcutManager { } private func showError(_ error: any Error) { - MacWindowManager.shared.open(VCamAlert(windowTitle: L10n.failure.text, message: error.localizedDescription, canCancel: false, okTitle: "OK", onOK: {}, onCancel: {})) + MacWindowManager.shared.open(VCamAlert(windowTitle: String(localized: .failure), message: error.localizedDescription, canCancel: false, okTitle: "OK", onOK: {}, onCancel: {})) } } diff --git a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbar.swift b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbar.swift index d4e7c7e..1e3cb45 100644 --- a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbar.swift +++ b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbar.swift @@ -1,10 +1,3 @@ -// -// VCamMainToolbar.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/12. -// - import SwiftUI import VCamEntity import VCamData @@ -18,7 +11,6 @@ public struct VCamMainToolbar: View { @State private var isBlendShapePickerPopover = false @Environment(UniState.self) var uniState - @Environment(\.locale) var locale @OpenEmojiPicker var openEmojiPicker public var body: some View { @@ -29,22 +21,20 @@ public struct VCamMainToolbar: View { Image(systemName: "paintpalette.fill") } .popover(isPresented: $isPhotoPopover) { - VCamPopoverContainer(L10n.background.key) { + VCamPopoverContainer(.background) { VCamMainToolbarBackgroundColorPicker() } - .environment(\.locale, locale) } Item { isEmojiPickerPopover.toggle() } label: { - Text("👍") + Text(verbatim: "👍") } .popover(isPresented: $isEmojiPickerPopover) { - VCamPopoverContainer(L10n.emoji.key) { + VCamPopoverContainer(.emoji) { VCamMainToolbarEmojiPicker() } - .environment(\.locale, locale) .frame(width: 240) } @@ -54,10 +44,9 @@ public struct VCamMainToolbar: View { Image(systemName: "figure.wave") } .popover(isPresented: $isMotionPickerPopover) { - VCamPopoverContainerWithWindow(L10n.motion.key) { + VCamPopoverContainerWithWindow(.motion) { VCamMainToolbarMotionPicker() } - .environment(\.locale, locale) .frame(width: 240) } @@ -67,10 +56,9 @@ public struct VCamMainToolbar: View { Image(systemName: "face.smiling") } .popover(isPresented: $isBlendShapePickerPopover) { - VCamPopoverContainerWithWindow(L10n.facialExpression.key) { + VCamPopoverContainerWithWindow(.facialExpression) { VCamMainToolbarExpressionPicker() } - .environment(\.locale, locale) .frame(width: 280, height: 150) } .disabled(uniState.expressions.isEmpty) diff --git a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarBackgroundColorPicker.swift b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarBackgroundColorPicker.swift index 0c80f5e..98f19bf 100644 --- a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarBackgroundColorPicker.swift +++ b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarBackgroundColorPicker.swift @@ -1,10 +1,3 @@ -// -// VCamMainToolbarBackgroundColorPicker.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/12. -// - import SwiftUI import VCamUIFoundation import VCamData @@ -20,9 +13,9 @@ public struct VCamMainToolbarBackgroundColorPicker: View { GroupBox { Form { HStack { - Text(L10n.color.key, bundle: .localize) + Text(.color) .fixedSize(horizontal: true, vertical: false) - ColorEditField(L10n.color.key, value: $state.backgroundColor) + ColorEditField(.color, value: $state.backgroundColor) .labelsHidden() } } diff --git a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarExpressionPicker.swift b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarExpressionPicker.swift index 19c3ee5..28aad59 100644 --- a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarExpressionPicker.swift +++ b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarExpressionPicker.swift @@ -1,10 +1,3 @@ -// -// VCamMainToolbarBlendShapePicker.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/12. -// - import SwiftUI import VCamBridge import VCamEntity @@ -24,7 +17,7 @@ public struct VCamMainToolbarExpressionPicker: View { isSelected: uniState.currentExpressionIndex == index) { UniBridge.applyExpression(name: expression.name) } label: { - Text(.init(expression.name), bundle: .localize) + Text(expression.name) } } } @@ -42,7 +35,7 @@ public struct VCamMainToolbarExpressionPicker: View { extension VCamMainToolbarExpressionPicker: MacWindow { public var windowTitle: String { - L10n.facialExpression.text + String(localized: .facialExpression) } public func configureWindow(_ window: NSWindow) -> NSWindow { diff --git a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarMotionPicker.swift b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarMotionPicker.swift index 3ca37d1..1094512 100644 --- a/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarMotionPicker.swift +++ b/app/xcode/Sources/VCamUI/Toolbar/VCamMainToolbarMotionPicker.swift @@ -1,10 +1,3 @@ -// -// VCamMainToolbarMotionPicker.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/12. -// - import SwiftUI import VCamBridge import VCamData @@ -39,7 +32,7 @@ public struct VCamMainToolbarMotionPicker: View { } } ) { - Text(.init(motion.name), bundle: .localize) + Text(motion.name) } #if !FEATURE_3 @@ -69,7 +62,7 @@ public struct VCamMainToolbarMotionPicker: View { extension VCamMainToolbarMotionPicker: MacWindow { public var windowTitle: String { - L10n.motion.text + String(localized: .motion) } public func configureWindow(_ window: NSWindow) -> NSWindow { diff --git a/app/xcode/Sources/VCamUI/TrackingDeviceView.swift b/app/xcode/Sources/VCamUI/TrackingDeviceView.swift index f35125c..14332c2 100644 --- a/app/xcode/Sources/VCamUI/TrackingDeviceView.swift +++ b/app/xcode/Sources/VCamUI/TrackingDeviceView.swift @@ -36,13 +36,13 @@ public struct TrackingDeviceView: View { Text(device.localizedName).tag(device) } } label: { - Text(L10n.camera.key, bundle: .localize) + Text(.camera) } } else { Picker(selection: .constant(0)) { - Text(L10n.isNotFound(L10n.camera.text).key, bundle: .localize).tag(0) + Text(.isNotFound(String(localized: .camera))).tag(0) } label: { - Text(L10n.camera.key, bundle: .localize) + Text(.camera) } } if let firstDevice = AudioDevice.devices().first { @@ -57,13 +57,13 @@ public struct TrackingDeviceView: View { Text(device.name()).tag(device) } } label: { - Text(L10n.mic.key, bundle: .localize) + Text(.mic) } } else { Picker(selection: .constant(0)) { - Text(L10n.isNotFound(L10n.mic.text).key, bundle: .localize).tag(0) + Text(.isNotFound(String(localized: .mic))).tag(0) } label: { - Text(L10n.mic.key, bundle: .localize) + Text(.mic) } } Picker(selection: Binding( @@ -74,10 +74,10 @@ public struct TrackingDeviceView: View { } )) { ForEach(LipSyncType.allCases) { type in - Text(type.name, bundle: .localize).tag(type) + Text(type.name).tag(type) } } label: { - Text(L10n.lipSync.key, bundle: .localize) + Text(.lipSync) } .disabled(Tracking.shared.micLipSyncDisabled) .onReceive(NotificationCenter.default.publisher(for: .deviceWasChanged)) { _ in diff --git a/app/xcode/Sources/VCamUI/UIComponent/ColorEditField.swift b/app/xcode/Sources/VCamUI/UIComponent/ColorEditField.swift index 1c6ca21..654b501 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/ColorEditField.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/ColorEditField.swift @@ -1,18 +1,17 @@ import SwiftUI -import VCamLocalization public struct ColorEditField: View { - public init(_ label: LocalizedStringKey, value: Binding) { + public init(_ label: LocalizedStringResource, value: Binding) { self.label = label self._value = value } - let label: LocalizedStringKey + let label: LocalizedStringResource @Binding var value: Color public var body: some View { ColorPicker(selection: $value) { - Text(label, bundle: .localize).bold() + Text(label).bold() .lineLimit(1) .modifier { view in if #available(macOS 26.0, *) { diff --git a/app/xcode/Sources/VCamUI/UIComponent/FlatButton.swift b/app/xcode/Sources/VCamUI/UIComponent/FlatButton.swift index 0abfa2b..2e09938 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/FlatButton.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/FlatButton.swift @@ -1,10 +1,3 @@ -// -// FlatButton.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/01. -// - import SwiftUI public struct FlatButton: View { @@ -88,13 +81,13 @@ struct FlatButton_Previews: PreviewProvider { static var previews: some View { FlatButton { } label: { - Text("Hello") + Text(verbatim: "Hello") } .padding() FlatButton { } label: { - Text("Hello") + Text(verbatim: "Hello") } .flatButtonStyle(.filled()) .padding() diff --git a/app/xcode/Sources/VCamUI/UIComponent/KeyRecordingPopoverView.swift b/app/xcode/Sources/VCamUI/UIComponent/KeyRecordingPopoverView.swift index df03264..d881333 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/KeyRecordingPopoverView.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/KeyRecordingPopoverView.swift @@ -1,10 +1,3 @@ -// -// KeyRecordingPopoverView.swift -// -// -// Created by Tatsuya Tanaka on 2023/04/15. -// - import SwiftUI import VCamEntity @@ -35,11 +28,11 @@ public struct KeyRecordingPopoverView: View { @Environment(\.dismiss) var dismiss - var helpMessage: LocalizedStringKey? { + var helpMessage: LocalizedStringResource? { if keys.key.isEmpty { - return L10n.recordingShortcutKey.key + return .recordingShortcutKey } else if isError { - return L10n.recordingShortcutKeyError.key + return .recordingShortcutKeyError } return nil } @@ -49,7 +42,7 @@ public struct KeyRecordingPopoverView: View { keyView if let helpMessage { - Text(helpMessage, bundle: .localize) + Text(helpMessage) .fixedSize() .foregroundStyle(isError ? .red : .init(.labelColor)) } diff --git a/app/xcode/Sources/VCamUI/UIComponent/MinMaxSlider.swift b/app/xcode/Sources/VCamUI/UIComponent/MinMaxSlider.swift index 496bd03..b453455 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/MinMaxSlider.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/MinMaxSlider.swift @@ -1,10 +1,3 @@ -// -// MinMaxSlider.swift -// -// -// Created by tattn on 2023/02/04. -// - import SwiftUI struct SliderBar: View { @@ -117,11 +110,11 @@ public struct MinMaxSlider: View { public init( - cancelTitle: String = L10n.cancel.text, + cancelTitle: String? = nil, doneTitle: String, doneDisabled: Bool = false, cancel: (() -> Void)? = nil, done: @escaping () -> Void, content: @escaping () -> Content ) { - self.cancelTitle = cancelTitle + self.cancelTitle = cancelTitle ?? String(localized: .cancel) self.doneTitle = doneTitle self.doneDisabled = doneDisabled self.cancel = cancel @@ -26,15 +18,13 @@ public struct ModalSheet: View { self.content = content } - var cancelTitle = L10n.cancel.text + var cancelTitle = String(localized: .cancel) let doneTitle: String var doneDisabled = false let cancel: (() -> Void)? let done: () -> Void @ViewBuilder let content: () -> Content - @AppStorage(key: .locale) var locale - public var body: some View { VStack { content() @@ -56,6 +46,5 @@ public struct ModalSheet: View { } .padding() } - .environment(\.locale, locale.isEmpty ? .current : Locale(identifier: locale)) } } diff --git a/app/xcode/Sources/VCamUI/UIComponent/TextFieldListRow.swift b/app/xcode/Sources/VCamUI/UIComponent/TextFieldListRow.swift index 4b8491c..007d3eb 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/TextFieldListRow.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/TextFieldListRow.swift @@ -1,17 +1,11 @@ -// -// TextFieldListRow.swift -// -// -// Created by Tatsuya Tanaka on 2022/05/07. -// - import Foundation import SwiftUI public struct TextFieldListRow: View { - public init(id: ID, text: Binding, editingId: Binding, selectedId: ID?, onCommit: @escaping () -> Void) { + public init(id: ID, text: Binding, placeholder: String, editingId: Binding, selectedId: ID?, onCommit: @escaping () -> Void) { self.id = id self._text = text + self.placeholder = placeholder self._editingId = editingId self.selectedId = selectedId self.onCommit = onCommit @@ -19,6 +13,7 @@ public struct TextFieldListRow: View { let id: ID @Binding var text: String + let placeholder: String @Binding var editingId: ID? let selectedId: ID? let onCommit: () -> Void @@ -28,7 +23,10 @@ public struct TextFieldListRow: View { public var body: some View { HStack { if editingId == id { - TextField("", text: $text) { + TextField(text: $text) { + Text(verbatim: placeholder) + } + .onSubmit { editingId = nil onCommit() } @@ -38,13 +36,13 @@ public struct TextFieldListRow: View { isFocused = true } } else if selectedId == id { - Text(text) + Text(verbatim: text.isEmpty ? placeholder : text) .font(.subheadline) .onTapGestureWithKeyboardShortcut(.defaultAction) { editingId = id } } else { - Text(text) + Text(verbatim: text.isEmpty ? placeholder : text) .font(.subheadline) } } diff --git a/app/xcode/Sources/VCamUI/UIComponent/ToggleButton.swift b/app/xcode/Sources/VCamUI/UIComponent/ToggleButton.swift index 62cd749..5578294 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/ToggleButton.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/ToggleButton.swift @@ -1,16 +1,9 @@ -// -// ToggleButton.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/11. -// - import SwiftUI import Combine public struct ToggleButton: View { - public init(_ title: LocalizedStringKey, isOn: Binding) { - self.text = Text(title, bundle: .localize) + public init(_ title: LocalizedStringResource, isOn: Binding) { + self.text = Text(title) self._isOn = isOn } diff --git a/app/xcode/Sources/VCamUI/UIComponent/VCamAlert.swift b/app/xcode/Sources/VCamUI/UIComponent/VCamAlert.swift index 99e4aaa..310a39a 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/VCamAlert.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/VCamAlert.swift @@ -1,10 +1,3 @@ -// -// VCamAlert.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/22. -// - import SwiftUI public struct VCamAlert: View { @@ -58,7 +51,7 @@ public struct VCamAlert: View { if canCancel { Button(action: cancel) { - Text(L10n.cancel.text) + Text(.cancel) .padding(.vertical, 10) .frame(maxWidth: .infinity) .contentShape(Rectangle()) diff --git a/app/xcode/Sources/VCamUI/UIComponent/VCamPopoverContainer.swift b/app/xcode/Sources/VCamUI/UIComponent/VCamPopoverContainer.swift index 45e3ac4..bedca22 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/VCamPopoverContainer.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/VCamPopoverContainer.swift @@ -1,24 +1,17 @@ -// -// VCamPopoverContainer.swift -// -// -// Created by Tatsuya Tanaka on 2023/02/14. -// - import SwiftUI public struct VCamPopoverContainer: View { - public init(_ title: LocalizedStringKey, @ViewBuilder content: @escaping () -> Content) { + public init(_ title: LocalizedStringResource, @ViewBuilder content: @escaping () -> Content) { self.title = title self.content = content } - let title: LocalizedStringKey + let title: LocalizedStringResource let content: () -> Content public var body: some View { VStack(spacing: 1) { - Text(title, bundle: .localize) + Text(title) .font(.caption) content() @@ -29,19 +22,19 @@ public struct VCamPopoverContainer: View { } public struct VCamPopoverContainerWithButton: View { - public init(_ title: LocalizedStringKey, @ViewBuilder button: @escaping () -> ButtonContent, @ViewBuilder content: @escaping () -> Content) { + public init(_ title: LocalizedStringResource, @ViewBuilder button: @escaping () -> ButtonContent, @ViewBuilder content: @escaping () -> Content) { self.title = title self.button = button self.content = content } - let title: LocalizedStringKey + let title: LocalizedStringResource let button: () -> ButtonContent let content: () -> Content public var body: some View { VStack(spacing: 1) { - Text(title, bundle: .localize) + Text(title) .font(.caption) .frame(maxWidth: .infinity) .background(alignment: .topTrailing) { @@ -59,12 +52,12 @@ public struct VCamPopoverContainerWithButton public struct VCamPopoverContainerWithWindow: View { - public init(_ title: LocalizedStringKey, @ViewBuilder content: @escaping () -> Content) { + public init(_ title: LocalizedStringResource, @ViewBuilder content: @escaping () -> Content) { self.title = title self.content = content } - let title: LocalizedStringKey + let title: LocalizedStringResource let content: () -> Content public var body: some View { @@ -83,7 +76,7 @@ public struct VCamPopoverContainerWithWindow: View { struct VCamMainToolbarContainer_Previews: PreviewProvider { static var previews: some View { VCamPopoverContainer("hello") { - Text("world") + Text(verbatim: "world") } } } diff --git a/app/xcode/Sources/VCamUI/UIComponent/VCamSection.swift b/app/xcode/Sources/VCamUI/UIComponent/VCamSection.swift index 8e39f36..61b59c1 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/VCamSection.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/VCamSection.swift @@ -1,19 +1,12 @@ -// -// VCamSection.swift -// -// -// Created by Tatsuya Tanaka on 2022/04/23. -// - import SwiftUI public struct VCamSection: View { - public init(_ title: LocalizedStringKey, @ViewBuilder content: () -> Content) { + public init(_ title: LocalizedStringResource, @ViewBuilder content: () -> Content) { self.title = title self.content = content() } - let title: LocalizedStringKey + let title: LocalizedStringResource let content: Content @State private var isExpanded = false @@ -25,7 +18,7 @@ public struct VCamSection: View { .padding(.top, 8) .padding(.leading) } label: { - Text(title, bundle: .localize) + Text(title) .bold() .contentShape(Rectangle()) .onTapGesture { diff --git a/app/xcode/Sources/VCamUI/UIComponent/ValueEditField.swift b/app/xcode/Sources/VCamUI/UIComponent/ValueEditField.swift index 5c75bce..7e9290d 100644 --- a/app/xcode/Sources/VCamUI/UIComponent/ValueEditField.swift +++ b/app/xcode/Sources/VCamUI/UIComponent/ValueEditField.swift @@ -1,15 +1,8 @@ -// -// ValueEditField.swift -// -// -// Created by Tatsuya Tanaka on 2022/02/22. -// - import SwiftUI public struct ValueEditField: View { public init( - _ label: LocalizedStringKey, + _ label: LocalizedStringResource, value: Binding, type: EditType, @ViewBuilder valueLabel: @escaping (CGFloat) -> ValueLabel @@ -20,7 +13,7 @@ public struct ValueEditField: View { self.valueLabel = valueLabel } - let label: LocalizedStringKey + let label: LocalizedStringResource @Binding var value: CGFloat let type: EditType let valueLabel: (CGFloat) -> ValueLabel @@ -28,7 +21,7 @@ public struct ValueEditField: View { public var body: some View { HStack(spacing: 2) { HStack(spacing: 4) { - Text(label, bundle: .localize) + Text(label) valueLabel(value) .lineLimit(1) .font(.caption2) @@ -41,7 +34,7 @@ public struct ValueEditField: View { case let .slider(range, onEditingChanged): Slider(value: $value, in: range, onEditingChanged: onEditingChanged) case .stepper: - TextField("", value: $value, formatter: NumberFormatter()) + TextField(value: $value, formatter: NumberFormatter()) { EmptyView() } .textFieldStyle(.roundedBorder) } } @@ -63,7 +56,7 @@ public struct ValueEditField: View { extension ValueEditField where ValueLabel == Text { public init( - _ label: LocalizedStringKey, + _ label: LocalizedStringResource, value: Binding, type: EditType, format: F @@ -75,7 +68,7 @@ extension ValueEditField where ValueLabel == Text { } public init( - _ label: LocalizedStringKey, + _ label: LocalizedStringResource, value: Binding, type: EditType, precision: FloatingPointFormatStyle.Configuration.Precision = .fractionLength(1) @@ -89,7 +82,7 @@ extension ValueEditField where ValueLabel == Text { extension ValueEditField where ValueLabel == EmptyView { static func emptyValueLabel( - _ label: LocalizedStringKey, + _ label: LocalizedStringResource, value: Binding, type: EditType ) -> Self { diff --git a/app/xcode/Sources/VCamUI/VCamDisplayView.swift b/app/xcode/Sources/VCamUI/VCamDisplayView.swift index fe28fe9..433ea4e 100644 --- a/app/xcode/Sources/VCamUI/VCamDisplayView.swift +++ b/app/xcode/Sources/VCamUI/VCamDisplayView.swift @@ -29,28 +29,28 @@ public struct VCamDisplayView: View { HStack { GroupBox { Toggle(isOn: $state.usePostEffect) { - Text(L10n.enable.key, bundle: .localize) + Text(.enable) } } GroupBox { HStack { Picker(selection: $state.currentDisplayParameterPreset) { ForEach(presetItems) { item in - Text(item.description) + Text(verbatim: item.description.isEmpty ? String(localized: .newPreset) : item.description) .frame(minWidth: 120, alignment: .leading) .tag(item) } } label: { - Text(L10n.preset.key, bundle: .localize) + Text(.preset) } TextField(text: $state.currentDisplayParameterPreset.description) { - Text(L10n.newPreset.key, bundle: .localize) + Text(.newPreset) } .frame(minWidth: 120) Button { uniState.displayParameters.saveCurrentParameter() } label: { - Text(L10n.save.key, bundle: .localize) + Text(.save) } Button { uniState.displayParameters.addParameter() @@ -90,48 +90,49 @@ private struct VCamDisplayParameterView: View { HStack { VStack(alignment: .leading) { Form { - ValueEditField(L10n.ambientLightIntensity.key, value: $state.light, type: .slider(0...2)) - ColorEditField(L10n.ambientLightColor.key, value: $state.environmentLightColor) - ValueEditField(L10n.cameraExposure.key, value: $state.postExposure, type: .slider(-2...6)) - ColorEditField(L10n.colorFilter.key, value: $state.colorFilter) - ValueEditField(L10n.saturation.key, value: $state.saturation, type: .slider(-100...100), precision: .fractionLength(0)) - ValueEditField(L10n.hueShift.key, value: $state.hueShift, type: .slider(-180...180), precision: .fractionLength(0)) - ValueEditField(L10n.contrast.key, value: $state.contrast, type: .slider(-100...100), precision: .fractionLength(0)) + ValueEditField(.ambientLightIntensity, value: $state.light, type: .slider(0...2)) + ColorEditField(.ambientLightColor, value: $state.environmentLightColor) + ValueEditField(.cameraExposure, value: $state.postExposure, type: .slider(-2...6)) + ColorEditField(.colorFilter, value: $state.colorFilter) + ValueEditField(.saturation, value: $state.saturation, type: .slider(-100...100), precision: .fractionLength(0)) + ValueEditField(.hueShift, value: $state.hueShift, type: .slider(-180...180), precision: .fractionLength(0)) + ValueEditField(.contrast, value: $state.contrast, type: .slider(-100...100), precision: .fractionLength(0)) Spacer() } } VStack(alignment: .leading) { - VCamSection(L10n.whiteBalance.key) { + VCamSection(.whiteBalance) { Form { - ValueEditField(L10n.colorTemperature.key, value: $state.whiteBalanceTemperature, type: .slider(-100...100), precision: .fractionLength(0)) - ValueEditField(L10n.tint.key, value: $state.whiteBalanceTint, type: .slider(-100...100), precision: .fractionLength(0)) + ValueEditField(.colorTemperature, value: $state.whiteBalanceTemperature, type: .slider(-100...100), precision: .fractionLength(0)) + ValueEditField(.tint, value: $state.whiteBalanceTint, type: .slider(-100...100), precision: .fractionLength(0)) } } - VCamSection(L10n.bloom.key) { + .accessibilityIdentifier("display.whiteBalance") + VCamSection(.bloom) { Form { - ValueEditField(L10n.intensity.key, value: $state.bloomIntensity, type: .slider(0...60)) - ValueEditField(L10n.thresholdScreenEffect.key, value: $state.bloomThreshold, type: .slider(0...2)) - ValueEditField(L10n.softKnee.key, value: $state.bloomSoftKnee, type: .slider(0...1)) - ValueEditField(L10n.diffusion.key, value: $state.bloomDiffusion, type: .slider(1...10)) - ValueEditField(L10n.anamorphicRatio.key, value: $state.bloomAnamorphicRatio, type: .slider(-1...1)) - ColorEditField(L10n.color.key, value: $state.bloomColor) + ValueEditField(.intensity, value: $state.bloomIntensity, type: .slider(0...60)) + ValueEditField(.thresholdScreenEffect, value: $state.bloomThreshold, type: .slider(0...2)) + ValueEditField(.softKnee, value: $state.bloomSoftKnee, type: .slider(0...1)) + ValueEditField(.diffusion, value: $state.bloomDiffusion, type: .slider(1...10)) + ValueEditField(.anamorphicRatio, value: $state.bloomAnamorphicRatio, type: .slider(-1...1)) + ColorEditField(.color, value: $state.bloomColor) Picker(selection: $state.lensFlare.map(get: LensFlare.initOrNone, set: { $0.rawValue })) { ForEach(LensFlare.allCases) { item in - Text(item.description) + Text(item.localizedName) .tag(item) } } label: { - Text(L10n.lensFlare.key, bundle: .localize) + Text(.lensFlare) } - ValueEditField(L10n.lensFlareIntensity.key, value: $state.bloomLensFlareIntensity, type: .slider(0...50)) + ValueEditField(.lensFlareIntensity, value: $state.bloomLensFlareIntensity, type: .slider(0...50)) } } - VCamSection(L10n.vignette.key) { + VCamSection(.vignette) { Form { - ValueEditField(L10n.intensity.key, value: $state.vignetteIntensity, type: .slider(0...1)) - ColorEditField(L10n.color.key, value: $state.vignetteColor) - ValueEditField(L10n.smoothness.key, value: $state.vignetteSmoothness, type: .slider(0...1)) - ValueEditField(L10n.roundness.key, value: $state.vignetteRoundness, type: .slider(0...1)) + ValueEditField(.intensity, value: $state.vignetteIntensity, type: .slider(0...1)) + ColorEditField(.color, value: $state.vignetteColor) + ValueEditField(.smoothness, value: $state.vignetteSmoothness, type: .slider(0...1)) + ValueEditField(.roundness, value: $state.vignetteRoundness, type: .slider(0...1)) } } Spacer() @@ -148,7 +149,6 @@ private struct VCamDisplayParameterView: View { #Preview { VCamDisplayView() - .environment(\.locale, Locale(identifier: "ja")) .environment(UniState.preview()) } diff --git a/app/xcode/Sources/VCamUI/VCamMainObjectListView.swift b/app/xcode/Sources/VCamUI/VCamMainObjectListView.swift index 84cc32c..e239a9d 100644 --- a/app/xcode/Sources/VCamUI/VCamMainObjectListView.swift +++ b/app/xcode/Sources/VCamUI/VCamMainObjectListView.swift @@ -29,6 +29,7 @@ public struct VCamMainObjectListView: View { // Do not use `$object.name` now object.name = $0 }), + placeholder: object.type.localizedName, editingId: $editingId, selectedId: selectedId ) { @@ -53,7 +54,7 @@ public struct VCamMainObjectListView: View { VCamMainObjectListBottomBar(selectedId: selectedId) } label: { - Text(L10n.object.key, bundle: .localize) + Text(.object) } .onReceive(NotificationCenter.default.publisher(for: .unfocusObject)) { _ in selectedIdBinding.wrappedValue = nil @@ -72,7 +73,7 @@ private struct VCamMainObjectListAddButton: View { objectManager.addImage(url: url) } label: { Image(systemName: "photo") - Text(L10n.clipboard.key, bundle: .localize) + Text(.clipboard) } } Button { @@ -81,7 +82,7 @@ private struct VCamMainObjectListAddButton: View { } } label: { Image(systemName: "photo") - Text(L10n.image.key, bundle: .localize) + Text(.image) } Button { showScreenRecorderPreferenceView { recorder in @@ -91,7 +92,7 @@ private struct VCamMainObjectListAddButton: View { } } label: { Image(systemName: "display") - Text(L10n.screen.key, bundle: .localize) + Text(.screen) } Button { CaptureDeviceRenderer.selectDevice { drawer in @@ -100,13 +101,13 @@ private struct VCamMainObjectListAddButton: View { } } label: { Image(systemName: "camera") - Text(L10n.videoCaptureDevice.key, bundle: .localize) + Text(.videoCaptureDevice) } Button { WebRenderer.showPreferencesForAdding() } label: { Image(systemName: "network") - Text(L10n.web.key, bundle: .localize) + Text(.web) } #if FEATURE_3 @@ -116,7 +117,7 @@ private struct VCamMainObjectListAddButton: View { objectManager.add(.init(type: .wind(), isHidden: false, isLocked: false)) } label: { Image(systemName: "wind") - Text(L10n.wind.key, bundle: .localize) + Text(.wind) } #endif } label: { @@ -185,7 +186,7 @@ private struct VCamMainObjectListBottomBar: View { } private struct EditSceneObjectButton: View { - var key = L10n.edit.key + var key: LocalizedStringResource = .edit let isLocked: Bool let action: () -> Void var body: some View { @@ -193,7 +194,7 @@ private struct EditSceneObjectButton: View { action() } label: { Image(systemName: "pencil") - Text(key, bundle: .localize) + Text(key) } .disabled(isLocked) } @@ -214,7 +215,7 @@ private struct FilterSceneObjectButton: View { } } label: { Image(systemName: "wand.and.stars") - Text(L10n.filter.key, bundle: .localize) + Text(.filter) } .disabled(object.isLocked) } @@ -228,7 +229,7 @@ private struct DeleteSceneObjectButton: View { SceneObjectManager.shared.remove(byId: object.id) } label: { Image(systemName: "trash") - Text(L10n.delete.key, bundle: .localize) + Text(.delete) } .disabled(object.isLocked) } @@ -245,7 +246,7 @@ private struct HideSceneObjectButton: View { } label: { Image(systemName: "eye") .symbolVariant(object.isHidden ? .none : .slash) - Text(object.isHidden ? L10n.show.key : L10n.hide.key, bundle: .localize) + Text(object.isHidden ? .show : .hide) } } } @@ -261,7 +262,7 @@ private struct LockSceneObjectButton: View { } label: { Image(systemName: "lock") .symbolVariant(object.isLocked ? .slash : .none) - Text(object.isLocked ? L10n.unlock.key : L10n.lock.key, bundle: .localize) + Text(object.isLocked ? .unlock : .lock) } } } @@ -286,7 +287,7 @@ private struct EditSceneObjectViewModifier: ViewModifier { UniBridge.shared.resetCamera() } label: { Image(systemName: "arrow.uturn.backward") - Text(L10n.moveInitialPosition.key, bundle: .localize) + Text(.moveInitialPosition) } } case let .image(image): @@ -308,7 +309,7 @@ private struct EditSceneObjectViewModifier: ViewModifier { SceneObjectManager.shared.moveToBack(id: object.id) } label: { Image(systemName: "person.and.background.dotted") - Text(L10n.setAsBackground.key, bundle: .localize) + Text(.setAsBackground) } Divider() EditSceneObjectButton(isLocked: object.isLocked) { @@ -399,7 +400,7 @@ private struct EditSceneObjectViewModifier: ViewModifier { renderer.showWindow() } label: { Image(systemName: "network") - Text(L10n.interact.key, bundle: .localize) + Text(.interact) } FilterSceneObjectButton(object: object, configuration: web.filter?.configuration) { filter in web.filter = filter @@ -414,7 +415,7 @@ private struct EditSceneObjectViewModifier: ViewModifier { HideSceneObjectButton(object: object) LockSceneObjectButton(object: object) Divider() - EditSceneObjectButton(key: L10n.changeWindDirection.key, isLocked: object.isLocked) { + EditSceneObjectButton(key: .changeWindDirection, isLocked: object.isLocked) { wind.direction = SceneObject.Wind.random.direction SceneObjectManager.shared.update(object) } diff --git a/app/xcode/Sources/VCamUI/VCamMainView.swift b/app/xcode/Sources/VCamUI/VCamMainView.swift index a9b0b6c..40f4a37 100644 --- a/app/xcode/Sources/VCamUI/VCamMainView.swift +++ b/app/xcode/Sources/VCamUI/VCamMainView.swift @@ -27,7 +27,7 @@ public struct VCamMainView: View { MacWindowManager.shared.open(VCamSettingView(tab: .virtualCamera)) } label: { Image(systemName: "exclamationmark.triangle") - Text(L10n.cameraExtensionAwaitingUserApproval.key, bundle: .localize) + Text(.cameraExtensionAwaitingUserApproval) } .font(.footnote) .frame(maxWidth: .infinity, alignment: .trailing) @@ -36,17 +36,17 @@ public struct VCamMainView: View { let calibrateButton = FlatButton { Tracking.shared.resetCalibration() } label: { - Text(L10n.calibrate.key, bundle: .localize) + Text(.calibrate) .font(.callout) .foregroundStyle(.secondary) } .flatButtonStyle(.label) - .help(L10n.helpCalibrate.text) + .help(.helpCalibrate) HStack { if #available(macOS 26.0, *) { GroupBox { - SelectAllTextField(placeholder: L10n.message.text, text: $state.message) + SelectAllTextField(placeholder: String(localized: .message), text: $state.message) .padding(.horizontal, 8) } @@ -56,7 +56,7 @@ public struct VCamMainView: View { .padding(.vertical, -1.5) } } else { - SelectAllTextField(placeholder: L10n.message.text, text: $state.message) + SelectAllTextField(placeholder: String(localized: .message), text: $state.message) calibrateButton } diff --git a/app/xcode/Sources/VCamUI/VCamMenu.swift b/app/xcode/Sources/VCamUI/VCamMenu.swift index cc07d39..5189dd8 100644 --- a/app/xcode/Sources/VCamUI/VCamMenu.swift +++ b/app/xcode/Sources/VCamUI/VCamMenu.swift @@ -17,28 +17,24 @@ public enum VCamMenuItem: Identifiable, CaseIterable { public var id: Self { self } - public var title: LocalizedStringKey { + public var title: LocalizedStringResource { switch self { case .main: - return L10n.main.key + return .main #if FEATURE_3 case .screenEffect: - return L10n.screenEffect.key + return .screenEffect #endif case .recording: - return L10n.recording.key + return .recording } } public var icon: Image { switch self { case .main: -#if CI_TESTING - Image("SymbolIcon", bundle: .module) -#else Image(.symbolIcon) .resizable() -#endif #if FEATURE_3 case .screenEffect: Image(systemName: "sparkles") @@ -62,10 +58,11 @@ public struct VCamMenu: View { item.icon .scaledToFit() .frame(width: 16) - Text(item.title, bundle: .localize) + Text(item.title) .font(.callout) } .buttonStyle(VCamMenuButtonStyle(isSelected: item == state.currentMenu)) + .accessibilityIdentifier("menu.\(item)") } Spacer() MenuBottomView() @@ -82,7 +79,6 @@ private struct MenuBottomView: View { @Bindable private var recorder = VideoRecorder.shared - @Environment(\.locale) private var locale var body: some View { VStack(spacing: 2) { @@ -114,11 +110,10 @@ private struct MenuBottomView: View { } .buttonStyle(.plain) .popover(isPresented: $isScenePopover) { - VCamPopoverContainerWithWindow(L10n.scene.key) { + VCamPopoverContainerWithWindow(.scene) { VCamSceneListView() } .frame(width: 200, height: 240) - .environment(\.locale, locale) } .offset(y: -8) } diff --git a/app/xcode/Sources/VCamUI/VCamRecordingView.swift b/app/xcode/Sources/VCamUI/VCamRecordingView.swift index 960281e..e0f250a 100644 --- a/app/xcode/Sources/VCamUI/VCamRecordingView.swift +++ b/app/xcode/Sources/VCamUI/VCamRecordingView.swift @@ -27,8 +27,8 @@ public struct VCamRecordingView: View { GroupBox { HStack(spacing: 4) { - Text(L10n.destinationToSave.key, bundle: .localize) - TextField("", text: .constant(screenshotDestinationString)) + Text(.destinationToSave) + TextField(text: .constant(screenshotDestinationString)) { EmptyView() } .textFieldStyle(.roundedBorder) .disabled(true) Button { @@ -57,7 +57,7 @@ public struct VCamRecordingView: View { } label: { HStack(spacing: 4) { Image(systemName: "camera.circle") - restWaitTime < 1 ? Text(L10n.takePhoto.key, bundle: .localize) : Text(Int(restWaitTime).description) + restWaitTime < 1 ? Text(.takePhoto) : Text(Int(restWaitTime).description) } } .controlSize(.large) @@ -68,9 +68,9 @@ public struct VCamRecordingView: View { in: 0...30) { let seconds = Int(screenshotWaitTime) HStack { - Text(L10n.timeToTakePhoto.key, bundle: .localize) - Text("\(seconds)") - Text(L10n.seconds.key, bundle: .localize) + Text(.timeToTakePhoto) + Text(verbatim: "\(seconds)") + Text(.seconds) } } .padding(.leading, 8) @@ -95,27 +95,28 @@ public struct VCamRecordingView: View { } label: { HStack(spacing: 4) { Image(systemName: "video") - Text(recorder.isRecording ? L10n.stopRecording.key : L10n.startRecording.key, bundle: .localize) + Text(recorder.isRecording ? .stopRecording : .startRecording) } } .controlSize(.large) + .accessibilityIdentifier("recording.startButton") Spacer() Picker(selection: $recordingVideoFormat) { ForEach(VideoFormat.allCases) { format in - Text(format.name).tag(format.rawValue) + Text(verbatim: format.localizedName).tag(format.rawValue) } } label: { - Text(L10n.videoFormat.key, bundle: .localize) + Text(.videoFormat) } .disabled(recorder.isRecording) } GroupBox { HStack(spacing: 16) { Toggle(isOn: $recordSystemSound) { - Text(L10n.recordDesktopAudio.key, bundle: .localize) + Text(.recordDesktopAudio) } Divider() - ValueEditField.emptyValueLabel(L10n.micSyncOffset.key, value: $recordMicSyncOffset.map(), type: .stepper) + ValueEditField.emptyValueLabel(.micSyncOffset, value: $recordMicSyncOffset.map(), type: .stepper) .disabled(!recordSystemSound) .opacity(recordSystemSound ? 1 : 0.5) } diff --git a/app/xcode/Sources/VCamUI/VCamSceneListView.swift b/app/xcode/Sources/VCamUI/VCamSceneListView.swift index 6a6edc0..f007c50 100644 --- a/app/xcode/Sources/VCamUI/VCamSceneListView.swift +++ b/app/xcode/Sources/VCamUI/VCamSceneListView.swift @@ -1,10 +1,3 @@ -// -// VCamSceneListView.swift -// -// -// Created by Tatsuya Tanaka on 2022/05/06. -// - import SwiftUI import VCamEntity import VCamData @@ -25,6 +18,7 @@ public struct VCamSceneListView: View { TextFieldListRow( id: scene.id, text: $scene.name, + placeholder: String(localized: .scene), editingId: $editingId, selectedId: selectedId ) { @@ -105,7 +99,7 @@ public struct VCamSceneListView: View { extension VCamSceneListView: MacWindow { public var windowTitle: String { - L10n.scene.text + String(localized: .scene) } public func configureWindow(_ window: NSWindow) -> NSWindow { @@ -127,7 +121,7 @@ private struct DeleteSceneButton: View { SceneManager.shared.remove(byId: scene.id) } label: { Image(systemName: "trash") - Text(L10n.delete.key, bundle: .localize) + Text(.delete) } } } @@ -159,7 +153,7 @@ private struct EditSceneViewModifier: ViewModifier { } } label: { Image(systemName: "doc.on.doc") - Text(L10n.duplicate.key, bundle: .localize) + Text(.duplicate) } Divider() DeleteSceneButton(scene: scene) diff --git a/app/xcode/Sources/VCamUI/VCamTrackingView.swift b/app/xcode/Sources/VCamUI/VCamTrackingView.swift index 94df215..40ddd5b 100644 --- a/app/xcode/Sources/VCamUI/VCamTrackingView.swift +++ b/app/xcode/Sources/VCamUI/VCamTrackingView.swift @@ -22,14 +22,14 @@ public struct VCamTrackingView: View { public var body: some View { HStack { VStack(spacing: 8) { - Text(L10n.faceEyeMouth.key, bundle: .localize) + Text(.faceEyeMouth) .bold() Picker(selection: faceTrackingMethod) { ForEach(TrackingMethod.Face.allCases) { method in - Text(method.name, bundle: .localize) + Text(verbatim: method.name) } } label: { - Text(L10n.faceEyeMouth.key, bundle: .localize) + Text(.faceEyeMouth) } .labelsHidden() .frame(maxWidth: .infinity, alignment: .trailing) @@ -38,20 +38,20 @@ public struct VCamTrackingView: View { Divider() VStack(spacing: 8) { - Text(L10n.hand.key, bundle: .localize) + Text(.hand) .bold() #if FEATURE_3 Picker(selection: handTrackingMethod) { ForEach(TrackingMethod.Hand.allCases) { method in - Text(method.name, bundle: .localize) + Text(verbatim: method.name) } } label: { - Text(L10n.hand.key, bundle: .localize) + Text(.hand) } .labelsHidden() .frame(maxWidth: .infinity, alignment: .trailing) #else - Text(L10n.notSupported.key, bundle: .localize) + Text(.notSupported) .frame(maxWidth: .infinity, alignment: .trailing) #endif } @@ -62,21 +62,21 @@ public struct VCamTrackingView: View { Divider() VStack(spacing: 8) { - Text(L10n.finger.key, bundle: .localize) + Text(.finger) .bold() #if FEATURE_3 Picker(selection: fingerTrackingMethod) { ForEach(TrackingMethod.Finger.allCases) { method in - Text(method.name, bundle: .localize) + Text(verbatim: method.name) } } label: { - Text(L10n.finger.key, bundle: .localize) + Text(.finger) } .labelsHidden() .frame(maxWidth: .infinity, alignment: .trailing) #else - Text(L10n.notSupported.key, bundle: .localize) + Text(.notSupported) .frame(maxWidth: .infinity, alignment: .trailing) #endif } @@ -111,10 +111,10 @@ public struct VCamTrackingView: View { } extension TrackingMethod.Face { - var name: LocalizedStringKey { + var name: String { switch self { - case .disabled: return L10n.none.key - case .default: return L10n.default.key + case .disabled: return String(localized: .none) + case .default: return String(localized: .default) case .iFacialMocap: return "iFacialMocap" case .vcamMocap: return "VCamMocap" } @@ -122,10 +122,10 @@ extension TrackingMethod.Face { } extension TrackingMethod.Hand { - var name: LocalizedStringKey { + var name: String { switch self { - case .disabled: return L10n.none.key - case .default: return L10n.default.key + case .disabled: return String(localized: .none) + case .default: return String(localized: .default) case .vcamMocap: return "VCamMocap" #if ENABLE_MOCOPI case .mocopi: return "mocopi" @@ -135,10 +135,10 @@ extension TrackingMethod.Hand { } extension TrackingMethod.Finger { - var name: LocalizedStringKey { + var name: String { switch self { - case .disabled: return L10n.none.key - case .default: return L10n.default.key + case .disabled: return String(localized: .none) + case .default: return String(localized: .default) case .vcamMocap: return "VCamMocap" } } diff --git a/app/xcode/Sources/VCamUI/WebRenderer+UI.swift b/app/xcode/Sources/VCamUI/WebRenderer+UI.swift index 207badf..4677777 100644 --- a/app/xcode/Sources/VCamUI/WebRenderer+UI.swift +++ b/app/xcode/Sources/VCamUI/WebRenderer+UI.swift @@ -1,21 +1,13 @@ -// -// WebRenderer+UI.swift -// -// -// Created by Tatsuya Tanaka on 2022/06/20. -// - import Foundation import SwiftUI import CoreImage import Combine -import VCamLocalization import VCamUIFoundation public extension WebRenderer { static func showPreferences(url: String?, bookmarkData: Data?, width: Int?, height: Int?, fps: Int?, css: String?, js: String?, completion: @escaping (WebRenderer) -> Void) { showSheet( - title: L10n.web.text, + title: String(localized: .web), view: { close in WebRendererPreferenceView( url: url, @@ -87,7 +79,7 @@ public struct WebRendererPreferenceView: View { } public var body: some View { - ModalSheet(doneTitle: L10n.apply.text, doneDisabled: doneDisabled) { + ModalSheet(doneTitle: String(localized: .apply), doneDisabled: doneDisabled) { renderer = nil // References remain, so explicitly clear them close() } done: { @@ -120,11 +112,11 @@ public struct WebRendererPreferenceView: View { ScrollView { Form { HStack { - Text("URL") + Text(verbatim: "URL") Spacer() if isLocalFile { HStack { - TextField("", text: $path) + TextField(text: $path) { EmptyView() } .disabled(true) Button { guard let url = FileUtility.openFile(type: .html), @@ -133,52 +125,52 @@ public struct WebRendererPreferenceView: View { path = url.path pathBookmarkData = bookmarkData } label: { - Text(L10n.pick.key, bundle: .localize) + Text(.pick) } } } else { - TextField("", text: $url) + TextField(text: $url) { EmptyView() } } if !doneDisabled, let resource = resource { Button { refreshScreen(resource: resource) } label: { - Text(L10n.refreshScreen.key, bundle: .localize) + Text(.refreshScreen) } } if let renderer = renderer { Button { renderer.showWindow() } label: { - Text(L10n.interact.key, bundle: .localize) + Text(.interact) } } } HStack { Spacer() Toggle(isOn: $isLocalFile) { - Text(L10n.localFile.key, bundle: .localize) + Text(.localFile) } } HStack(alignment: .top) { VStack { Form { HStack { - Text(L10n.width.key, bundle: .localize) + Text(.width) Spacer() - TextField("", text: $width.map()) + TextField(text: $width.map()) { EmptyView() } .acceptNumberOnly($width.map()) } HStack { - Text(L10n.height.key, bundle: .localize) + Text(.height) Spacer() - TextField("", text: $height.map()) + TextField(text: $height.map()) { EmptyView() } .acceptNumberOnly($height.map()) } HStack { - Text("FPS") + Text(verbatim: "FPS") Spacer() - TextField("", text: $fps.map()) + TextField(text: $fps.map()) { EmptyView() } .acceptNumberOnly($fps.map()) } } @@ -187,7 +179,7 @@ public struct WebRendererPreferenceView: View { VStack { GroupBox { VStack { - Text("CSS") + Text(verbatim: "CSS") TextEditor(text: $css) .font(Font.footnote.monospaced()) .disableAutocorrection(true) @@ -195,13 +187,13 @@ public struct WebRendererPreferenceView: View { } GroupBox { VStack { - Text("JavaScript") + Text(verbatim: "JavaScript") .frame(maxWidth: .infinity) .overlay( Button { renderer?.javaScript = js } label: { - Text(L10n.runCode.key, bundle: .localize) + Text(.runCode) }, alignment: .trailing ) diff --git a/app/xcode/Sources/VCamUI/WebRenderer.swift b/app/xcode/Sources/VCamUI/WebRenderer.swift index 2ec05d2..c13ef37 100644 --- a/app/xcode/Sources/VCamUI/WebRenderer.swift +++ b/app/xcode/Sources/VCamUI/WebRenderer.swift @@ -195,8 +195,8 @@ public final class WebRenderer { let containerView = webView.superview webView.removeFromSuperview() - VCamWindow.showWindow(title: L10n.interact.text) { close in - ModalSheet(doneTitle: L10n.done.text, done: close) { + VCamWindow.showWindow(title: String(localized: .interact)) { close in + ModalSheet(doneTitle: String(localized: .done), done: close) { NSViewRepresentableBuilder { webView } diff --git a/app/xcode/Sources/VCamUI/WindowManager.swift b/app/xcode/Sources/VCamUI/WindowManager.swift index 19d563a..06c6180 100644 --- a/app/xcode/Sources/VCamUI/WindowManager.swift +++ b/app/xcode/Sources/VCamUI/WindowManager.swift @@ -116,14 +116,14 @@ public final class WindowManager { self.statusItem = statusItem statusItem.button?.image = Bundle.module.image(forResource: "StatusItemIcon") let menu = NSMenu() - let unhideMenu = NSMenuItem(title: "\(L10n.openVCam(Bundle.main.displayName).text)...", action: #selector(unhide), keyEquivalent: "") + let unhideMenu = NSMenuItem(title: "\(String(localized: .openVCam(Bundle.main.displayName)))...", action: #selector(unhide), keyEquivalent: "") unhideMenu.target = self menu.addItem(unhideMenu) - let preferenceMenu = NSMenuItem(title: "\(L10n.settings.text)...", action: #selector(openPreferences), keyEquivalent: "") + let preferenceMenu = NSMenuItem(title: "\(String(localized: .settings))...", action: #selector(openPreferences), keyEquivalent: "") preferenceMenu.target = self menu.addItem(preferenceMenu) menu.addItem(NSMenuItem.separator()) - let quitMenu = NSMenuItem(title: L10n.quitVCam(Bundle.main.displayName).text, action: #selector(quit), keyEquivalent: "q") + let quitMenu = NSMenuItem(title: String(localized: .quitVCam(Bundle.main.displayName)), action: #selector(quit), keyEquivalent: "q") quitMenu.target = self menu.addItem(quitMenu)