diff --git a/Limelight/iPad.storyboard b/Limelight/Base.lproj/iPad.storyboard
similarity index 92%
rename from Limelight/iPad.storyboard
rename to Limelight/Base.lproj/iPad.storyboard
index 06fe8045..f1b2e39a 100644
--- a/Limelight/iPad.storyboard
+++ b/Limelight/Base.lproj/iPad.storyboard
@@ -59,11 +59,11 @@
-
+
-
-
-
+
+
@@ -109,8 +109,8 @@
-
-
+
+
@@ -122,8 +122,8 @@
-
-
+
+
@@ -153,16 +153,16 @@
-
-
+
+
-
-
+
+
@@ -179,8 +179,8 @@
-
-
+
+
@@ -219,15 +219,15 @@
-
-
+
+
-
+
@@ -236,15 +236,15 @@
-
-
+
+
-
+
@@ -253,129 +253,8 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
@@ -391,8 +270,8 @@
-
-
+
+
@@ -430,18 +309,139 @@ ICAgICAgICAgICAgICA
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -478,7 +478,7 @@ ICAgICAgICAgICAgICA
-
+
diff --git a/Limelight/iPhone.storyboard b/Limelight/Base.lproj/iPhone.storyboard
similarity index 100%
rename from Limelight/iPhone.storyboard
rename to Limelight/Base.lproj/iPhone.storyboard
diff --git a/Limelight/Localization/Localizable.xcstrings b/Limelight/Localization/Localizable.xcstrings
new file mode 100644
index 00000000..5825964f
--- /dev/null
+++ b/Limelight/Localization/Localizable.xcstrings
@@ -0,0 +1,1011 @@
+{
+ "sourceLanguage" : "en",
+ "strings" : {
+ "!ML_TEST_RESULT_INCONCLUSIVE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\n\nYour device's network connection is blocking Moonlight. Streaming may not work while connected to this network."
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\n\n设备的网络连接似乎正在阻塞Moonlight. 可能无法在此网络中串流."
+ }
+ }
+ }
+ },
+ "%@ is currently running" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "%@ 正在运行"
+ }
+ }
+ }
+ },
+ "Add Host Manually" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "手动添加远程主机"
+ }
+ }
+ }
+ },
+ "Bitrate: %.1f Mbps" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流码率: %.1f Mbps"
+ }
+ }
+ }
+ },
+ "Cancel" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "取消"
+ }
+ }
+ }
+ },
+ "Connecting" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "正在连接"
+ }
+ }
+ }
+ },
+ "Connection Error" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接错误"
+ }
+ }
+ }
+ },
+ "Connection Failed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接失败"
+ }
+ }
+ }
+ },
+ "Connection Help" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接帮助"
+ }
+ }
+ }
+ },
+ "Connection Interrupted" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接已中断"
+ }
+ }
+ }
+ },
+ "Connection Terminated" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接已终止"
+ }
+ }
+ }
+ },
+ "ConnectionFailedFirewall" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\n\nCheck your firewall and port forwarding rules for port(s):\n%s"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\n\n检查主机端防火墙以及端口%s的转发规则"
+ }
+ }
+ }
+ },
+ "Current profile updated successfully" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "当前布局已修改"
+ }
+ }
+ }
+ },
+ "Current Profile: %@" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "当前布局: %@"
+ }
+ }
+ }
+ },
+ "Custom Resolution Selected" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "已设定为自定义分辨率"
+ }
+ }
+ }
+ },
+ "Custom resolutions are not officially supported by GeForce Experience, so it will not set your host display resolution. You will need to set it manually while in game.\n\nResolutions that are not supported by your client or host PC may cause streaming errors." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "您可能需要在主机端的显卡控制面板手动添加自定义分辨率"
+ }
+ }
+ }
+ },
+ "Delete Buttons Here" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "按键删除"
+ }
+ }
+ }
+ },
+ "Drag and drop buttons onto this trash can to remove them from the interface" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "将按键拖动到这个垃圾桶即可删除"
+ }
+ }
+ }
+ },
+ "Enter Custom Resolution" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "输入自定义分辨率"
+ }
+ }
+ }
+ },
+ "Enter the name you want to save this controller profile as" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "将当前虚拟手柄布局另存为"
+ }
+ }
+ }
+ },
+ "Enter_PIN_Msg" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\nEnter the following PIN on the host machine: %@\n\nIf your host PC is running Sunshine, navigate to the Sunshine web UI to enter the PIN"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "\n请在主机端输入PIN码: %@\n\n如果主机运行的是Sunshine, 请在网页控制台输入PIN码"
+ }
+ }
+ }
+ },
+ "Failed to quit app. If this app was started by another device, you'll need to quit from that device." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出应用失败. 如果此应用是由其他串流设备启动的, 请用相应的设备退出此应用"
+ }
+ }
+ }
+ },
+ "Failed to resolve host." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "解析主机域名失败"
+ }
+ }
+ }
+ },
+ "Got it!" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "了解!"
+ }
+ }
+ }
+ },
+ "Help" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "帮助"
+ }
+ }
+ }
+ },
+ "Hide App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "隐藏应用"
+ }
+ }
+ }
+ },
+ "Host MAC unknown, unable to send WOL Packet" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "未知主机MAC地址, 无法发送WOL包"
+ }
+ }
+ }
+ },
+ "If Moonlight doesn't find your local gaming PC automatically, enter the IP address of your PC" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "输入主机端IP地址"
+ }
+ }
+ }
+ },
+ "Launch App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启动应用"
+ }
+ }
+ }
+ },
+ "Layout of the Default profile can not be changed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "默认布局无法被修改"
+ }
+ }
+ }
+ },
+ "ML_TEST_RESULT_INCONCLUSIVE" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "The network test could not be performed because none of Moonlight's connection testing servers were reachable. Check your Internet connection or try again later."
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "无法执行网络测试. 请检查网络连接后重试."
+ }
+ }
+ }
+ },
+ "Mouse Pointer Velocity: %d%%" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "鼠标指针灵敏度: %d%%"
+ }
+ }
+ }
+ },
+ "name" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "名称"
+ }
+ }
+ }
+ },
+ "NetTestFailed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Your current network connection seems to be blocking Moonlight. Streaming may not work while connected to this network.\n\nThe following network ports were blocked:\n%s"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "设备的网络连接似乎正在阻塞Moonlight. 可能无法在此网络中串流.\n\n以下网络端口被阻塞:\n%s"
+ }
+ }
+ }
+ },
+ "NetTestOK" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "This network does not appear to be blocking Moonlight. If you still have trouble connecting, check your PC's firewall settings.\n\nVisit the Moonlight Setup Guide on GitHub for additional setup help and troubleshooting steps."
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络测试成功. 如果仍然无法连接远程主机, 请检查主机端防火墙设置."
+ }
+ }
+ }
+ },
+ "Network Error" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络错误"
+ }
+ }
+ }
+ },
+ "Network Test Complete" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络测试已完成"
+ }
+ }
+ }
+ },
+ "No video received from host." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "无法从主机接收视频帧"
+ }
+ }
+ }
+ },
+ "Nothing to Undo" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "无修改可撤消"
+ }
+ }
+ }
+ },
+ "NVIDIA GameStream End-of-Service" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "NVIDIA GAMESTREAM 服务终止"
+ }
+ }
+ }
+ },
+ "Ok" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "确认"
+ }
+ }
+ }
+ },
+ "On-Screen Controls" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "屏显虚拟手柄"
+ }
+ }
+ }
+ },
+ "Online - Not Paired" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "在线 - 未配对"
+ }
+ }
+ }
+ },
+ "Online - Paired" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "在线 - 已配对"
+ }
+ }
+ }
+ },
+ "Pairing" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "正在配对"
+ }
+ }
+ }
+ },
+ "Pairing Failed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "配对失败"
+ }
+ }
+ }
+ },
+ "Poor connection to PC" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络状态较差"
+ }
+ }
+ }
+ },
+ "Profile %@ duplicated from current layout" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "当前布局已另存为: %@"
+ }
+ }
+ }
+ },
+ "Profile Default can not be overwritten" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "默认布局无法被覆盖保存"
+ }
+ }
+ }
+ },
+ "Profile name already exists" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "布局名称已存"
+ }
+ }
+ }
+ },
+ "Profile name cannot be blank!" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "布局名称不能为空!"
+ }
+ }
+ }
+ },
+ "Quit App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出应用"
+ }
+ }
+ }
+ },
+ "Quit Running App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出运行中的应用"
+ }
+ }
+ }
+ },
+ "Quit Running App and Start" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出运行中的应用, 并运行此应用"
+ }
+ }
+ }
+ },
+ "Quitting App Failed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出应用失败"
+ }
+ }
+ }
+ },
+ "Quitting application: %@" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "正在退出应用: %@"
+ }
+ }
+ }
+ },
+ "Rebase in Stream View" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流中修改布局"
+ }
+ }
+ }
+ },
+ "Remove Host" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "移除主机"
+ }
+ }
+ }
+ },
+ "Resume App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "恢复应用"
+ }
+ }
+ }
+ },
+ "Resume Running App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "恢复运行中的应用"
+ }
+ }
+ }
+ },
+ "Save" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "保存"
+ }
+ }
+ }
+ },
+ "Saving over the 'Default' profile is not allowed" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "默认布局无法被覆盖保存"
+ }
+ }
+ }
+ },
+ "Searching for PCs on your network..." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Searching for PCs on your network..."
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "正在搜索网络中的主机 ..."
+ }
+ }
+ }
+ },
+ "Select Host" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "选择主机"
+ }
+ }
+ }
+ },
+ "Select New Host" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "选择新主机"
+ }
+ }
+ }
+ },
+ "Set PC/Game resolution:" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流分辨率:"
+ }
+ }
+ }
+ },
+ "Show App" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "显示应用"
+ }
+ }
+ }
+ },
+ "Slow connection to PC, Reduce your bitrate" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络带宽不足, 请降低串流码率"
+ }
+ }
+ }
+ },
+ "Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "成功发送唤醒请求. 主机唤醒需要一定时间. 如果主机未被唤醒, 请检查Wake-on-LAN设置"
+ }
+ }
+ }
+ },
+ "Swipe & Exit Distance: %.2f * screen-width" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "退出远程桌面的滑动距离: %.2f x 屏幕宽度"
+ }
+ }
+ }
+ },
+ "Tap 4 fingers to change on-screen controller layout in stream view" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "在串流视图中轻按4根手指修改虚拟手柄布局"
+ }
+ }
+ }
+ },
+ "Tap 4 Fingers to Change OSC Layout in Stream View" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "在串流视图中轻按4根手指修改虚拟手柄布局"
+ }
+ }
+ }
+ },
+ "Tap-Toggle Local Keyboard Disabled" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "本地软键盘切换手势已禁用"
+ }
+ }
+ }
+ },
+ "Test Network" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "测试网络"
+ }
+ }
+ }
+ },
+ "The connection was terminated, Error code: %@" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "连接终止, 错误码: %@"
+ }
+ }
+ }
+ },
+ "There are no changes to undo" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "已经没有修改可以撤消"
+ }
+ }
+ }
+ },
+ "Tip: Swipe from screen edge to a certiain distance (configured by Swipe & Exit settings) to disconnect from your PC" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "提示: 从屏幕连续滑动一定距离退出远程桌面. 滑动边缘和距离取决于菜单设置."
+ }
+ }
+ }
+ },
+ "To Toggle Local Keyboard: Tap %d Fingers" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "To Toggle Local Keyboard: Tap %d Fingers"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "轻按%d根手指, 切换本地软键盘"
+ }
+ }
+ }
+ },
+ "Touch Pointer Velocity: %d%%" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "触点灵敏度: %d%%"
+ }
+ }
+ }
+ },
+ "Touch Pointer Velocity: Scaled on %d%% of Right Screen" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "调节靠右 %d%%屏幕区域的触点灵敏度"
+ }
+ }
+ }
+ },
+ "Unsupported on this device" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "该设备不支持"
+ }
+ }
+ }
+ },
+ "Video Height" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "视频高度"
+ }
+ }
+ }
+ },
+ "Video Width" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "视频宽度"
+ }
+ }
+ }
+ },
+ "View All Apps" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "查看所有应用"
+ }
+ }
+ }
+ },
+ "Wake PC" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "唤醒PC"
+ }
+ }
+ }
+ },
+ "Wake-On-LAN" : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Wake-on-LAN"
+ }
+ }
+ }
+ },
+ "Your network connection isn't performing well. Reduce your video bitrate setting or try a faster connection." : {
+ "extractionState" : "manual",
+ "localizations" : {
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "网络状态较差. 请降低码率或更换更可靠的网络连接."
+ }
+ }
+ }
+ }
+ },
+ "version" : "1.0"
+}
\ No newline at end of file
diff --git a/Limelight/Localization/LocalizationHelper.h b/Limelight/Localization/LocalizationHelper.h
new file mode 100644
index 00000000..565fd83f
--- /dev/null
+++ b/Limelight/Localization/LocalizationHelper.h
@@ -0,0 +1,21 @@
+//
+// LocalizationHelper.h
+// Moonlight
+//
+// Created by ZWM on 2024/6/30.
+// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
+//
+
+#ifndef LocalizationHelper_h
+#define LocalizationHelper_h
+
+#import
+
+@interface LocalizationHelper : NSObject
+
+// Method to get localized string with format arguments
++ (NSString *)localizedStringForKey:(NSString *)key, ... NS_FORMAT_FUNCTION(1,2);
+
+@end
+
+#endif /* LocalizationHelper_h */
diff --git a/Limelight/Localization/LocalizationHelper.m b/Limelight/Localization/LocalizationHelper.m
new file mode 100644
index 00000000..92332e8b
--- /dev/null
+++ b/Limelight/Localization/LocalizationHelper.m
@@ -0,0 +1,22 @@
+//
+// LocalizationHelper.m
+// Moonlight
+//
+// Created by Admin on 2024/6/30.
+// Copyright © 2024 Moonlight Game Streaming Project. All rights reserved.
+//
+
+#import "LocalizationHelper.h"
+
+@implementation LocalizationHelper
+
++ (NSString *)localizedStringForKey:(NSString *)key, ... {
+ va_list args;
+ va_start(args, key);
+ NSString *format = NSLocalizedStringFromTable(key, @"Localizable", nil);
+ NSString *result = [[NSString alloc] initWithFormat:format arguments:args];
+ va_end(args);
+ return result;
+}
+
+@end
diff --git a/Limelight/UIComputerView.m b/Limelight/UIComputerView.m
index 450ce3b8..f1c718f3 100644
--- a/Limelight/UIComputerView.m
+++ b/Limelight/UIComputerView.m
@@ -7,6 +7,7 @@
//
#import "UIComputerView.h"
+#import "LocalizationHelper.h"
@implementation UIComputerView {
TemporaryHost* _host;
@@ -104,7 +105,7 @@ static const int LABEL_DY = 20;
[self addTarget:self action:@selector(addClicked) forControlEvents:UIControlEventPrimaryActionTriggered];
- [_hostLabel setText:@"Add Host Manually"];
+ [_hostLabel setText:[LocalizationHelper localizedStringForKey:@"Add Host Manually"]];
[_hostLabel sizeToFit];
[_hostOverlay setImage:[UIImage imageNamed:@"AddOverlayIcon"]];
diff --git a/Limelight/Utility/Utils.m b/Limelight/Utility/Utils.m
index fded11b7..df974838 100644
--- a/Limelight/Utility/Utils.m
+++ b/Limelight/Utility/Utils.m
@@ -11,6 +11,7 @@
#include
#include
#include
+#import "LocalizationHelper.h"
@implementation Utils
NSString *const deviceName = @"roth";
@@ -73,7 +74,7 @@ NSString *const deviceName = @"roth";
+ (void) addHelpOptionToDialog:(UIAlertController*)dialog {
#if !TARGET_OS_TV
// tvOS doesn't have a browser
- [dialog addAction:[UIAlertAction actionWithTitle:@"Help" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [dialog addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Help"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[Utils launchUrl:@"https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting"];
}]];
#endif
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
index 5250ac7a..b47f5139 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
+++ b/Limelight/ViewControllers/CustomOSCViewControl/LayoutOnScreenControlsViewController.m
@@ -11,6 +11,7 @@
#import "OnScreenButtonState.h"
#import "OnScreenControls.h"
#import "OSCProfilesManager.h"
+#import "LocalizationHelper.h"
@interface LayoutOnScreenControlsViewController ()
@@ -172,9 +173,9 @@
}
- (IBAction) trashCanTapped:(id)sender {
- UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Delete Buttons Here" message:@"Drag and drop buttons onto this trash can to remove them from the interface" preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController *alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Delete Buttons Here"] message:[LocalizationHelper localizedStringForKey:@"Drag and drop buttons onto this trash can to remove them from the interface"] preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *ok = [UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:nil];
+ UIAlertAction *ok = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil];
[alert addAction:ok];
[self presentViewController:alert animated:YES completion:nil];
}
@@ -210,8 +211,8 @@
[self OSCLayoutChanged]; // will fade the undo button in or out depending on whether there are any further changes to undo
}
else { // there are no changes to undo. let user know there are no changes to undo
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@"Nothing to Undo"] message: @"There are no changes to undo" preferredStyle:UIAlertControllerStyleAlert];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Nothing to Undo"] message: [LocalizationHelper localizedStringForKey: @"There are no changes to undo"] preferredStyle:UIAlertControllerStyleAlert];
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[savedAlertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
@@ -222,14 +223,14 @@
- (IBAction) saveTapped:(id)sender {
if([self->profilesManager updateSelectedProfileSucceedWithButtonLayers:self.layoutOSC.OSCButtonLayers]){
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Current profile updated successfully"] preferredStyle:UIAlertControllerStyleAlert];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Current profile updated successfully"] preferredStyle:UIAlertControllerStyleAlert];
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
}
else{
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Profile Default can not be overwritten"] preferredStyle:UIAlertControllerStyleAlert];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Profile Default can not be overwritten"] preferredStyle:UIAlertControllerStyleAlert];
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self.oscProfilesTableViewController profileViewRefresh]; // execute this will reset layout in OSC tool!
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
@@ -243,7 +244,7 @@
[self->profilesManager saveProfileWithName: enteredProfileName andButtonLayers:self.layoutOSC.OSCButtonLayers];
}]];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"No" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // don't overwrite the existing profile
+ [savedAlertController addAction:[UIAlertAction actionWithpinNo" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // don't overwrite the existing profile
[savedAlertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
@@ -254,13 +255,13 @@
UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"%@ profile saved and set as your active in-game controller profile layout", enteredProfileName] preferredStyle:UIAlertControllerStyleAlert]; // Let user know this profile has been saved and is now the selected controller layout
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[savedAlertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
}
}]];
- [inputNameAlertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // adds a button that allows user to decline the option to save the controller layout they currently see on screen
+ [inputNameAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // adds a button that allows user to decline the option to save the controller layout they currently see on screen
[inputNameAlertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:inputNameAlertController animated:YES completion:nil]; */
@@ -286,7 +287,7 @@
// Set the label's frame with the calculated x-position
self.currentProfileLabel.frame = CGRectMake(xPosition, self.currentProfileLabel.frame.origin.y, self.currentProfileLabel.frame.size.width, self.currentProfileLabel.frame.size.height);
self.currentProfileLabel.hidden = NO; // Show Current Profile display
- [self.currentProfileLabel setText:[NSString stringWithFormat:@"Current Profile: %@",[profilesManager getSelectedProfile].name]]; // display current profile name when profile is being refreshed.
+ [self.currentProfileLabel setText:[LocalizationHelper localizedStringForKey:@"Current Profile: %@",[profilesManager getSelectedProfile].name]]; // display current profile name when profile is being refreshed.
//initialiaze _oscProfilesTableViewController
_oscProfilesTableViewController = [storyboard instantiateViewControllerWithIdentifier:@"OSCProfilesTableViewController"];
@@ -393,8 +394,8 @@
// in case of default profile OSC change, popup msgbox & remind user it's not allowed.
if([profilesManager getIndexOfSelectedProfile] == 0 && [self.layoutOSC.layoutChanges count] > 0){
- UIAlertController * movedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Layout of the Default profile can not be changed"] preferredStyle:UIAlertControllerStyleAlert];
- [movedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ UIAlertController * movedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Layout of the Default profile can not be changed"] preferredStyle:UIAlertControllerStyleAlert];
+ [movedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[self.oscProfilesTableViewController profileViewRefresh];
}]];
[self presentViewController:movedAlertController animated:YES completion:nil];
diff --git a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
index dca63e2a..07e3a5db 100644
--- a/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
+++ b/Limelight/ViewControllers/CustomOSCViewControl/OSCProfilesTableViewController.m
@@ -12,6 +12,7 @@
#import "OSCProfile.h"
#import "OnScreenButtonState.h"
#import "OSCProfilesManager.h"
+#import "LocalizationHelper.h"
const double NAV_BAR_HEIGHT = 50;
@@ -73,22 +74,22 @@ const double NAV_BAR_HEIGHT = 50;
/* Loads the OSC profile that user selected, dismisses this VC, then tells the presenting view controller to lay out the on screen buttons according to the selected profile's instructions */
- (IBAction) duplicateTapped:(id)sender {
- UIAlertController * inputNameAlertController = [UIAlertController alertControllerWithTitle: @"Enter the name you want to save this controller profile as" message: @"" preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController * inputNameAlertController = [UIAlertController alertControllerWithTitle: [LocalizationHelper localizedStringForKey:@"Enter the name you want to save this controller profile as"] message: @"" preferredStyle:UIAlertControllerStyleAlert];
[inputNameAlertController addTextFieldWithConfigurationHandler:^(UITextField *textField) { // pop up notification with text field where user can enter the text they wish to name their OSC layout profile
- textField.placeholder = @"name";
+ textField.placeholder = [LocalizationHelper localizedStringForKey:@"name"];
textField.textColor = [UIColor lightGrayColor];
textField.clearButtonMode = UITextFieldViewModeWhileEditing;
textField.borderStyle = UITextBorderStyleNone;
}];
- [inputNameAlertController addAction:[UIAlertAction actionWithTitle:@"Save" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // add save button to allow user to save the on screen controller configuration
+ [inputNameAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Save"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // add save button to allow user to save the on screen controller configuration
NSArray *textFields = inputNameAlertController.textFields;
UITextField *nameField = textFields[0];
NSString *enteredProfileName = nameField.text;
if ([enteredProfileName isEqualToString:@"Default"]) { // don't let user user overwrite the 'Default' profile
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Saving over the 'Default' profile is not allowed"] preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Saving over the 'Default' profile is not allowed"] preferredStyle:UIAlertControllerStyleAlert];
- [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[alertController dismissViewControllerAnimated:NO completion:^{
[self presentViewController:inputNameAlertController animated:YES completion:nil];
}];
@@ -96,9 +97,9 @@ const double NAV_BAR_HEIGHT = 50;
[self presentViewController:alertController animated:YES completion:nil];
}
else if ([enteredProfileName length] == 0) { // if user entered no text and taps the 'Save' button let them know they can't do that
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Profile name cannot be blank!"] preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Profile name cannot be blank!"] preferredStyle:UIAlertControllerStyleAlert];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // show pop up notification letting user know they must enter a name in the text field if they wish to save the controller profile
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // show pop up notification letting user know they must enter a name in the text field if they wish to save the controller profile
[savedAlertController dismissViewControllerAnimated:NO completion:^{
[self presentViewController:inputNameAlertController animated:YES completion:nil];
@@ -107,9 +108,9 @@ const double NAV_BAR_HEIGHT = 50;
[self presentViewController:savedAlertController animated:YES completion:nil];
}
else if ([self->profilesManager profileNameAlreadyExist:enteredProfileName] == YES) { // if the entered profile name already
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Profile name already exists"] preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Profile name already exists"] preferredStyle:UIAlertControllerStyleAlert];
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
//[savedAlertController dismissViewControllerAnimated:NO completion:nil];
//[self profileViewRefresh]; //refresh profile view after saving new profile;
}]];
@@ -119,16 +120,16 @@ const double NAV_BAR_HEIGHT = 50;
[self->profilesManager saveProfileWithName: enteredProfileName andButtonLayers:self.currentOSCButtonLayers]; // the OSC layout here is passed from parent LayoutOSCViewController;
[self->profilesManager setProfileToSelected: enteredProfileName];
- UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [NSString stringWithFormat:@"Profile %@ duplicated from current layout", enteredProfileName] preferredStyle:UIAlertControllerStyleAlert]; // Let user know this profile has been duplicated & saved
+ UIAlertController * savedAlertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: [LocalizationHelper localizedStringForKey:@"Profile %@ duplicated from current layout", enteredProfileName] preferredStyle:UIAlertControllerStyleAlert]; // Let user know this profile has been duplicated & saved
- [savedAlertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [savedAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[savedAlertController dismissViewControllerAnimated:NO completion:nil];
[self profileViewRefresh]; //refresh profile view after saving new profile;
}]];
[self presentViewController:savedAlertController animated:YES completion:nil];
}
}]];
- [inputNameAlertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // adds a button that allows user to decline the option to save the controller layout they currently see on screen
+ [inputNameAlertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { // adds a button that allows user to decline the option to save the controller layout they currently see on screen
[inputNameAlertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:inputNameAlertController animated:YES completion:nil];
@@ -186,7 +187,7 @@ const double NAV_BAR_HEIGHT = 50;
if ([[[profiles objectAtIndex:indexPath.row] name] isEqualToString:@"Default"]) { // if user is attempting to delete the 'Default' profile then show a pop up telling user they can't do that and return out of this method
UIAlertController *alertController = [UIAlertController alertControllerWithTitle: [NSString stringWithFormat:@""] message: @"Deleting the 'Default' profile is not allowed" preferredStyle:UIAlertControllerStyleAlert];
- [alertController addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
[alertController dismissViewControllerAnimated:NO completion:nil];
}]];
[self presentViewController:alertController animated:YES completion:nil];
diff --git a/Limelight/ViewControllers/MainFrameViewController.m b/Limelight/ViewControllers/MainFrameViewController.m
index 0e4f092e..9e00ad1c 100644
--- a/Limelight/ViewControllers/MainFrameViewController.m
+++ b/Limelight/ViewControllers/MainFrameViewController.m
@@ -26,6 +26,7 @@
#import "TemporaryApp.h"
#import "IdManager.h"
#import "ConnectionHelper.h"
+#import "LocalizationHelper.h"
#if !TARGET_OS_TV
#import "SettingsViewController.h"
@@ -63,10 +64,10 @@ static NSMutableSet* hostList;
// Needs to be synchronous to ensure the alert is shown before any potential
// failure callback could be invoked.
dispatch_sync(dispatch_get_main_queue(), ^{
- self->_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing"
- message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@\n\nIf your host PC is running Sunshine, navigate to the Sunshine web UI to enter the PIN.", PIN]
+ self->_pairAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Pairing"]
+ message:[LocalizationHelper localizedStringForKey:@"Enter_PIN_Msg", PIN]
preferredStyle:UIAlertControllerStyleAlert];
- [self->_pairAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) {
+ [self->_pairAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) {
self->_pairAlert = nil;
[self->_discMan startDiscovery];
[self hideLoadingFrame: ^{
@@ -78,11 +79,11 @@ static NSMutableSet* hostList;
}
- (void)displayPairingFailureDialog:(NSString *)message {
- UIAlertController* failedDialog = [UIAlertController alertControllerWithTitle:@"Pairing Failed"
+ UIAlertController* failedDialog = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Pairing Failed"]
message:message
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:failedDialog];
- [failedDialog addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [failedDialog addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
[_discMan startDiscovery];
@@ -124,7 +125,7 @@ static NSMutableSet* hostList;
- (void)enableUpButton {
#if !TARGET_OS_TV
- [self->_upButton setTitle:@"Select New Host"];
+ [self->_upButton setTitle: [LocalizationHelper localizedStringForKey: @"Select New Host"]];
#endif
}
@@ -133,10 +134,10 @@ static NSMutableSet* hostList;
self.title = _selectedHost.name;
}
else if ([hostList count] == 0) {
- self.title = @"Searching for PCs on your network...";
+ self.title = [LocalizationHelper localizedStringForKey: @"Searching for PCs on your network..."] ;
}
else {
- self.title = @"Select Host";
+ self.title = [LocalizationHelper localizedStringForKey: @"Select Host" ];
}
}
@@ -180,11 +181,11 @@ static NSMutableSet* hostList;
return;
}
- UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:@"Connection Interrupted"
+ UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Interrupted"]
message:appListResp.statusMessage
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:applistAlert];
- [applistAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [applistAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
[self hideLoadingFrame: ^{
[self showHostSelectionView];
[[self activeViewController] presentViewController:applistAlert animated:YES completion:nil];
@@ -317,11 +318,11 @@ static NSMutableSet* hostList;
}
- (void)displayDnsFailedDialog {
- UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Network Error"
- message:@"Failed to resolve host."
+ UIAlertController* alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Network Error"]
+ message:[LocalizationHelper localizedStringForKey:@"Failed to resolve host."]
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:alert];
- [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [alert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
[[self activeViewController] presentViewController:alert animated:YES completion:nil];
}
@@ -390,11 +391,11 @@ static NSMutableSet* hostList;
return;
}
- UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
+ UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Failed"]
message:serverInfoResp.statusMessage
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:applistAlert];
- [applistAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [applistAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
// Only display an alert if this was the result of a real
// user action, not just passively entering the foreground again
@@ -456,15 +457,15 @@ static NSMutableSet* hostList;
case StateOnline:
if (host.pairState == PairStatePaired) {
- message = @"Online - Paired";
+ message = [LocalizationHelper localizedStringForKey:@"Online - Paired"];
}
else {
- message = @"Online - Not Paired";
+ message = [LocalizationHelper localizedStringForKey:@"Online - Not Paired"];
}
break;
case StateUnknown:
- message = @"Connecting";
+ message = [LocalizationHelper localizedStringForKey:@"Connecting"];
break;
default:
@@ -473,35 +474,35 @@ static NSMutableSet* hostList;
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:message preferredStyle:UIAlertControllerStyleActionSheet];
if (host.state != StateOnline) {
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"Wake PC" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
- UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:@"Wake-On-LAN" message:@"" preferredStyle:UIAlertControllerStyleAlert];
- [wolAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Wake PC"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Wake-On-LAN"] message:@"" preferredStyle:UIAlertControllerStyleAlert];
+ [wolAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
if (host.mac == nil || [host.mac isEqualToString:@"00:00:00:00:00:00"]) {
- wolAlert.message = @"Host MAC unknown, unable to send WOL Packet";
+ wolAlert.message = [LocalizationHelper localizedStringForKey: @"Host MAC unknown, unable to send WOL Packet"];
} else {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[WakeOnLanManager wakeHost:host];
});
- wolAlert.message = @"Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN.";
+ wolAlert.message = [LocalizationHelper localizedStringForKey:@"Successfully sent wake-up request. It may take a few moments for the PC to wake. If it never wakes up, ensure it's properly configured for Wake-on-LAN."];
}
[[self activeViewController] presentViewController:wolAlert animated:YES completion:nil];
}]];
}
else if (host.pairState == PairStatePaired) {
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"View All Apps" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"View All Apps"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
self->_showHiddenApps = YES;
[self hostClicked:host view:view];
}]];
#if !TARGET_OS_TV
if (host.isNvidiaServerSoftware) {
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"NVIDIA GameStream End-of-Service" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"NVIDIA GameStream End-of-Service"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[Utils launchUrl:@"https://github.com/moonlight-stream/moonlight-docs/wiki/NVIDIA-GameStream-End-Of-Service-Announcement-FAQ"];
}]];
}
#endif
}
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"Test Network" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) {
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Test Network"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action) {
[self showLoadingFrame:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// Perform the network test on a GCD worker thread. It may take a while.
@@ -511,19 +512,19 @@ static NSMutableSet* hostList;
NSString* message;
if (portTestResult == 0) {
- message = @"This network does not appear to be blocking Moonlight. If you still have trouble connecting, check your PC's firewall settings.\n\nVisit the Moonlight Setup Guide on GitHub for additional setup help and troubleshooting steps.";
+ message = [LocalizationHelper localizedStringForKey:@"NetTestOK"];
}
else if (portTestResult == ML_TEST_RESULT_INCONCLUSIVE) {
- message = @"The network test could not be performed because none of Moonlight's connection testing servers were reachable. Check your Internet connection or try again later.";
+ message = [LocalizationHelper localizedStringForKey:@"ML_TEST_RESULT_INCONCLUSIVE"];
}
else {
char blockedPorts[512];
LiStringifyPortFlags(portTestResult, "\n", blockedPorts, sizeof(blockedPorts));
- message = [NSString stringWithFormat:@"Your current network connection seems to be blocking Moonlight. Streaming may not work while connected to this network.\n\nThe following network ports were blocked:\n%s", blockedPorts];
+ message = [LocalizationHelper localizedStringForKey:@"NetTestFailed", blockedPorts];
}
- UIAlertController* netTestAlert = [UIAlertController alertControllerWithTitle:@"Network Test Complete" message:message preferredStyle:UIAlertControllerStyleAlert];
- [netTestAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ UIAlertController* netTestAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Network Test Complete"] message:message preferredStyle:UIAlertControllerStyleAlert];
+ [netTestAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
[[self activeViewController] presentViewController:netTestAlert animated:YES completion:nil];
}];
});
@@ -532,15 +533,15 @@ static NSMutableSet* hostList;
}]];
#if !TARGET_OS_TV
if (host.state != StateOnline) {
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"NVIDIA GameStream End-of-Service" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"NVIDIA GameStream End-of-Service"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[Utils launchUrl:@"https://github.com/moonlight-stream/moonlight-docs/wiki/NVIDIA-GameStream-End-Of-Service-Announcement-FAQ"];
}]];
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"Connection Help" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Help"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[Utils launchUrl:@"https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting"];
}]];
}
#endif
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"Remove Host" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) {
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Remove Host"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) {
[self->_discMan removeHostFromDiscovery:host];
DataManager* dataMan = [[DataManager alloc] init];
[dataMan removeHost:host];
@@ -550,7 +551,7 @@ static NSMutableSet* hostList;
}
}]];
- [longClickAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
+ [longClickAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]];
// these two lines are required for iPad support of UIAlertSheet
longClickAlert.popoverPresentationController.sourceView = view;
@@ -561,9 +562,9 @@ static NSMutableSet* hostList;
- (void) addHostClicked {
Log(LOG_D, @"Clicked add host");
- UIAlertController* alertController = [UIAlertController alertControllerWithTitle:@"Add Host Manually" message:@"If Moonlight doesn't find your local gaming PC automatically,\nenter the IP address of your PC" preferredStyle:UIAlertControllerStyleAlert];
- [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
- [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ UIAlertController* alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Add Host Manually"] message:[LocalizationHelper localizedStringForKey:@"If Moonlight doesn't find your local gaming PC automatically, enter the IP address of your PC"] preferredStyle:UIAlertControllerStyleAlert];
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]];
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
NSString* hostAddress = [((UITextField*)[[alertController textFields] objectAtIndex:0]).text trim];
[self showLoadingFrame:^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
@@ -581,12 +582,12 @@ static NSMutableSet* hostList;
unsigned int portTestResults = LiTestClientConnectivity(CONN_TEST_SERVER, 443,
ML_PORT_FLAG_TCP_47984 | ML_PORT_FLAG_TCP_47989);
if (portTestResults != ML_TEST_RESULT_INCONCLUSIVE && portTestResults != 0) {
- error = [error stringByAppendingString:@"\n\nYour device's network connection is blocking Moonlight. Streaming may not work while connected to this network."];
+ error = [error stringByAppendingString:[LocalizationHelper localizedStringForKey:@"!ML_TEST_RESULT_INCONCLUSIVE"]];
}
- UIAlertController* hostNotFoundAlert = [UIAlertController alertControllerWithTitle:@"Add Host Manually" message:error preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController* hostNotFoundAlert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Add Host Manually"] message:error preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:hostNotFoundAlert];
- [hostNotFoundAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [hostNotFoundAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[self hideLoadingFrame:^{
[[self activeViewController] presentViewController:hostNotFoundAlert animated:YES completion:nil];
@@ -729,7 +730,7 @@ static NSMutableSet* hostList;
}
}
else {
- message = [NSString stringWithFormat:@"%@ is currently running", currentApp.name];
+ message = [LocalizationHelper localizedStringForKey:@"%@ is currently running", currentApp.name];
}
UIAlertController* alertController = [UIAlertController
@@ -738,7 +739,7 @@ static NSMutableSet* hostList;
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction
- actionWithTitle:currentApp == nil ? @"Launch App" : ([app.id isEqualToString:currentApp.id] ? @"Resume App" : @"Resume Running App") style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ actionWithTitle:currentApp == nil ? [LocalizationHelper localizedStringForKey:@"Launch App"] : ([app.id isEqualToString:currentApp.id] ? [LocalizationHelper localizedStringForKey: @"Resume App"] : [LocalizationHelper localizedStringForKey: @"Resume Running App"]) style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
if (currentApp != nil) {
Log(LOG_I, @"Resuming application: %@", currentApp.name);
[self prepareToStreamApp:currentApp];
@@ -753,7 +754,7 @@ static NSMutableSet* hostList;
if (currentApp != nil) {
[alertController addAction:[UIAlertAction actionWithTitle:
- [app.id isEqualToString:currentApp.id] ? @"Quit App" : @"Quit Running App and Start" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
+ [app.id isEqualToString:currentApp.id] ? [LocalizationHelper localizedStringForKey:@"Quit App"] : [LocalizationHelper localizedStringForKey:@"Quit Running App and Start"] style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
Log(LOG_I, @"Quitting application: %@", currentApp.name);
[self showLoadingFrame: ^{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
@@ -783,11 +784,10 @@ static NSMutableSet* hostList;
// If it fails, display an error and stop the current operation
if (quitResponse.statusCode != 200) {
- UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Quitting App Failed"
- message:@"Failed to quit app. If this app was started by "
- "another device, you'll need to quit from that device."
+ UIAlertController* alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Quitting App Failed"]
+ message:[LocalizationHelper localizedStringForKey:@"Failed to quit app. If this app was started by another device, you'll need to quit from that device."]
preferredStyle:UIAlertControllerStyleAlert];
- [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ [alert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[self updateAppsForHost:app.host];
[self hideLoadingFrame: ^{
@@ -818,7 +818,7 @@ static NSMutableSet* hostList;
}
if (currentApp == nil || ![app.id isEqualToString:currentApp.id] || app.hidden) {
- [alertController addAction:[UIAlertAction actionWithTitle:app.hidden ? @"Show App" : @"Hide App"
+ [alertController addAction:[UIAlertAction actionWithTitle:app.hidden ? [LocalizationHelper localizedStringForKey: @"Show App"] : [LocalizationHelper localizedStringForKey: @"Hide App"]
style:app.hidden ? UIAlertActionStyleDefault : UIAlertActionStyleDestructive
handler:^(UIAlertAction* action) {
app.hidden = !app.hidden;
@@ -829,7 +829,7 @@ static NSMutableSet* hostList;
}]];
}
- [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:nil]];
// these two lines are required for iPad support of UIAlertSheet
alertController.popoverPresentationController.sourceView = view;
diff --git a/Limelight/ViewControllers/SettingsViewController.m b/Limelight/ViewControllers/SettingsViewController.m
index 82492c63..bff1bde2 100644
--- a/Limelight/ViewControllers/SettingsViewController.m
+++ b/Limelight/ViewControllers/SettingsViewController.m
@@ -14,6 +14,8 @@
#import
#import
+#import "LocalizationHelper.h"
+
@implementation SettingsViewController {
NSInteger _bitrate;
NSInteger _lastSelectedResolutionIndex;
@@ -21,7 +23,7 @@
@dynamic overrideUserInterfaceStyle;
-static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
+//static NSString* bitrateFormat;
static const int bitrateTable[] = {
500,
1000,
@@ -151,7 +153,7 @@ BOOL isCustomResolution(CGSize res) {
- (void)viewDidLoad {
[super viewDidLoad];
-
+
// Always run settings in dark mode because we want the light fonts
if (@available(iOS 13.0, tvOS 13.0, *)) {
self.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
@@ -256,7 +258,7 @@ BOOL isCustomResolution(CGSize res) {
if (!VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC) || !(AVPlayer.availableHDRModes & AVPlayerHDRModeHDR10)) {
[self.hdrSelector removeAllSegments];
- [self.hdrSelector insertSegmentWithTitle:@"Unsupported on this device" atIndex:0 animated:NO];
+ [self.hdrSelector insertSegmentWithTitle:[LocalizationHelper localizedStringForKey:@"Unsupported on this device"] atIndex:0 animated:NO];
[self.hdrSelector setEnabled:NO];
}
else {
@@ -292,12 +294,12 @@ BOOL isCustomResolution(CGSize res) {
if(currentSettings.touchMode.intValue == RELATIVE_TOUCH_MODE){
[self.keyboardToggleFingerNumSlider setEnabled:[self.touchModeSelector selectedSegmentIndex] != RELATIVE_TOUCH_MODE];
[self.keyboardToggleFingerNumSlider setValue:3.0]; //force 3 finger tap to toggle keyboard in relative touch mode. This is for the 4 finger OSC layout tool gesture.
- [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]];
+ [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]];
}
else{
[self.keyboardToggleFingerNumSlider setValue:(CGFloat)currentSettings.keyboardToggleFingers.intValue animated:YES]; // Load old setting. old setting was converted to uint16_t before saving.
- if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Tap-Toggle Local Keyboard Disabled"]]; // Initiate label display. Allow higher required finger number to completely disable keyboard toggle
- else [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
+ if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"Tap-Toggle Local Keyboard Disabled"]]; // Initiate label display. Allow higher required finger number to completely disable keyboard toggle
+ else [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
}
[self.keyboardToggleFingerNumSlider addTarget:self action:@selector(keyboardToggleFingerNumSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
@@ -310,24 +312,24 @@ BOOL isCustomResolution(CGSize res) {
// swipe & exit setting
[self.swipeExitScreenEdgeSelector setSelectedSegmentIndex:[self getSelectorIndexFromScreenEdge:(uint32_t)currentSettings.swipeExitScreenEdge.integerValue]]; // Load old setting
[self.swipeToExitDistanceSlider setValue:(CGFloat)currentSettings.swipeToExitDistance.floatValue animated:YES]; // Load old setting.
- [self.swipeToExitDistanceUILabel setText:[NSString stringWithFormat:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]]; // Initiate label display
+ [self.swipeToExitDistanceUILabel setText:[LocalizationHelper localizedStringForKey:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]]; // Initiate label display
[self.swipeToExitDistanceSlider addTarget:self action:@selector(swipeToExitDistanceSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
// pointer veloc setting
[self.pointerVelocityModeDividerSlider setValue:currentSettings.pointerVelocityModeDivider.floatValue * 100 animated:YES]; // Load old setting.
- [self.pointerVelocityModeDividerUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]]; // Initiate label display
+ [self.pointerVelocityModeDividerUILabel setText:[LocalizationHelper localizedStringForKey:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]]; // Initiate label display
[self.pointerVelocityModeDividerSlider addTarget:self action:@selector(pointerVelocityModeDividerSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self.pointerVelocityModeDividerSlider setEnabled: currentSettings.touchMode.intValue == NATIVE_TOUCH_MODE]; // pointer velocity scaling works only in native touch mode.
// init pointer veloc setting
[self.touchPointerVelocityFactorSlider setValue:currentSettings.touchPointerVelocityFactor.floatValue * 100 animated:YES]; // Load old setting.
- [self.touchPointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Initiate label display
+ [self.touchPointerVelocityFactorUILabel setText:[LocalizationHelper localizedStringForKey: @"Touch Pointer Velocity: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Initiate label display
[self.touchPointerVelocityFactorSlider addTarget:self action:@selector(touchPointerVelocityFactorSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self.touchPointerVelocityFactorSlider setEnabled: currentSettings.touchMode.intValue == NATIVE_TOUCH_MODE]; // pointer velocity scaling works only in native touch mode.
// init relative touch mouse pointer veloc setting
[self.mousePointerVelocityFactorSlider setValue:currentSettings.mousePointerVelocityFactor.floatValue * 100 animated:YES]; // Load old setting.
- [self.mousePointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Mouse Pointer Velocity: %d%%", (uint16_t)self.mousePointerVelocityFactorSlider.value]]; // Initiate label display
+ [self.mousePointerVelocityFactorUILabel setText:[LocalizationHelper localizedStringForKey: @"Mouse Pointer Velocity: %d%%", (uint16_t)self.mousePointerVelocityFactorSlider.value]]; // Initiate label display
[self.mousePointerVelocityFactorSlider addTarget:self action:@selector(mousePointerVelocityFactorSliderMoved) forControlEvents:(UIControlEventValueChanged)]; // Update label display when slider is being moved.
[self.mousePointerVelocityFactorSlider setEnabled: currentSettings.touchMode.intValue == RELATIVE_TOUCH_MODE]; // mouse velocity scaling works only in relative touch mode.
@@ -347,20 +349,20 @@ BOOL isCustomResolution(CGSize res) {
self.layoutOnScreenControlsVC.modalPresentationStyle = UIModalPresentationFullScreen;
}
if(currentSettings.onscreenControls.intValue == OnScreenControlsCustom && currentSettings.touchMode.intValue == RELATIVE_TOUCH_MODE) { //load OSC slider UI Lable to remind user:
- [self.onscreenControllerLabel setText:@"Tap 4 Fingers to Change OSC Layout in Stream View"]; //keyboard is force set to 3 finger to make this working.
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"Tap 4 Fingers to Change OSC Layout in Stream View"]]; //keyboard is force set to 3 finger to make this working.
//if (self.layoutOnScreenControlsVC.isBeingPresented == NO)
}
else{
- [self.onscreenControllerLabel setText:@"On-Screen Controls"];
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"On-Screen Controls"]];
}
}
- (void)showCustomOSCTip {
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Rebase in Stream View"
- message:@"Tap 4 fingers to change on-screen controller layout in stream view ~"
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Rebase in Stream View"]
+ message:[LocalizationHelper localizedStringForKey:@"Tap 4 fingers to change on-screen controller layout in stream view"]
preferredStyle:UIAlertControllerStyleAlert];
- UIAlertAction *okAction = [UIAlertAction actionWithTitle:@"Got it!"
+ UIAlertAction *okAction = [UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey: @"Got it!"]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
// Continue execution after the alert is dismissed
@@ -386,12 +388,12 @@ BOOL isCustomResolution(CGSize res) {
}
if([self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsCustom && [self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH_MODE) {
- [self.onscreenControllerLabel setText:@"Tap 4 Fingers to Change OSC Layout in Stream View"];
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"Tap 4 Fingers to Change OSC Layout in Stream View"]];
[self showCustomOSCTip];
//if (self.layoutOnScreenControlsVC.isBeingPresented == NO)
}
else{
- [self.onscreenControllerLabel setText:@"On-Screen Controls"];
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"On-Screen Controls"]];
}
}
@@ -401,15 +403,15 @@ BOOL isCustomResolution(CGSize res) {
- (void) pointerVelocityModeDividerSliderMoved {
- [self.pointerVelocityModeDividerUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]];
+ [self.pointerVelocityModeDividerUILabel setText:[LocalizationHelper localizedStringForKey:@"Touch Pointer Velocity: Scaled on %d%% of Right Screen", 100 - (uint8_t)self.pointerVelocityModeDividerSlider.value]];
}
- (void) touchPointerVelocityFactorSliderMoved {
- [self.touchPointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Touch Pointer Velocity: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Update label display
+ [self.touchPointerVelocityFactorUILabel setText:[LocalizationHelper localizedStringForKey: @"Touch Pointer Velocity: %d%%", (uint16_t)self.touchPointerVelocityFactorSlider.value]]; // Update label display
}
- (void) mousePointerVelocityFactorSliderMoved {
- [self.mousePointerVelocityFactorUILabel setText:[NSString stringWithFormat:@"Mouse Pointer Velocity: %d%%", (uint16_t)self.mousePointerVelocityFactorSlider.value]]; // Update label display
+ [self.mousePointerVelocityFactorUILabel setText:[LocalizationHelper localizedStringForKey: @"Mouse Pointer Velocity: %d%%", (uint16_t)self.mousePointerVelocityFactorSlider.value]]; // Update label display
}
- (uint32_t) getScreenEdgeFromSelector {
@@ -442,15 +444,15 @@ BOOL isCustomResolution(CGSize res) {
[self.keyboardToggleFingerNumSlider setEnabled:[self.touchModeSelector selectedSegmentIndex] != RELATIVE_TOUCH_MODE];
if([self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH_MODE) {
[self.keyboardToggleFingerNumSlider setValue:3.0];
- [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]];
+ [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]];
}
if([self.onscreenControlSelector selectedSegmentIndex] == OnScreenControlsCustom && [self.touchModeSelector selectedSegmentIndex] == RELATIVE_TOUCH_MODE) {
- [self.onscreenControllerLabel setText:@"Tap 4 Fingers to Change OSC Layout in Stream View"];
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"Tap 4 Fingers to Change OSC Layout in Stream View"]];
//if (self.layoutOnScreenControlsVC.isBeingPresented == NO)
}
else{
- [self.onscreenControllerLabel setText:@"On-Screen Controls"];
+ [self.onscreenControllerLabel setText:[LocalizationHelper localizedStringForKey: @"On-Screen Controls"]];
}
}
@@ -529,10 +531,10 @@ BOOL isCustomResolution(CGSize res) {
}
- (void) promptCustomResolutionDialog {
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Enter Custom Resolution" message:nil preferredStyle:UIAlertControllerStyleAlert];
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey: @"Enter Custom Resolution"] message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
- textField.placeholder = @"Video Width";
+ textField.placeholder = [LocalizationHelper localizedStringForKey:@"Video Width"];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.keyboardType = UIKeyboardTypeNumberPad;
@@ -546,7 +548,7 @@ BOOL isCustomResolution(CGSize res) {
}];
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
- textField.placeholder = @"Video Height";
+ textField.placeholder = [LocalizationHelper localizedStringForKey:@"Video Height"];
textField.clearButtonMode = UITextFieldViewModeAlways;
textField.borderStyle = UITextBorderStyleRoundedRect;
textField.keyboardType = UIKeyboardTypeNumberPad;
@@ -559,7 +561,7 @@ BOOL isCustomResolution(CGSize res) {
}
}];
- [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
NSArray * textfields = alertController.textFields;
UITextField *widthField = textfields[0];
UITextField *heightField = textfields[1];
@@ -594,12 +596,12 @@ BOOL isCustomResolution(CGSize res) {
[self updateResolutionDisplayViewText];
self->_lastSelectedResolutionIndex = [self.resolutionSelector selectedSegmentIndex];
- UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"Custom Resolution Selected" message: @"Custom resolutions are not officially supported by GeForce Experience, so it will not set your host display resolution. You will need to set it manually while in game.\n\nResolutions that are not supported by your client or host PC may cause streaming errors." preferredStyle:UIAlertControllerStyleAlert];
- [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
+ UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Custom Resolution Selected"] message: [LocalizationHelper localizedStringForKey:@"Custom resolutions are not officially supported by GeForce Experience, so it will not set your host display resolution. You will need to set it manually while in game.\n\nResolutions that are not supported by your client or host PC may cause streaming errors."] preferredStyle:UIAlertControllerStyleAlert];
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}]];
- [alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
+ [alertController addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Cancel"] style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
// Restore the previous selection
[self.resolutionSelector setSelectedSegmentIndex:self->_lastSelectedResolutionIndex];
}]];
@@ -626,7 +628,7 @@ BOOL isCustomResolution(CGSize res) {
[subview removeFromSuperview];
}
UILabel *label1 = [[UILabel alloc] init];
- label1.text = @"Set PC/Game resolution: ";
+ label1.text = [LocalizationHelper localizedStringForKey:@"Set PC/Game resolution:"];
label1.font = [UIFont systemFontOfSize:fontSize];
[label1 sizeToFit];
label1.frame = CGRectMake(padding, (viewFrameHeight - label1.frame.size.height) / 2, label1.frame.size.width, label1.frame.size.height);
@@ -641,12 +643,12 @@ BOOL isCustomResolution(CGSize res) {
}
- (void) keyboardToggleFingerNumSliderMoved{
- if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"Local Keyboard Toggle Disabled"]];
- else [self.keyboardToggleFingerNumLabel setText:[NSString stringWithFormat:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
+ if (self.keyboardToggleFingerNumSlider.value > 10.5f) [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"Local Keyboard Toggle Disabled"]];
+ else [self.keyboardToggleFingerNumLabel setText:[LocalizationHelper localizedStringForKey:@"To Toggle Local Keyboard: Tap %d Fingers", (uint16_t)self.keyboardToggleFingerNumSlider.value]]; // Initiate label display
}
- (void) swipeToExitDistanceSliderMoved{
- [self.swipeToExitDistanceUILabel setText:[NSString stringWithFormat:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]];
+ [self.swipeToExitDistanceUILabel setText:[LocalizationHelper localizedStringForKey:@"Swipe & Exit Distance: %.2f * screen-width", self.swipeToExitDistanceSlider.value]];
}
- (void) bitrateSliderMoved {
@@ -657,7 +659,7 @@ BOOL isCustomResolution(CGSize res) {
- (void) updateBitrateText {
// Display bitrate in Mbps
- [self.bitrateLabel setText:[NSString stringWithFormat:bitrateFormat, _bitrate / 1000.]];
+ [self.bitrateLabel setText:[LocalizationHelper localizedStringForKey:@"Bitrate: %.1f Mbps", _bitrate / 1000.]];
}
- (NSInteger) getChosenFrameRate {
diff --git a/Limelight/ViewControllers/StreamFrameViewController.m b/Limelight/ViewControllers/StreamFrameViewController.m
index 8d38b68b..59a9b818 100644
--- a/Limelight/ViewControllers/StreamFrameViewController.m
+++ b/Limelight/ViewControllers/StreamFrameViewController.m
@@ -14,6 +14,7 @@
#import "DataManager.h"
#import "CustomEdgeSwipeGestureRecognizer.h"
#import "CustomTapGestureRecognizer.h"
+#import "LocalizationHelper.h"
#include
#include
@@ -174,7 +175,7 @@
#if TARGET_OS_TV
[_tipLabel setText:@"Tip: Tap the Play/Pause button on the Apple TV Remote to disconnect from your PC"];
#else
- [_tipLabel setText:@"Tip: Swipe from screen edge (configured by Swipe & Exit settings) to disconnect from your PC"];
+ [_tipLabel setText:[LocalizationHelper localizedStringForKey:@"Tip: Swipe from screen edge to a certiain distance (configured by Swipe & Exit settings) to disconnect from your PC"]];
#endif
[_tipLabel sizeToFit];
@@ -453,7 +454,7 @@
NSString* message;
if (portTestResults != ML_TEST_RESULT_INCONCLUSIVE && portTestResults != 0) {
- title = @"Connection Error";
+ title = [LocalizationHelper localizedStringForKey:@"Connection Error"];
message = @"Your device's network connection is blocking Moonlight. Streaming may not work while connected to this network.";
}
else {
@@ -463,28 +464,28 @@
return;
case ML_ERROR_NO_VIDEO_TRAFFIC:
- title = @"Connection Error";
- message = @"No video received from host.";
+ title = [LocalizationHelper localizedStringForKey:@"Connection Error"];
+ message = [LocalizationHelper localizedStringForKey:@"No video received from host."];
if (portFlags != 0) {
char failingPorts[256];
LiStringifyPortFlags(portFlags, "\n", failingPorts, sizeof(failingPorts));
- message = [message stringByAppendingString:[NSString stringWithFormat:@"\n\nCheck your firewall and port forwarding rules for port(s):\n%s", failingPorts]];
+ message = [message stringByAppendingString:[LocalizationHelper localizedStringForKey:@"ConnectionFailedFirewall", failingPorts]];
}
break;
case ML_ERROR_NO_VIDEO_FRAME:
- title = @"Connection Error";
- message = @"Your network connection isn't performing well. Reduce your video bitrate setting or try a faster connection.";
+ title = [LocalizationHelper localizedStringForKey:@"Connection Error"];
+ message = [LocalizationHelper localizedStringForKey: @"Your network connection isn't performing well. Reduce your video bitrate setting or try a faster connection."];
break;
case ML_ERROR_UNEXPECTED_EARLY_TERMINATION:
case ML_ERROR_PROTECTED_CONTENT:
- title = @"Connection Error";
+ title = [LocalizationHelper localizedStringForKey:@"Connection Error"];
message = @"Something went wrong on your host PC when starting the stream.\n\nMake sure you don't have any DRM-protected content open on your host PC. You can also try restarting your host PC.\n\nIf the issue persists, try reinstalling your GPU drivers and GeForce Experience.";
break;
case ML_ERROR_FRAME_CONVERSION:
- title = @"Connection Error";
+ title = [LocalizationHelper localizedStringForKey:@"Connection Error"];
message = @"The host PC reported a fatal video encoding error.\n\nTry disabling HDR mode, changing the streaming resolution, or changing your host PC's display resolution.";
break;
@@ -500,8 +501,8 @@
errorString = [NSString stringWithFormat:@"%d", errorCode];
}
- title = @"Connection Terminated";
- message = [NSString stringWithFormat: @"The connection was terminated\n\nError code: %@", errorString];
+ title = [LocalizationHelper localizedStringForKey: @"Connection Terminated"];
+ message = [LocalizationHelper localizedStringForKey: @"The connection was terminated, Error code: %@", errorString];
break;
}
}
@@ -511,7 +512,7 @@
message:message
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:conTermAlert];
- [conTermAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [conTermAlert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:conTermAlert animated:YES completion:nil];
@@ -523,7 +524,7 @@
- (void) stageStarting:(const char*)stageName {
Log(LOG_I, @"Starting %s", stageName);
dispatch_async(dispatch_get_main_queue(), ^{
- NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
+ NSString* lowerCase = [NSString stringWithFormat:@"%s ...", stageName];
NSString* titleCase = [[[lowerCase substringToIndex:1] uppercaseString] stringByAppendingString:[lowerCase substringFromIndex:1]];
[self->_stageLabel setText:titleCase];
[self->_stageLabel sizeToFit];
@@ -547,17 +548,17 @@
if (portTestFlags != 0) {
char failingPorts[256];
LiStringifyPortFlags(portTestFlags, "\n", failingPorts, sizeof(failingPorts));
- message = [message stringByAppendingString:[NSString stringWithFormat:@"\n\nCheck your firewall and port forwarding rules for port(s):\n%s", failingPorts]];
+ message = [message stringByAppendingString:[LocalizationHelper localizedStringForKey:@"ConnectionFailedFirewall", failingPorts]];
}
if (portTestResults != ML_TEST_RESULT_INCONCLUSIVE && portTestResults != 0) {
- message = [message stringByAppendingString:@"\n\nYour device's network connection is blocking Moonlight. Streaming may not work while connected to this network."];
+ message = [message stringByAppendingString:[LocalizationHelper localizedStringForKey:@"!ML_TEST_RESULT_INCONCLUSIVE"]];
}
- UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
+ UIAlertController* alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Failed"]
message:message
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:alert];
- [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [alert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
@@ -573,11 +574,11 @@
// Allow the display to go to sleep now
[UIApplication sharedApplication].idleTimerDisabled = NO;
- UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Error"
+ UIAlertController* alert = [UIAlertController alertControllerWithTitle:[LocalizationHelper localizedStringForKey:@"Connection Error"]
message:message
preferredStyle:UIAlertControllerStyleAlert];
[Utils addHelpOptionToDialog:alert];
- [alert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
+ [alert addAction:[UIAlertAction actionWithTitle:[LocalizationHelper localizedStringForKey:@"Ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
@@ -624,10 +625,10 @@
case CONN_STATUS_POOR:
if (self->_streamConfig.bitRate > 5000) {
- [self updateOverlayText:@"Slow connection to PC\nReduce your bitrate"];
+ [self updateOverlayText:[LocalizationHelper localizedStringForKey:@"Slow connection to PC, Reduce your bitrate"]];
}
else {
- [self updateOverlayText:@"Poor connection to PC"];
+ [self updateOverlayText:[LocalizationHelper localizedStringForKey:@"Poor connection to PC"]];
}
break;
}
diff --git a/Limelight/mul.lproj/iPad.xcstrings b/Limelight/mul.lproj/iPad.xcstrings
new file mode 100644
index 00000000..27f8113d
--- /dev/null
+++ b/Limelight/mul.lproj/iPad.xcstrings
@@ -0,0 +1,1236 @@
+{
+ "sourceLanguage" : "en",
+ "strings" : {
+ "6w5-Md-NpV.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Preferred Codec \"; ObjectID = \"6w5-Md-NpV\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Preferred Codec "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "视频编解码"
+ }
+ }
+ }
+ },
+ "7va-uJ-IfD.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 7va-uJ-IfD.segmentTitles[0] = \"Lowest Latency\"; ObjectID = \"7va-uJ-IfD\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Lowest Latency"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "低延迟"
+ }
+ }
+ }
+ },
+ "7va-uJ-IfD.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 7va-uJ-IfD.segmentTitles[1] = \"Smoothest Video\"; ObjectID = \"7va-uJ-IfD\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Smoothest Video"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "最高流畅度"
+ }
+ }
+ }
+ },
+ "aFy-0w-YPe.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; aFy-0w-YPe.segmentTitles[0] = \"H.264\"; ObjectID = \"aFy-0w-YPe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "H.264"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "H.264"
+ }
+ }
+ }
+ },
+ "aFy-0w-YPe.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; aFy-0w-YPe.segmentTitles[1] = \"HEVC\"; ObjectID = \"aFy-0w-YPe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "HEVC"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "HEVC"
+ }
+ }
+ }
+ },
+ "aFy-0w-YPe.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; aFy-0w-YPe.segmentTitles[2] = \"AV1\"; ObjectID = \"aFy-0w-YPe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "AV1"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "AV1"
+ }
+ }
+ }
+ },
+ "aFy-0w-YPe.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; aFy-0w-YPe.segmentTitles[3] = \"Auto\"; ObjectID = \"aFy-0w-YPe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "Aiv-r8-9k2.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Frame Rate \"; ObjectID = \"Aiv-r8-9k2\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Frame Rate "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "串流帧率"
+ }
+ }
+ }
+ },
+ "aup-5k-z6P.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Show Local Keyboard Toolbar \"; ObjectID = \"aup-5k-z6P\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Show Local Keyboard Toolbar "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "显示本地软键盘工具栏"
+ }
+ }
+ }
+ },
+ "bFD-Ng-abn.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Multi-Controller Mode \"; ObjectID = \"bFD-Ng-abn\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Multi-Controller Mode "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "多手柄模式"
+ }
+ }
+ }
+ },
+ "Bhn-IO-Wlt.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Cancel\"; ObjectID = \"Bhn-IO-Wlt\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Cancel"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "取消"
+ }
+ }
+ }
+ },
+ "byH-Qz-Nbw.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; byH-Qz-Nbw.segmentTitles[0] = \"No\"; ObjectID = \"byH-Qz-Nbw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "byH-Qz-Nbw.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; byH-Qz-Nbw.segmentTitles[1] = \"Yes\"; ObjectID = \"byH-Qz-Nbw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "bZL-t1-mk7.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"HDR (Beta) \"; ObjectID = \"bZL-t1-mk7\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "HDR (Beta) "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "HDR (测试功能)"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[0] = \"360p\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "360p"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[1] = \"720p\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "720p"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[2] = \"1080p\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "1080p"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[3] = \"4K\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "4K"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[4]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[4] = \"Safe Area\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Safe Area"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "安全区域"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[5]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[5] = \"Full\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Full"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "全屏显示"
+ }
+ }
+ }
+ },
+ "ckc-Dm-8ex.segmentTitles[6]" : {
+ "comment" : "Class = \"UISegmentedControl\"; ckc-Dm-8ex.segmentTitles[6] = \"Custom\"; ObjectID = \"ckc-Dm-8ex\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Custom"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自定义"
+ }
+ }
+ }
+ },
+ "cRV-Xw-CVi.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Current Profile:\"; ObjectID = \"cRV-Xw-CVi\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Current Profile:"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "当前布局: "
+ }
+ }
+ }
+ },
+ "DkI-w6-jku.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Pointer Velocity: Scaled on 0% of Right Screen \"; ObjectID = \"DkI-w6-jku\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Pointer Velocity: Scaled on 0% of Right Screen "
+ }
+ }
+ }
+ },
+ "Dll-7x-18l.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swap A/B and X/Y Buttons \"; ObjectID = \"Dll-7x-18l\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swap A/B and X/Y Buttons "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "交换A/B键、X/Y键位置"
+ }
+ }
+ }
+ },
+ "e4G-id-vjI.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; e4G-id-vjI.segmentTitles[0] = \"Touchpad\"; ObjectID = \"e4G-id-vjI\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touchpad"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "触控板"
+ }
+ }
+ }
+ },
+ "e4G-id-vjI.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; e4G-id-vjI.segmentTitles[1] = \"Native Multi-Touch\"; ObjectID = \"e4G-id-vjI\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Native Multi-Touch"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "原生多点触控"
+ }
+ }
+ }
+ },
+ "e4G-id-vjI.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; e4G-id-vjI.segmentTitles[2] = \"Absolute Touch\"; ObjectID = \"e4G-id-vjI\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Absolute Touch"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "鼠标模式"
+ }
+ }
+ }
+ },
+ "egA-7n-Dpe.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Pointer Velocity: 100% \"; ObjectID = \"egA-7n-Dpe\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Pointer Velocity: 100% "
+ }
+ }
+ }
+ },
+ "egC-9E-zS4.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Delete\"; ObjectID = \"egC-9E-zS4\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Delete"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "删除"
+ }
+ }
+ }
+ },
+ "fXq-oD-MrL.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Play Audio on PC \"; ObjectID = \"fXq-oD-MrL\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Play Audio on PC "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "播放主机端声音"
+ }
+ }
+ }
+ },
+ "h5g-U1-Z2J.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Mode \"; ObjectID = \"h5g-U1-Z2J\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Mode "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "触控模式"
+ }
+ }
+ }
+ },
+ "hm3-EV-h6d.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; hm3-EV-h6d.segmentTitles[0] = \"No\"; ObjectID = \"hm3-EV-h6d\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "hm3-EV-h6d.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; hm3-EV-h6d.segmentTitles[1] = \"Yes\"; ObjectID = \"hm3-EV-h6d\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "IvI-tw-APj.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swipe & Exit Session from: \"; ObjectID = \"IvI-tw-APj\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swipe & Exit Session from: "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "从以下屏幕边缘滑动, 退出远程桌面:"
+ }
+ }
+ }
+ },
+ "KlC-fG-wEi.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; KlC-fG-wEi.segmentTitles[0] = \"Single\"; ObjectID = \"KlC-fG-wEi\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Single"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "单手柄"
+ }
+ }
+ }
+ },
+ "KlC-fG-wEi.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; KlC-fG-wEi.segmentTitles[1] = \"Auto\"; ObjectID = \"KlC-fG-wEi\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "KMg-3j-F9p.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; KMg-3j-F9p.segmentTitles[0] = \"No\"; ObjectID = \"KMg-3j-F9p\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "KMg-3j-F9p.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; KMg-3j-F9p.segmentTitles[1] = \"Yes\"; ObjectID = \"KMg-3j-F9p\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "lcO-6v-Tbg.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; lcO-6v-Tbg.segmentTitles[0] = \"No\"; ObjectID = \"lcO-6v-Tbg\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "lcO-6v-Tbg.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; lcO-6v-Tbg.segmentTitles[1] = \"Yes\"; ObjectID = \"lcO-6v-Tbg\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "lGK-vl-pdw.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; lGK-vl-pdw.segmentTitles[0] = \"30 FPS\"; ObjectID = \"lGK-vl-pdw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "30 FPS"
+ }
+ }
+ }
+ },
+ "lGK-vl-pdw.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; lGK-vl-pdw.segmentTitles[1] = \"60 FPS\"; ObjectID = \"lGK-vl-pdw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "60 FPS"
+ }
+ }
+ }
+ },
+ "lGK-vl-pdw.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; lGK-vl-pdw.segmentTitles[2] = \"120 FPS\"; ObjectID = \"lGK-vl-pdw\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "120 FPS"
+ }
+ }
+ }
+ },
+ "LGV-5y-piG.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"On-Screen Controls \"; ObjectID = \"LGV-5y-piG\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "On-Screen Controls "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "屏幕虚拟手柄"
+ }
+ }
+ }
+ },
+ "lMt-4H-fkV.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Bitrate: 10 Mbps \"; ObjectID = \"lMt-4H-fkV\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Bitrate: 10 Mbps "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "码率: 10Mbps"
+ }
+ }
+ }
+ },
+ "Mm0-xf-9eh.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; Mm0-xf-9eh.segmentTitles[0] = \"Left Screen Edge\"; ObjectID = \"Mm0-xf-9eh\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Left Screen Edge"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "左边缘"
+ }
+ }
+ }
+ },
+ "Mm0-xf-9eh.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; Mm0-xf-9eh.segmentTitles[1] = \"Right Screen Edge\"; ObjectID = \"Mm0-xf-9eh\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Right Screen Edge"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "右边缘"
+ }
+ }
+ }
+ },
+ "Mm0-xf-9eh.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; Mm0-xf-9eh.segmentTitles[2] = \"Either\"; ObjectID = \"Mm0-xf-9eh\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Either"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "左右任意"
+ }
+ }
+ }
+ },
+ "mSL-ru-nRm.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Settings\"; ObjectID = \"mSL-ru-nRm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Settings"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "设置"
+ }
+ }
+ }
+ },
+ "nCO-OT-dV1.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; nCO-OT-dV1.segmentTitles[0] = \"No\"; ObjectID = \"nCO-OT-dV1\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "nCO-OT-dV1.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; nCO-OT-dV1.segmentTitles[1] = \"Yes\"; ObjectID = \"nCO-OT-dV1\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "NLH-qN-qCo.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; NLH-qN-qCo.segmentTitles[0] = \"No\"; ObjectID = \"NLH-qN-qCo\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "NLH-qN-qCo.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; NLH-qN-qCo.segmentTitles[1] = \"Yes\"; ObjectID = \"NLH-qN-qCo\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "OA2-SA-bBO.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; OA2-SA-bBO.segmentTitles[0] = \"No\"; ObjectID = \"OA2-SA-bBO\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "OA2-SA-bBO.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; OA2-SA-bBO.segmentTitles[1] = \"Yes\"; ObjectID = \"OA2-SA-bBO\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "oPM-G6-u5O.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Mouse Pointer Velocity: 100% \"; ObjectID = \"oPM-G6-u5O\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Mouse Pointer Velocity: 100% "
+ }
+ }
+ }
+ },
+ "P34-hO-6cX.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Duplicate\"; ObjectID = \"P34-hO-6cX\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Duplicate"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "复制"
+ }
+ }
+ }
+ },
+ "pMN-6T-aYE.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swipe & Exit Distance: 0.5 * screen-width \"; ObjectID = \"pMN-6T-aYE\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swipe & Exit Distance: 0.5 * screen-width "
+ }
+ }
+ }
+ },
+ "pYZ-GR-EwO.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Resolution \"; ObjectID = \"pYZ-GR-EwO\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Resolution "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "串流分辨率"
+ }
+ }
+ }
+ },
+ "Q2V-XF-4jq.title" : {
+ "comment" : "Class = \"UINavigationItem\"; title = \"OSC Layout Profiles\"; ObjectID = \"Q2V-XF-4jq\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "OSC Layout Profiles"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "虚拟手柄布局文件"
+ }
+ }
+ }
+ },
+ "qSU-wh-tqA.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; qSU-wh-tqA.segmentTitles[0] = \"Off\"; ObjectID = \"qSU-wh-tqA\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Off"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "qSU-wh-tqA.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; qSU-wh-tqA.segmentTitles[1] = \"Auto\"; ObjectID = \"qSU-wh-tqA\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "qSU-wh-tqA.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; qSU-wh-tqA.segmentTitles[2] = \"Simple\"; ObjectID = \"qSU-wh-tqA\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Simple"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "简单"
+ }
+ }
+ }
+ },
+ "qSU-wh-tqA.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; qSU-wh-tqA.segmentTitles[3] = \"Full\"; ObjectID = \"qSU-wh-tqA\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Full"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "完整"
+ }
+ }
+ }
+ },
+ "qSU-wh-tqA.segmentTitles[4]" : {
+ "comment" : "Class = \"UISegmentedControl\"; qSU-wh-tqA.segmentTitles[4] = \"Custom\"; ObjectID = \"qSU-wh-tqA\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Custom"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自定义"
+ }
+ }
+ }
+ },
+ "QYJ-84-bvc.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Lift Stream View for Local Keyboard \"; ObjectID = \"QYJ-84-bvc\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Lift Stream View for Local Keyboard "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "唤醒本地软键盘时, 抬升串流视图"
+ }
+ }
+ }
+ },
+ "s2i-ZL-Gz4.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Statistics Overlay \"; ObjectID = \"s2i-ZL-Gz4\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Statistics Overlay "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "性能数据叠加显示"
+ }
+ }
+ }
+ },
+ "t9f-V8-GCm.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Citrix X1 Mouse Support \"; ObjectID = \"t9f-V8-GCm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Citrix X1 Mouse Support "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "Citrix X1 鼠标支持"
+ }
+ }
+ }
+ },
+ "WDY-9o-6Hb.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WDY-9o-6Hb.segmentTitles[0] = \"No\"; ObjectID = \"WDY-9o-6Hb\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "WDY-9o-6Hb.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WDY-9o-6Hb.segmentTitles[1] = \"Yes\"; ObjectID = \"WDY-9o-6Hb\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "WSI-9V-G6c.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Optimize Game Settings \"; ObjectID = \"WSI-9V-G6c\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Optimize Game Settings "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "优化游戏设置"
+ }
+ }
+ }
+ },
+ "ZWC-Gw-pSq.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Frame Pacing Preference \"; ObjectID = \"ZWC-Gw-pSq\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Frame Pacing Preference "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "needs_review",
+ "value" : "帧间距控制"
+ }
+ }
+ }
+ }
+ },
+ "version" : "1.0"
+}
\ No newline at end of file
diff --git a/Limelight/mul.lproj/iPhone.xcstrings b/Limelight/mul.lproj/iPhone.xcstrings
new file mode 100644
index 00000000..2598df1b
--- /dev/null
+++ b/Limelight/mul.lproj/iPhone.xcstrings
@@ -0,0 +1,1200 @@
+{
+ "sourceLanguage" : "en",
+ "strings" : {
+ "2lg-HW-tku.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2lg-HW-tku.segmentTitles[0] = \"Touchpad\"; ObjectID = \"2lg-HW-tku\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touchpad"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "触控板"
+ }
+ }
+ }
+ },
+ "2lg-HW-tku.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2lg-HW-tku.segmentTitles[1] = \"Native Multi-Touch\"; ObjectID = \"2lg-HW-tku\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Native Multi-Touch"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "原生多点触控"
+ }
+ }
+ }
+ },
+ "2lg-HW-tku.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2lg-HW-tku.segmentTitles[2] = \"Absolute Touch\"; ObjectID = \"2lg-HW-tku\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Absolute Touch"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "鼠标模式"
+ }
+ }
+ }
+ },
+ "2Lx-OY-ZPu.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2Lx-OY-ZPu.segmentTitles[0] = \"Left Screen Edge\"; ObjectID = \"2Lx-OY-ZPu\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Left Screen Edge"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "左边缘"
+ }
+ }
+ }
+ },
+ "2Lx-OY-ZPu.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2Lx-OY-ZPu.segmentTitles[1] = \"Right Screen Edge\"; ObjectID = \"2Lx-OY-ZPu\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Right Screen Edge"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "右边缘"
+ }
+ }
+ }
+ },
+ "2Lx-OY-ZPu.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 2Lx-OY-ZPu.segmentTitles[2] = \"Either\"; ObjectID = \"2Lx-OY-ZPu\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Either"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "左右任意"
+ }
+ }
+ }
+ },
+ "2p1-r1-Gvf.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swap A/B and X/Y Buttons\"; ObjectID = \"2p1-r1-Gvf\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swap A/B and X/Y Buttons"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "交换A/B键、X/Y键位置"
+ }
+ }
+ }
+ },
+ "5pN-Sn-SCN.title" : {
+ "comment" : "Class = \"UINavigationItem\"; title = \"OSC Layout Profiles\"; ObjectID = \"5pN-Sn-SCN\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "OSC Layout Profiles"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "虚拟手柄布局文件"
+ }
+ }
+ }
+ },
+ "6fE-k6-IG0.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 6fE-k6-IG0.segmentTitles[0] = \"No\"; ObjectID = \"6fE-k6-IG0\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "6fE-k6-IG0.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 6fE-k6-IG0.segmentTitles[1] = \"Yes\"; ObjectID = \"6fE-k6-IG0\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "8GA-Js-kQN.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 8GA-Js-kQN.segmentTitles[0] = \"No\"; ObjectID = \"8GA-Js-kQN\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "8GA-Js-kQN.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 8GA-Js-kQN.segmentTitles[1] = \"Yes\"; ObjectID = \"8GA-Js-kQN\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "8kV-xZ-73k.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swipe & Exit Session from:\"; ObjectID = \"8kV-xZ-73k\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swipe & Exit Session from:"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "从以下屏幕边缘滑动, 退出远程桌面:"
+ }
+ }
+ }
+ },
+ "8zy-ri-Dqc.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Resolution\"; ObjectID = \"8zy-ri-Dqc\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Resolution"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流分辨率"
+ }
+ }
+ }
+ },
+ "9xD-GL-9xq.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 9xD-GL-9xq.segmentTitles[0] = \"No\"; ObjectID = \"9xD-GL-9xq\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "9xD-GL-9xq.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; 9xD-GL-9xq.segmentTitles[1] = \"Yes\"; ObjectID = \"9xD-GL-9xq\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "AbS-CW-fjP.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; AbS-CW-fjP.segmentTitles[0] = \"H.264\"; ObjectID = \"AbS-CW-fjP\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "H.264"
+ }
+ }
+ }
+ },
+ "AbS-CW-fjP.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; AbS-CW-fjP.segmentTitles[1] = \"HEVC\"; ObjectID = \"AbS-CW-fjP\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "HEVC"
+ }
+ }
+ }
+ },
+ "AbS-CW-fjP.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; AbS-CW-fjP.segmentTitles[2] = \"AV1\"; ObjectID = \"AbS-CW-fjP\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "AV1"
+ }
+ }
+ }
+ },
+ "AbS-CW-fjP.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; AbS-CW-fjP.segmentTitles[3] = \"Auto\"; ObjectID = \"AbS-CW-fjP\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "BEG-Id-J8y.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Preferred Codec\"; ObjectID = \"BEG-Id-J8y\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Preferred Codec"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "视频编解码"
+ }
+ }
+ }
+ },
+ "bue-hp-CWD.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Duplicate\"; ObjectID = \"bue-hp-CWD\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Duplicate"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "复制"
+ }
+ }
+ }
+ },
+ "c6f-bJ-Vji.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Pointer Velocity: 100% \"; ObjectID = \"c6f-bJ-Vji\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Pointer Velocity: 100% "
+ }
+ }
+ }
+ },
+ "CHp-14-aTt.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Mode\"; ObjectID = \"CHp-14-aTt\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Mode"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "触控模式"
+ }
+ }
+ }
+ },
+ "d2a-Ka-H2c.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; d2a-Ka-H2c.segmentTitles[0] = \"Lowest Latency\"; ObjectID = \"d2a-Ka-H2c\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Lowest Latency"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "低延迟"
+ }
+ }
+ }
+ },
+ "d2a-Ka-H2c.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; d2a-Ka-H2c.segmentTitles[1] = \"Smoothest Video\"; ObjectID = \"d2a-Ka-H2c\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Smoothest Video"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "最高流畅度"
+ }
+ }
+ }
+ },
+ "dLF-qJ-2nY.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; dLF-qJ-2nY.segmentTitles[0] = \"30 FPS\"; ObjectID = \"dLF-qJ-2nY\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "30 FPS"
+ }
+ }
+ }
+ },
+ "dLF-qJ-2nY.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; dLF-qJ-2nY.segmentTitles[1] = \"60 FPS\"; ObjectID = \"dLF-qJ-2nY\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "60 FPS"
+ }
+ }
+ }
+ },
+ "dLF-qJ-2nY.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; dLF-qJ-2nY.segmentTitles[2] = \"120 FPS\"; ObjectID = \"dLF-qJ-2nY\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "120 FPS"
+ }
+ }
+ }
+ },
+ "ecG-dC-PT1.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Mouse Pointer Velocity: 100% \"; ObjectID = \"ecG-dC-PT1\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Mouse Pointer Velocity: 100% "
+ }
+ }
+ }
+ },
+ "Ex1-zI-oAH.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Swipe & Exit Distance: 0.5 * screen-width \"; ObjectID = \"Ex1-zI-oAH\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Swipe & Exit Distance: 0.5 * screen-width "
+ }
+ }
+ }
+ },
+ "ghM-zc-sr6.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Delete\"; ObjectID = \"ghM-zc-sr6\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Delete"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "删除"
+ }
+ }
+ }
+ },
+ "glN-9Q-GKD.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Citrix X1 Mouse Support\"; ObjectID = \"glN-9Q-GKD\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Citrix X1 Mouse Support"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "Citrix X1 鼠标支持"
+ }
+ }
+ }
+ },
+ "Gob-Lu-b1y.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; Gob-Lu-b1y.segmentTitles[0] = \"No\"; ObjectID = \"Gob-Lu-b1y\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "Gob-Lu-b1y.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; Gob-Lu-b1y.segmentTitles[1] = \"Yes\"; ObjectID = \"Gob-Lu-b1y\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "hxa-gT-JXC.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Optimize Game Settings\"; ObjectID = \"hxa-gT-JXC\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Optimize Game Settings"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "优化游戏设置"
+ }
+ }
+ }
+ },
+ "HZT-dd-DuQ.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"On-Screen Controls \"; ObjectID = \"HZT-dd-DuQ\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "On-Screen Controls "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "屏幕虚拟手柄"
+ }
+ }
+ }
+ },
+ "Jps-kj-bYJ.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Multi-Controller Mode\"; ObjectID = \"Jps-kj-bYJ\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Multi-Controller Mode"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "多手柄模式"
+ }
+ }
+ }
+ },
+ "Kkv-DF-MAl.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Frame Rate\"; ObjectID = \"Kkv-DF-MAl\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Frame Rate"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流帧率"
+ }
+ }
+ }
+ },
+ "lBe-dn-yc7.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"HDR (Beta)\"; ObjectID = \"lBe-dn-yc7\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "HDR (Beta)"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "HDR (测试功能)"
+ }
+ }
+ }
+ },
+ "m1k-oE-fIO.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Show Local Keyboard Toolbar\"; ObjectID = \"m1k-oE-fIO\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Show Local Keyboard Toolbar"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "显示本地软键盘工具栏"
+ }
+ }
+ }
+ },
+ "mSL-ru-nRm.title" : {
+ "comment" : "Class = \"UIBarButtonItem\"; title = \"Settings\"; ObjectID = \"mSL-ru-nRm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Settings"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "设置"
+ }
+ }
+ }
+ },
+ "o4O-hO-teB.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; o4O-hO-teB.segmentTitles[0] = \"No\"; ObjectID = \"o4O-hO-teB\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "o4O-hO-teB.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; o4O-hO-teB.segmentTitles[1] = \"Yes\"; ObjectID = \"o4O-hO-teB\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "OCT-oL-Dqb.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; OCT-oL-Dqb.segmentTitles[0] = \"Single\"; ObjectID = \"OCT-oL-Dqb\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Single"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "单手柄"
+ }
+ }
+ }
+ },
+ "OCT-oL-Dqb.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; OCT-oL-Dqb.segmentTitles[1] = \"Auto\"; ObjectID = \"OCT-oL-Dqb\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "P8R-nu-8Ln.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; P8R-nu-8Ln.segmentTitles[0] = \"No\"; ObjectID = \"P8R-nu-8Ln\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "P8R-nu-8Ln.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; P8R-nu-8Ln.segmentTitles[1] = \"Yes\"; ObjectID = \"P8R-nu-8Ln\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[0] = \"360p\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "360p"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[1] = \"720p\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "720p"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[2] = \"1080p\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "1080p"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[3] = \"4K\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "4K"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[4]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[4] = \"Safe Area\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Safe Area"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "安全区域"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[5]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[5] = \"Full\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Full"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "全屏显示"
+ }
+ }
+ }
+ },
+ "PCM-t4-Sha.segmentTitles[6]" : {
+ "comment" : "Class = \"UISegmentedControl\"; PCM-t4-Sha.segmentTitles[6] = \"Custom\"; ObjectID = \"PCM-t4-Sha\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Custom"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自定义"
+ }
+ }
+ }
+ },
+ "pQE-vU-Nr7.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; pQE-vU-Nr7.segmentTitles[0] = \"No\"; ObjectID = \"pQE-vU-Nr7\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "pQE-vU-Nr7.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; pQE-vU-Nr7.segmentTitles[1] = \"Yes\"; ObjectID = \"pQE-vU-Nr7\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "rdz-eg-2oR.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; rdz-eg-2oR.segmentTitles[0] = \"No\"; ObjectID = \"rdz-eg-2oR\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "No"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "rdz-eg-2oR.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; rdz-eg-2oR.segmentTitles[1] = \"Yes\"; ObjectID = \"rdz-eg-2oR\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Yes"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "启用"
+ }
+ }
+ }
+ },
+ "SBv-Wn-LB7.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Bitrate: 10 Mbps \"; ObjectID = \"SBv-Wn-LB7\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Bitrate: 10 Mbps "
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "串流码率: 10Mbps"
+ }
+ }
+ }
+ },
+ "T6M-nz-TW0.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Play Audio on PC\"; ObjectID = \"T6M-nz-TW0\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Play Audio on PC"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "播放主机端声音"
+ }
+ }
+ }
+ },
+ "VlN-ZW-1gm.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Touch Pointer Velocity: Scaled on 0% of Right Screen \"; ObjectID = \"VlN-ZW-1gm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Touch Pointer Velocity: Scaled on 0% of Right Screen "
+ }
+ }
+ }
+ },
+ "WGf-9d-eAm.segmentTitles[0]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[0] = \"Off\"; ObjectID = \"WGf-9d-eAm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Off"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "关闭"
+ }
+ }
+ }
+ },
+ "WGf-9d-eAm.segmentTitles[1]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[1] = \"Auto\"; ObjectID = \"WGf-9d-eAm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Auto"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自动"
+ }
+ }
+ }
+ },
+ "WGf-9d-eAm.segmentTitles[2]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[2] = \"Simple\"; ObjectID = \"WGf-9d-eAm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Simple"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "简单"
+ }
+ }
+ }
+ },
+ "WGf-9d-eAm.segmentTitles[3]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[3] = \"Full\"; ObjectID = \"WGf-9d-eAm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Full"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "完整"
+ }
+ }
+ }
+ },
+ "WGf-9d-eAm.segmentTitles[4]" : {
+ "comment" : "Class = \"UISegmentedControl\"; WGf-9d-eAm.segmentTitles[4] = \"Custom\"; ObjectID = \"WGf-9d-eAm\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Custom"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "自定义"
+ }
+ }
+ }
+ },
+ "WtB-ib-ZDj.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Statistics Overlay\"; ObjectID = \"WtB-ib-ZDj\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Statistics Overlay"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "性能数据叠加显示"
+ }
+ }
+ }
+ },
+ "wUg-MH-aae.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Lift Stream View for Local Keyboard\"; ObjectID = \"wUg-MH-aae\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Lift Stream View for Local Keyboard"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "唤醒本地软键盘时, 抬升串流视图"
+ }
+ }
+ }
+ },
+ "x1l-m4-eAM.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Frame Pacing Preference\"; ObjectID = \"x1l-m4-eAM\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Frame Pacing Preference"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "帧间距控制"
+ }
+ }
+ }
+ },
+ "yJC-bq-EOU.text" : {
+ "comment" : "Class = \"UILabel\"; text = \"Current Profile:\"; ObjectID = \"yJC-bq-EOU\";",
+ "extractionState" : "extracted_with_value",
+ "localizations" : {
+ "en" : {
+ "stringUnit" : {
+ "state" : "new",
+ "value" : "Current Profile:"
+ }
+ },
+ "zh-Hans" : {
+ "stringUnit" : {
+ "state" : "translated",
+ "value" : "当前布局:"
+ }
+ }
+ }
+ }
+ },
+ "version" : "1.0"
+}
\ No newline at end of file
diff --git a/Moonlight.xcodeproj/project.pbxproj b/Moonlight.xcodeproj/project.pbxproj
index e4b8c763..6ce44d9c 100644
--- a/Moonlight.xcodeproj/project.pbxproj
+++ b/Moonlight.xcodeproj/project.pbxproj
@@ -3,15 +3,13 @@
archiveVersion = 1;
classes = {
};
- objectVersion = 54;
+ objectVersion = 60;
objects = {
/* Begin PBXBuildFile section */
693B3A9B218638CD00982F7B /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 693B3A9A218638CD00982F7B /* Settings.bundle */; };
840751B32BF49C050096B657 /* CustomTapGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */; };
840751B42BF49C050096B657 /* CustomTapGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */; };
- 8425C3002C298E0D00CD5E34 /* iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8425C2FE2C298E0D00CD5E34 /* iPhone.storyboard */; };
- 8425C3012C298E0D00CD5E34 /* iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8425C2FF2C298E0D00CD5E34 /* iPad.storyboard */; };
84351B0E2C29ACCB00A77989 /* LayoutOnScreenControls.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */; };
84351B0F2C29ACCB00A77989 /* OnScreenButtonState.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B092C29ACCA00A77989 /* OnScreenButtonState.m */; };
84351B102C29ACCB00A77989 /* OSCProfile.m in Sources */ = {isa = PBXBuildFile; fileRef = 84351B0A2C29ACCA00A77989 /* OSCProfile.m */; };
@@ -25,7 +23,13 @@
843CC7F12C1E757D00BBC475 /* NativeTouchPointer.m in Sources */ = {isa = PBXBuildFile; fileRef = 843CC7EF2C1E757D00BBC475 /* NativeTouchPointer.m */; };
843CC7F62C1E7A1700BBC475 /* NativeTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 843CC7F52C1E7A1700BBC475 /* NativeTouchHandler.m */; };
843CC7F72C1E7A1700BBC475 /* NativeTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 843CC7F52C1E7A1700BBC475 /* NativeTouchHandler.m */; };
+ 8454AC662C31907F00F0A302 /* iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8454AC682C31907F00F0A302 /* iPad.storyboard */; };
+ 8454AC6A2C319BDA00F0A302 /* iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8454AC6C2C319BDA00F0A302 /* iPhone.storyboard */; };
84591A512BE1625E006AAB10 /* CustomEdgeSwipeGestureRecognizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 84591A502BE1625E006AAB10 /* CustomEdgeSwipeGestureRecognizer.m */; };
+ 84FD0B512C31338D006B5BE5 /* LocalizationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FD0B502C31338D006B5BE5 /* LocalizationHelper.m */; };
+ 84FD0B522C31338D006B5BE5 /* LocalizationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 84FD0B502C31338D006B5BE5 /* LocalizationHelper.m */; };
+ 84FD0B542C3134A6006B5BE5 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 84FD0B532C3134A6006B5BE5 /* Localizable.xcstrings */; };
+ 84FD0B552C3134A6006B5BE5 /* Localizable.xcstrings in Resources */ = {isa = PBXBuildFile; fileRef = 84FD0B532C3134A6006B5BE5 /* Localizable.xcstrings */; };
98181BE92791277400E43572 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98181BE82791275D00E43572 /* libSDL2.a */; };
98181BEB2791278F00E43572 /* libSDL2.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98181BEA2791278300E43572 /* libSDL2.a */; };
98181BED2791281100E43572 /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 98181BEC2791281100E43572 /* CoreMotion.framework */; };
@@ -190,8 +194,6 @@
693B3A9A218638CD00982F7B /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = ""; };
840751B12BF49B5A0096B657 /* CustomTapGestureRecognizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomTapGestureRecognizer.h; sourceTree = ""; };
840751B22BF49C050096B657 /* CustomTapGestureRecognizer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomTapGestureRecognizer.m; sourceTree = ""; };
- 8425C2FE2C298E0D00CD5E34 /* iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = iPhone.storyboard; sourceTree = ""; };
- 8425C2FF2C298E0D00CD5E34 /* iPad.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = iPad.storyboard; sourceTree = ""; };
84351B062C29ACCA00A77989 /* OnScreenButtonState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnScreenButtonState.h; sourceTree = ""; };
84351B072C29ACCA00A77989 /* LayoutOnScreenControls.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LayoutOnScreenControls.m; sourceTree = ""; };
84351B082C29ACCA00A77989 /* OSCProfilesManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OSCProfilesManager.h; sourceTree = ""; };
@@ -213,8 +215,15 @@
843CC7EF2C1E757D00BBC475 /* NativeTouchPointer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NativeTouchPointer.m; sourceTree = ""; };
843CC7F42C1E778000BBC475 /* NativeTouchHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeTouchHandler.h; sourceTree = ""; };
843CC7F52C1E7A1700BBC475 /* NativeTouchHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NativeTouchHandler.m; sourceTree = ""; };
+ 8454AC672C31907F00F0A302 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/iPad.storyboard; sourceTree = ""; };
+ 8454AC692C31907F00F0A302 /* mul */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; name = mul; path = mul.lproj/iPad.xcstrings; sourceTree = ""; };
+ 8454AC6B2C319BDA00F0A302 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/iPhone.storyboard; sourceTree = ""; };
+ 8454AC6D2C319BDA00F0A302 /* mul */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; name = mul; path = mul.lproj/iPhone.xcstrings; sourceTree = ""; };
84591A4F2BE16240006AAB10 /* CustomEdgeSwipeGestureRecognizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CustomEdgeSwipeGestureRecognizer.h; sourceTree = ""; };
84591A502BE1625E006AAB10 /* CustomEdgeSwipeGestureRecognizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CustomEdgeSwipeGestureRecognizer.m; sourceTree = ""; };
+ 84FD0B4F2C313343006B5BE5 /* LocalizationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LocalizationHelper.h; sourceTree = ""; };
+ 84FD0B502C31338D006B5BE5 /* LocalizationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LocalizationHelper.m; sourceTree = ""; };
+ 84FD0B532C3134A6006B5BE5 /* Localizable.xcstrings */ = {isa = PBXFileReference; lastKnownFileType = text.json.xcstrings; path = Localizable.xcstrings; sourceTree = ""; };
9803CCAB254F9EAF00EE185E /* ConnectionCallbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ConnectionCallbacks.h; sourceTree = ""; };
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.1.xcdatamodel"; sourceTree = ""; };
98181BE82791275D00E43572 /* libSDL2.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libSDL2.a; path = libs/SDL2/lib/iOS/libSDL2.a; sourceTree = ""; };
@@ -523,6 +532,16 @@
path = Cells;
sourceTree = "";
};
+ 84FD0B492C312C0B006B5BE5 /* Localization */ = {
+ isa = PBXGroup;
+ children = (
+ 84FD0B4F2C313343006B5BE5 /* LocalizationHelper.h */,
+ 84FD0B502C31338D006B5BE5 /* LocalizationHelper.m */,
+ 84FD0B532C3134A6006B5BE5 /* Localizable.xcstrings */,
+ );
+ path = Localization;
+ sourceTree = "";
+ };
9896219423D15C2900211983 /* X1Kit */ = {
isa = PBXGroup;
children = (
@@ -604,8 +623,9 @@
FB290CF919B2C406004C83CF /* Moonlight */ = {
isa = PBXGroup;
children = (
- 8425C2FF2C298E0D00CD5E34 /* iPad.storyboard */,
- 8425C2FE2C298E0D00CD5E34 /* iPhone.storyboard */,
+ 84FD0B492C312C0B006B5BE5 /* Localization */,
+ 8454AC682C31907F00F0A302 /* iPad.storyboard */,
+ 8454AC6C2C319BDA00F0A302 /* iPhone.storyboard */,
D4746EEA1CBC740C006FB401 /* Moonlight-Bridging-Header.h */,
FB89460419F646E200339C8A /* Crypto */,
FB89460919F646E200339C8A /* Input */,
@@ -1034,6 +1054,7 @@
knownRegions = (
en,
Base,
+ "zh-Hans",
);
mainGroup = FB290CE519B2C406004C83CF;
productRefGroup = FB290CEF19B2C406004C83CF /* Products */;
@@ -1075,6 +1096,7 @@
buildActionMask = 2147483647;
files = (
693B3A9B218638CD00982F7B /* Settings.bundle in Resources */,
+ 84FD0B552C3134A6006B5BE5 /* Localizable.xcstrings in Resources */,
FB1A681E21328A1B00507771 /* Images.xcassets in Resources */,
FB1A67622132419A00507771 /* Assets.xcassets in Resources */,
FB1A67602132419700507771 /* Main.storyboard in Resources */,
@@ -1088,8 +1110,9 @@
FB290CFE19B2C406004C83CF /* InfoPlist.strings in Resources */,
FB290D0919B2C406004C83CF /* Images.xcassets in Resources */,
FB89463819F6473800339C8A /* Launch Screen.xib in Resources */,
- 8425C3012C298E0D00CD5E34 /* iPad.storyboard in Resources */,
- 8425C3002C298E0D00CD5E34 /* iPhone.storyboard in Resources */,
+ 8454AC662C31907F00F0A302 /* iPad.storyboard in Resources */,
+ 8454AC6A2C319BDA00F0A302 /* iPhone.storyboard in Resources */,
+ 84FD0B542C3134A6006B5BE5 /* Localizable.xcstrings in Resources */,
84351B5D2C29ADBE00A77989 /* ProfileTableViewCell.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1101,6 +1124,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
+ 84FD0B522C31338D006B5BE5 /* LocalizationHelper.m in Sources */,
9827E7A42514366900F25707 /* HapticContext.m in Sources */,
9897B6A62212732C00966419 /* Controller.m in Sources */,
9865DC3E21332D660005B9B9 /* MainFrameViewController.m in Sources */,
@@ -1179,6 +1203,7 @@
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */,
+ 84FD0B512C31338D006B5BE5 /* LocalizationHelper.m in Sources */,
FB1D59971BBCCB6400F482CA /* ComputerScrollView.m in Sources */,
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */,
843CC7F02C1E757D00BBC475 /* NativeTouchPointer.m in Sources */,
@@ -1237,6 +1262,24 @@
/* End PBXTargetDependency section */
/* Begin PBXVariantGroup section */
+ 8454AC682C31907F00F0A302 /* iPad.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8454AC672C31907F00F0A302 /* Base */,
+ 8454AC692C31907F00F0A302 /* mul */,
+ );
+ name = iPad.storyboard;
+ sourceTree = "";
+ };
+ 8454AC6C2C319BDA00F0A302 /* iPhone.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8454AC6B2C319BDA00F0A302 /* Base */,
+ 8454AC6D2C319BDA00F0A302 /* mul */,
+ );
+ name = iPhone.storyboard;
+ sourceTree = "";
+ };
FB1A675E2132419700507771 /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
@@ -1496,6 +1539,7 @@
"$(PROJECT_DIR)/Limelight/ViewControllers/CustomOSCViewControl",
"$(PROJECT_DIR)/Limelight/ViewControllers/CustomOSCViewControl/Cells",
"$(PROJECT_DIR)/Limelight/Input",
+ "$(PROJECT_DIR)/Limelight/Localization",
);
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = MoonlightZWM;
@@ -1551,6 +1595,7 @@
"$(PROJECT_DIR)/Limelight/ViewControllers/CustomOSCViewControl",
"$(PROJECT_DIR)/Limelight/ViewControllers/CustomOSCViewControl/Cells",
"$(PROJECT_DIR)/Limelight/Input",
+ "$(PROJECT_DIR)/Limelight/Localization",
);
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = MoonlightZWM;