diff --git a/FreeMove/Form1.Designer.cs b/FreeMove/Form1.Designer.cs index 844620c..be48ec6 100644 --- a/FreeMove/Form1.Designer.cs +++ b/FreeMove/Form1.Designer.cs @@ -69,31 +69,35 @@ private void InitializeComponent() this.reportAnIssueToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.gitHubToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.aboutToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.lunguToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.zhToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.chineseToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.chkBox_createDest = new System.Windows.Forms.CheckBox(); + this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.menuStrip1.SuspendLayout(); this.SuspendLayout(); // // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 34); + this.label1.Location = new System.Drawing.Point(12, 31); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(63, 13); + this.label1.Size = new System.Drawing.Size(65, 12); this.label1.TabIndex = 0; this.label1.Text = "Move From:"; // // textBox_From // - this.textBox_From.Location = new System.Drawing.Point(82, 34); + this.textBox_From.Location = new System.Drawing.Point(82, 31); this.textBox_From.Name = "textBox_From"; - this.textBox_From.Size = new System.Drawing.Size(383, 20); + this.textBox_From.Size = new System.Drawing.Size(383, 21); this.textBox_From.TabIndex = 1; // // button_BrowseFrom // - this.button_BrowseFrom.Location = new System.Drawing.Point(475, 34); + this.button_BrowseFrom.Location = new System.Drawing.Point(475, 31); this.button_BrowseFrom.Name = "button_BrowseFrom"; - this.button_BrowseFrom.Size = new System.Drawing.Size(75, 23); + this.button_BrowseFrom.Size = new System.Drawing.Size(75, 21); this.button_BrowseFrom.TabIndex = 2; this.button_BrowseFrom.Text = "Browse..."; this.button_BrowseFrom.UseVisualStyleBackColor = true; @@ -101,9 +105,9 @@ private void InitializeComponent() // // button_BrowseTo // - this.button_BrowseTo.Location = new System.Drawing.Point(475, 58); + this.button_BrowseTo.Location = new System.Drawing.Point(475, 54); this.button_BrowseTo.Name = "button_BrowseTo"; - this.button_BrowseTo.Size = new System.Drawing.Size(75, 23); + this.button_BrowseTo.Size = new System.Drawing.Size(75, 21); this.button_BrowseTo.TabIndex = 4; this.button_BrowseTo.Text = "Browse..."; this.button_BrowseTo.UseVisualStyleBackColor = true; @@ -111,17 +115,17 @@ private void InitializeComponent() // // textBox_To // - this.textBox_To.Location = new System.Drawing.Point(82, 60); + this.textBox_To.Location = new System.Drawing.Point(82, 55); this.textBox_To.Name = "textBox_To"; - this.textBox_To.Size = new System.Drawing.Size(383, 20); + this.textBox_To.Size = new System.Drawing.Size(383, 21); this.textBox_To.TabIndex = 3; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 60); + this.label2.Location = new System.Drawing.Point(12, 55); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(23, 13); + this.label2.Size = new System.Drawing.Size(23, 12); this.label2.TabIndex = 3; this.label2.Text = "To:"; // @@ -131,9 +135,9 @@ private void InitializeComponent() // // button_Move // - this.button_Move.Location = new System.Drawing.Point(475, 118); + this.button_Move.Location = new System.Drawing.Point(475, 109); this.button_Move.Name = "button_Move"; - this.button_Move.Size = new System.Drawing.Size(75, 23); + this.button_Move.Size = new System.Drawing.Size(75, 21); this.button_Move.TabIndex = 6; this.button_Move.Text = "Move"; this.button_Move.UseVisualStyleBackColor = true; @@ -142,18 +146,18 @@ private void InitializeComponent() // chkBox_originalHidden // this.chkBox_originalHidden.AutoSize = true; - this.chkBox_originalHidden.Location = new System.Drawing.Point(15, 95); + this.chkBox_originalHidden.Location = new System.Drawing.Point(15, 88); this.chkBox_originalHidden.Name = "chkBox_originalHidden"; - this.chkBox_originalHidden.Size = new System.Drawing.Size(154, 17); + this.chkBox_originalHidden.Size = new System.Drawing.Size(198, 16); this.chkBox_originalHidden.TabIndex = 5; this.chkBox_originalHidden.Text = "Set original folder to hidden"; this.chkBox_originalHidden.UseVisualStyleBackColor = true; // // button_Close // - this.button_Close.Location = new System.Drawing.Point(12, 118); + this.button_Close.Location = new System.Drawing.Point(12, 109); this.button_Close.Name = "button_Close"; - this.button_Close.Size = new System.Drawing.Size(75, 23); + this.button_Close.Size = new System.Drawing.Size(75, 21); this.button_Close.TabIndex = 7; this.button_Close.Text = "Close"; this.button_Close.UseVisualStyleBackColor = true; @@ -163,11 +167,12 @@ private void InitializeComponent() // this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.settingsToolStripMenuItem, + this.lunguToolStripMenuItem, this.infoToolStripMenuItem}); this.menuStrip1.Location = new System.Drawing.Point(0, 0); this.menuStrip1.Name = "menuStrip1"; this.menuStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; - this.menuStrip1.Size = new System.Drawing.Size(565, 24); + this.menuStrip1.Size = new System.Drawing.Size(565, 25); this.menuStrip1.TabIndex = 8; this.menuStrip1.Text = "menuStrip1"; // @@ -178,7 +183,7 @@ private void InitializeComponent() this.PermissionCheckToolStripMenuItem, this.safeModeToolStripMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; - this.settingsToolStripMenuItem.Size = new System.Drawing.Size(61, 20); + this.settingsToolStripMenuItem.Size = new System.Drawing.Size(66, 21); this.settingsToolStripMenuItem.Text = "Settings"; // // checkForUpdateToolStripMenuItem @@ -187,20 +192,20 @@ private void InitializeComponent() this.checkNowToolStripMenuItem, this.checkOnProgramStartToolStripMenuItem}); this.checkForUpdateToolStripMenuItem.Name = "checkForUpdateToolStripMenuItem"; - this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.checkForUpdateToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.checkForUpdateToolStripMenuItem.Text = "Check for update"; // // checkNowToolStripMenuItem // this.checkNowToolStripMenuItem.Name = "checkNowToolStripMenuItem"; - this.checkNowToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.checkNowToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.checkNowToolStripMenuItem.Text = "Check now"; this.checkNowToolStripMenuItem.Click += new System.EventHandler(this.CheckNowToolStripMenuItem_Click); // // checkOnProgramStartToolStripMenuItem // this.checkOnProgramStartToolStripMenuItem.Name = "checkOnProgramStartToolStripMenuItem"; - this.checkOnProgramStartToolStripMenuItem.Size = new System.Drawing.Size(199, 22); + this.checkOnProgramStartToolStripMenuItem.Size = new System.Drawing.Size(216, 22); this.checkOnProgramStartToolStripMenuItem.Text = "Check on program start"; this.checkOnProgramStartToolStripMenuItem.Click += new System.EventHandler(this.CheckOnProgramStartToolStripMenuItem_Click); // @@ -211,13 +216,13 @@ private void InitializeComponent() this.fastToolStripMenuItem, this.fullToolStripMenuItem}); this.PermissionCheckToolStripMenuItem.Name = "PermissionCheckToolStripMenuItem"; - this.PermissionCheckToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.PermissionCheckToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.PermissionCheckToolStripMenuItem.Text = "Permission check"; // // noneToolStripMenuItem // this.noneToolStripMenuItem.Name = "noneToolStripMenuItem"; - this.noneToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.noneToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.noneToolStripMenuItem.Text = "None"; this.noneToolStripMenuItem.ToolTipText = "Don\'t check any file before moving"; this.noneToolStripMenuItem.Click += new System.EventHandler(this.NoneToolStripMenuItem_Click); @@ -227,7 +232,7 @@ private void InitializeComponent() this.fastToolStripMenuItem.Checked = true; this.fastToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.fastToolStripMenuItem.Name = "fastToolStripMenuItem"; - this.fastToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.fastToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.fastToolStripMenuItem.Text = "Fast"; this.fastToolStripMenuItem.ToolTipText = "Check all .exe and .dll files before moving"; this.fastToolStripMenuItem.Click += new System.EventHandler(this.FastToolStripMenuItem_Click); @@ -235,7 +240,7 @@ private void InitializeComponent() // fullToolStripMenuItem // this.fullToolStripMenuItem.Name = "fullToolStripMenuItem"; - this.fullToolStripMenuItem.Size = new System.Drawing.Size(103, 22); + this.fullToolStripMenuItem.Size = new System.Drawing.Size(108, 22); this.fullToolStripMenuItem.Text = "Full"; this.fullToolStripMenuItem.ToolTipText = "Check all files before moving"; this.fullToolStripMenuItem.Click += new System.EventHandler(this.FullToolStripMenuItem_Click); @@ -245,7 +250,7 @@ private void InitializeComponent() this.safeModeToolStripMenuItem.Checked = true; this.safeModeToolStripMenuItem.CheckState = System.Windows.Forms.CheckState.Checked; this.safeModeToolStripMenuItem.Name = "safeModeToolStripMenuItem"; - this.safeModeToolStripMenuItem.Size = new System.Drawing.Size(166, 22); + this.safeModeToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.safeModeToolStripMenuItem.Text = "Safe mode"; this.safeModeToolStripMenuItem.Click += new System.EventHandler(this.SafeModeToolStripMenuItem_Click); // @@ -254,50 +259,81 @@ private void InitializeComponent() this.infoToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.reportAnIssueToolStripMenuItem, this.gitHubToolStripMenuItem, + this.helpToolStripMenuItem, this.aboutToolStripMenuItem}); this.infoToolStripMenuItem.Name = "infoToolStripMenuItem"; this.infoToolStripMenuItem.RightToLeft = System.Windows.Forms.RightToLeft.No; - this.infoToolStripMenuItem.Size = new System.Drawing.Size(40, 20); + this.infoToolStripMenuItem.Size = new System.Drawing.Size(43, 21); this.infoToolStripMenuItem.Text = "Info"; // // reportAnIssueToolStripMenuItem // this.reportAnIssueToolStripMenuItem.Name = "reportAnIssueToolStripMenuItem"; - this.reportAnIssueToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.reportAnIssueToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.reportAnIssueToolStripMenuItem.Text = "Report an Issue"; this.reportAnIssueToolStripMenuItem.Click += new System.EventHandler(this.ReportAnIssueToolStripMenuItem_Click); // // gitHubToolStripMenuItem // this.gitHubToolStripMenuItem.Name = "gitHubToolStripMenuItem"; - this.gitHubToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.gitHubToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.gitHubToolStripMenuItem.Text = "GitHub"; this.gitHubToolStripMenuItem.Click += new System.EventHandler(this.GitHubToolStripMenuItem_Click); // // aboutToolStripMenuItem // this.aboutToolStripMenuItem.Name = "aboutToolStripMenuItem"; - this.aboutToolStripMenuItem.Size = new System.Drawing.Size(154, 22); + this.aboutToolStripMenuItem.Size = new System.Drawing.Size(180, 22); this.aboutToolStripMenuItem.Text = "About"; this.aboutToolStripMenuItem.Click += new System.EventHandler(this.AboutToolStripMenuItem_Click); // + // lunguToolStripMenuItem + // + this.lunguToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.zhToolStripMenuItem, + this.chineseToolStripMenuItem}); + this.lunguToolStripMenuItem.Name = "lunguToolStripMenuItem"; + this.lunguToolStripMenuItem.Size = new System.Drawing.Size(77, 21); + this.lunguToolStripMenuItem.Text = "Language"; + // + // zhToolStripMenuItem + // + this.zhToolStripMenuItem.Name = "zhToolStripMenuItem"; + this.zhToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.zhToolStripMenuItem.Text = "English"; + this.zhToolStripMenuItem.Click += new System.EventHandler(this.zhToolStripMenuItem_Click); + // + // chineseToolStripMenuItem + // + this.chineseToolStripMenuItem.Name = "chineseToolStripMenuItem"; + this.chineseToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.chineseToolStripMenuItem.Text = "Chinese"; + this.chineseToolStripMenuItem.Click += new System.EventHandler(this.chineseToolStripMenuItem_Click); + // // chkBox_createDest // this.chkBox_createDest.AutoSize = true; this.chkBox_createDest.Checked = true; this.chkBox_createDest.CheckState = System.Windows.Forms.CheckState.Checked; - this.chkBox_createDest.Location = new System.Drawing.Point(175, 95); + this.chkBox_createDest.Location = new System.Drawing.Point(219, 88); this.chkBox_createDest.Name = "chkBox_createDest"; - this.chkBox_createDest.Size = new System.Drawing.Size(140, 17); + this.chkBox_createDest.Size = new System.Drawing.Size(174, 16); this.chkBox_createDest.TabIndex = 9; this.chkBox_createDest.Text = "Create destination folder"; this.chkBox_createDest.UseVisualStyleBackColor = true; // + // helpToolStripMenuItem + // + this.helpToolStripMenuItem.Name = "helpToolStripMenuItem"; + this.helpToolStripMenuItem.Size = new System.Drawing.Size(180, 22); + this.helpToolStripMenuItem.Text = "Help"; + this.helpToolStripMenuItem.Click += new System.EventHandler(this.HelpToolStripMenuItem_Click); + // // Form1 // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(565, 150); + this.ClientSize = new System.Drawing.Size(565, 138); this.Controls.Add(this.chkBox_createDest); this.Controls.Add(this.button_Close); this.Controls.Add(this.chkBox_originalHidden); @@ -350,6 +386,10 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem fastToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem fullToolStripMenuItem; public System.Windows.Forms.CheckBox chkBox_createDest; + private System.Windows.Forms.ToolStripMenuItem lunguToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem zhToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem chineseToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem helpToolStripMenuItem; } } diff --git a/FreeMove/Form1.cs b/FreeMove/Form1.cs index 242a1d8..8d6e7b9 100644 --- a/FreeMove/Form1.cs +++ b/FreeMove/Form1.cs @@ -43,8 +43,12 @@ public Form1() private async void Form1_Load(object sender, EventArgs e) { + ApplyLanguage(); SetToolTips(); + + + //Check whether the program is set to update on its start if (Settings.AutoUpdate) { @@ -77,6 +81,57 @@ private async void Form1_Load(object sender, EventArgs e) #endregion + /// + /// 根据当前 UI 语言刷新界面上的文本(按钮/菜单/标签等) + /// + private void ApplyLanguage() + { + // 窗口标题 + Text = Properties.Resources.ResourceManager.GetString("Form_Title"); + + // 标签和按钮 + label1.Text = Properties.Resources.ResourceManager.GetString("Label_From"); + label2.Text = Properties.Resources.ResourceManager.GetString("Label_To"); + button_BrowseFrom.Text = Properties.Resources.ResourceManager.GetString("Button_Browse"); + button_BrowseTo.Text = Properties.Resources.ResourceManager.GetString("Button_Browse"); + button_Move.Text = Properties.Resources.ResourceManager.GetString("Button_Move"); + button_Close.Text = Properties.Resources.ResourceManager.GetString("Button_Close"); + chkBox_originalHidden.Text = Properties.Resources.ResourceManager.GetString("Checkbox_OriginalHidden"); + chkBox_createDest.Text = Properties.Resources.ResourceManager.GetString("Checkbox_CreateDest"); + + // 菜单 + settingsToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Settings"); + infoToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Info"); + lunguToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Language"); + + checkForUpdateToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckForUpdate"); + checkNowToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckNow"); + checkOnProgramStartToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_CheckOnStart"); + + PermissionCheckToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_PermissionCheck"); + safeModeToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_SafeMode"); + + noneToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_None"); + fastToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Fast"); + fullToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Full"); + + reportAnIssueToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_ReportIssue"); + gitHubToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_GitHub"); + aboutToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_About"); + helpToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("HelpButtonText"); + + zhToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Lang_English"); + chineseToolStripMenuItem.Text = Properties.Resources.ResourceManager.GetString("Menu_Lang_Chinese"); + + // 语言菜单打勾状态 + string lang = Settings.Language; + // lang 为空时:跟随系统,这里根据当前 Culture 判定 + string current = System.Globalization.CultureInfo.CurrentUICulture.Name; + bool isChinese = (!string.IsNullOrEmpty(lang) ? lang : current).StartsWith("zh", StringComparison.OrdinalIgnoreCase); + zhToolStripMenuItem.Checked = !isChinese; + chineseToolStripMenuItem.Checked = isChinese; + } + private bool PreliminaryCheck(string source, string destination) { //Check for errors before copying @@ -84,14 +139,14 @@ private bool PreliminaryCheck(string source, string destination) { IOHelper.CheckDirectories(source, destination, safeMode); } - catch(AggregateException ae) + catch (AggregateException ae) { var msg = ""; foreach (var ex in ae.InnerExceptions) { msg += ex.Message + "\n"; } - MessageBox.Show(msg, "Error"); + MessageBox.Show(msg, Properties.Resources.ResourceManager.GetString("ErrorTitle")); return false; } return true; @@ -117,11 +172,12 @@ private async void Begin() olddir.Attributes = attrib | FileAttributes.Hidden; } - MessageBox.Show(this, "Done!"); + MessageBox.Show(this, Properties.Resources.ResourceManager.GetString("DoneMessage")); } catch (IO.MoveOperation.CopyFailedException ex) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?\n\nDetails:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) + string question = string.Format(Properties.Resources.ResourceManager.GetString("UndoChangesDetailsQuestion"), ex.InnerException.Message); + switch (MessageBox.Show(this, question, ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -130,7 +186,7 @@ private async void Begin() } catch (Exception ie) { - MessageBox.Show(this, ie.Message, "Could not remove copied contents. Try removing manually"); + MessageBox.Show(this, ie.Message, Properties.Resources.ResourceManager.GetString("RemoveCopiedContentsFailed")); } break; case DialogResult.No: @@ -140,7 +196,8 @@ private async void Begin() } catch (IO.MoveOperation.DeleteFailedException ex) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?\n\nDetails:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) + string question = string.Format(Properties.Resources.ResourceManager.GetString("UndoChangesDetailsQuestion"), ex.InnerException.Message); + switch (MessageBox.Show(this, question, ex.Message, MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -149,7 +206,7 @@ private async void Begin() } catch (Exception ie) { - MessageBox.Show(this, ie.Message, "Could not move back contents. Try moving manually"); + MessageBox.Show(this, ie.Message, Properties.Resources.ResourceManager.GetString("MoveBackFailedMessage")); } break; case DialogResult.No: @@ -159,11 +216,14 @@ private async void Begin() } catch (IO.MoveOperation.MoveFailedException ex) { - MessageBox.Show(this, string.Format($"Details:\n{ex.InnerException.Message}"), ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); + string details = string.Format(Properties.Resources.ResourceManager.GetString("MoveFailedDetailsFormat"), ex.InnerException.Message); + MessageBox.Show(this, details, ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error); } catch (OperationCanceledException) { - switch (MessageBox.Show(this, string.Format($"Do you want to undo the changes?"), "Cancelled", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)) + string question = Properties.Resources.ResourceManager.GetString("UndoChangesSimpleQuestion"); + string title = Properties.Resources.ResourceManager.GetString("CancelledTitle"); + switch (MessageBox.Show(this, question, title, MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1)) { case DialogResult.Yes: try @@ -185,7 +245,7 @@ private async void Begin() private async Task BeginMove(string source, string destination) { //Move files - using (ProgressDialog progressDialog = new ProgressDialog("Moving files...")) + using (ProgressDialog progressDialog = new ProgressDialog(Properties.Resources.ResourceManager.GetString("MovingFilesTitle"))) { IO.MoveOperation moveOp = IOHelper.MoveDir(source, destination); @@ -194,7 +254,9 @@ private async Task BeginMove(string source, string destination) progressDialog.CancelRequested += (sender, e) => { - if (DialogResult.Yes == MessageBox.Show(this, "Are you sure you want to cancel?", "Cancel confirmation", MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)) + string message = Properties.Resources.ResourceManager.GetString("CancelConfirmationMessage"); + string title = Properties.Resources.ResourceManager.GetString("CancelConfirmationTitle"); + if (DialogResult.Yes == MessageBox.Show(this, message, title, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2)) { moveOp.Cancel(); progressDialog.BeginInvoke(new Action(() => progressDialog.Cancellable = false)); @@ -230,9 +292,9 @@ private void SetToolTips() InitialDelay = 600, ReshowDelay = 500 }; - Tip.SetToolTip(this.textBox_From, "Select the folder you want to move"); - Tip.SetToolTip(this.textBox_To, "Select where you want to move the folder"); - Tip.SetToolTip(this.chkBox_originalHidden, "Select whether you want to hide the shortcut which is created in the old location or not"); + Tip.SetToolTip(this.textBox_From, Properties.Resources.ResourceManager.GetString("TooltipFrom")); + Tip.SetToolTip(this.textBox_To, Properties.Resources.ResourceManager.GetString("TooltipTo")); + Tip.SetToolTip(this.chkBox_originalHidden, Properties.Resources.ResourceManager.GetString("TooltipHidden")); } private void Reset() @@ -244,7 +306,8 @@ private void Reset() public static void Unauthorized(Exception ex) { - MessageBox.Show(Properties.Resources.ErrorUnauthorizedMoveDetails + ex.Message, "Error details"); + string title = Properties.Resources.ResourceManager.GetString("ErrorDetailsTitle"); + MessageBox.Show(Properties.Resources.ErrorUnauthorizedMoveDetails + ex.Message, title); } #region Event Handlers @@ -327,12 +390,14 @@ private void CheckOnProgramStartToolStripMenuItem_Click(object sender, EventArgs private void AboutToolStripMenuItem_Click(object sender, EventArgs e) { string msg = String.Format(Properties.Resources.AboutContent, System.Diagnostics.FileVersionInfo.GetVersionInfo(System.Reflection.Assembly.GetExecutingAssembly().Location).FileVersion); - MessageBox.Show(msg, "About FreeMove"); + string title = Properties.Resources.ResourceManager.GetString("AboutTitle"); + MessageBox.Show(msg, title); } private void SafeModeToolStripMenuItem_Click(object sender, EventArgs e) { - if (MessageBox.Show(Properties.Resources.DisableSafeModeMessage, "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) + string title = Properties.Resources.ResourceManager.GetString("WarningTitle"); + if (MessageBox.Show(Properties.Resources.DisableSafeModeMessage, title, MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button2) == DialogResult.Yes) { safeMode = false; safeModeToolStripMenuItem.Checked = false; @@ -363,5 +428,32 @@ private void FullToolStripMenuItem_Click(object sender, EventArgs e) fastToolStripMenuItem.Checked = false; fullToolStripMenuItem.Checked = true; } + + private void zhToolStripMenuItem_Click(object sender, EventArgs e) + { + // 切换为英文界面 + Settings.Language = "en"; + string msg = Properties.Resources.ResourceManager.GetString("LanguageChangedRestartMessage"); + string title = Properties.Resources.ResourceManager.GetString("LanguageChangedTitle"); + MessageBox.Show(msg, title); + Application.Restart(); + } + + private void chineseToolStripMenuItem_Click(object sender, EventArgs e) + { + // 切换为简体中文界面 + Settings.Language = "zh-Hans"; + string msg = Properties.Resources.ResourceManager.GetString("LanguageChangedRestartMessage"); + string title = Properties.Resources.ResourceManager.GetString("LanguageChangedTitle"); + MessageBox.Show(msg, title); + Application.Restart(); + } + + private void HelpToolStripMenuItem_Click(object sender, EventArgs e) + { + string help = Properties.Resources.ResourceManager.GetString("HelpContent"); + string title = Properties.Resources.ResourceManager.GetString("HelpButtonText"); + MessageBox.Show(this, help, title, MessageBoxButtons.OK, MessageBoxIcon.Information); + } } } diff --git a/FreeMove/FreeMove.csproj b/FreeMove/FreeMove.csproj index 4411525..5744d7a 100644 --- a/FreeMove/FreeMove.csproj +++ b/FreeMove/FreeMove.csproj @@ -1,6 +1,7 @@ net48 + 9.0 WinExe publish\ true @@ -39,11 +40,14 @@ + + + - + diff --git a/FreeMove/Program.cs b/FreeMove/Program.cs index bfedf00..b3165f1 100644 --- a/FreeMove/Program.cs +++ b/FreeMove/Program.cs @@ -19,6 +19,9 @@ using System.Linq; using System.Threading.Tasks; using System.Windows.Forms; +using System.Globalization; +using System.Threading; +using System.Security.Principal; namespace FreeMove { @@ -30,8 +33,52 @@ static class Program [STAThread] static void Main() { + // 如非管理员权限,提示并退出 + try + { + using (WindowsIdentity identity = WindowsIdentity.GetCurrent()) + { + WindowsPrincipal principal = new WindowsPrincipal(identity); + if (!principal.IsInRole(WindowsBuiltInRole.Administrator)) + { + string msg = Properties.Resources.ResourceManager.GetString("AdminRequiredMessage"); + string title = Properties.Resources.ResourceManager.GetString("AdminRequiredTitle"); + MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + } + } + catch + { + // 如果检查失败,出于安全考虑也直接退出 + string msg = Properties.Resources.ResourceManager.GetString("AdminRequiredMessage"); + string title = Properties.Resources.ResourceManager.GetString("AdminRequiredTitle"); + MessageBox.Show(msg, title, MessageBoxButtons.OK, MessageBoxIcon.Warning); + return; + } + + // 设置全局语言:优先使用用户在设置中选择的语言,否则跟随系统 + try + { + string lang = Settings.Language; + CultureInfo culture; + if (!string.IsNullOrEmpty(lang)) + { + culture = new CultureInfo(lang); + } + else + { + culture = CultureInfo.InstalledUICulture; + } + Thread.CurrentThread.CurrentCulture = culture; + Thread.CurrentThread.CurrentUICulture = culture; + } + catch + { + // 如果设置中的语言代码无效,忽略并使用系统默认 + } + Application.EnableVisualStyles(); - Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Form1()); } diff --git a/FreeMove/ProgressDialog.cs b/FreeMove/ProgressDialog.cs index ab2282b..205063b 100644 --- a/FreeMove/ProgressDialog.cs +++ b/FreeMove/ProgressDialog.cs @@ -69,7 +69,8 @@ public void UpdateProgress(IO.IOOperation.ProgressChangedEventArgs e) label_Progress?.BeginInvoke(new Action(() => { float percentage = ((float)e.Progress / e.Max); - label_Progress.Text = e.Progress == e.Max ? "Finishing..." : $"{e.Progress}/{e.Max}"; + string finishing = Properties.Resources.ResourceManager.GetString("ProgressFinishingText"); + label_Progress.Text = e.Progress == e.Max ? finishing : $"{e.Progress}/{e.Max}"; if (e.Progress == e.Max) Cancellable = false; // label_Progress.Text = $"{percentage*100f, 3:0.0}%"; diff --git a/FreeMove/Properties/Resources.resx b/FreeMove/Properties/Resources.resx index f52b321..9e41610 100644 --- a/FreeMove/Properties/Resources.resx +++ b/FreeMove/Properties/Resources.resx @@ -183,4 +183,191 @@ If this text file was useful or if you would have preferred it wasn't created le ImDema-FreeMove-Updater + + Done! + + + Error + + + Could not remove copied contents. Try removing manually + + + Could not move back contents. Try moving manually + + + Details: +{0} + + + Do you want to undo the changes? + +Details: +{0} + + + Do you want to undo the changes? + + + Cancelled + + + Are you sure you want to cancel? + + + Cancel confirmation + + + Select the folder you want to move + + + Select where you want to move the folder + + + Select whether you want to hide the shortcut which is created in the old location or not + + + Error details + + + About FreeMove + + + Warning + + + Moving files... + + + Finishing... + + + Language has been changed. The application will restart to apply the new language. + + + Language + + + Free Move + + + Move From: + + + To: + + + Browse... + + + Move + + + Close + + + Set original folder to hidden + + + Create destination folder + + + Settings + + + Info + + + Language + + + Check for update + + + Check now + + + Check on program start + + + Permission check + + + Safe mode + + + None + + + Fast + + + Full + + + Report an Issue + + + GitHub + + + About + + + English + + + Chinese + + + This application must be run as administrator in order to move folders and create junctions. + +Please right-click the executable and choose "Run as administrator". + + + Administrator required + + + Help + + + FreeMove - Help + +Move From: Select the folder you want to move (for example, a program folder under Program Files). +To: Select the target location (for example, another drive) where you want to move the folder. +Browse... Open a folder picker dialog to choose the source or target folder. + +Move: Start moving the selected folder to the target location and create a junction at the original path. +Close: Close the application window. + +Set original folder to hidden: + After moving, set the junction at the original location to Hidden so it is not visible in Explorer. + +Create destination folder: + If checked, FreeMove will create the target folder automatically when needed. + +Settings → Check for update: + - Check now: Manually check GitHub for a newer version. + - Check on program start: If enabled, FreeMove will automatically check for updates when it starts. + +Settings → Permission check: + - None: Don't check any file before moving (fastest, but may fail later if permissions are missing). + - Fast: Check .exe and .dll files before moving (default). + - Full: Check all files before moving (slowest, but most thorough). + +Settings → Safe mode: + Prevents moving critical system folders (such as Program Files). It is strongly recommended to keep this enabled. + +Info → Report an Issue: + Open the GitHub page to report a bug or request a feature. + +Info → GitHub: + Open the project page on GitHub. + +Info → About: + Show information about FreeMove and its license. + +Language: + - English / Chinese: Switch the user interface language (the application will restart to apply the change). + \ No newline at end of file diff --git a/FreeMove/Properties/Resources.zh-Hans.resx b/FreeMove/Properties/Resources.zh-Hans.resx new file mode 100644 index 0000000..d8fd074 --- /dev/null +++ b/FreeMove/Properties/Resources.zh-Hans.resx @@ -0,0 +1,368 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + + imDema/FreeMove {0} —— 移动目录而不破坏快捷方式或安装 +版权所有 (C) 2020 Luca De Martini + +本程序是自由软件:您可以在 GNU 通用公共许可证(GPL)第 3 版或(由您选择)任何更新版本的条款下重新分发和/或修改本程序。 + +本程序的发布希望它能带来帮助,但不提供任何担保;甚至不包括适销性或适用于特定目的的默示担保。 + +您应已随本程序一起收到 GNU 通用公共许可证的副本;如果没有,请参见 <http://www.gnu.org/licenses/>。 + +https://github.com/imDema + + + + 强烈不建议移动 “Program Files” 或 “Program Files (x86)” 目录,否则可能导致系统行为异常。 +推荐只移动这些目录中的具体程序文件夹。 + +确定要关闭安全模式吗? + + + + 创建符号链接时出错。 +文件夹已经移动到新位置,但无法创建链接。 +请尝试以管理员身份运行程序。 + +要把文件移回原位置吗? + + + + 移动文件时发生错误,某些文件可能正在被占用,或者您没有足够的权限。 + +请尝试以管理员身份运行本程序,并关闭正在使用该文件的其他程序。 + +详细信息: + + + + 错误:{0} + +如何继续? +“中止” 将撤销更改 +“忽略” 将停止程序 + + + + 无法从 GitHub 服务器获取版本信息 + + + + 确定要继续吗? + +如果选择忽略,文件将保持当前状态:部分文件已经在新位置,且在旧位置中缺失! + + + + 在 {0} 使用 FreeMove 移动文件时发生错误,并且您选择了“忽略”。 +此目录的其余内容可在 “{1}” 中找到(除非已经被再次移动)。 +下次在发生错误时,请使用 “中止” 将文件移回,或使用 “重试” 再试一次。 + +如果这个文本文件对您有帮助,或者您希望它不要被创建,请告诉我。 + + + + ImDema-FreeMove-Updater + + + + + + 完成! + + + + 错误 + + + + 无法删除已复制的内容,请尝试手动删除。 + + + + 无法将内容移回原位置,请尝试手动移动。 + + + + 详细信息: +{0} + + + + 要撤销这些更改吗? + +详细信息: +{0} + + + + 要撤销这些更改吗? + + + + 已取消 + + + + 确定要取消正在进行的操作吗? + + + + 取消确认 + + + + 选择要移动的文件夹 + + + + 选择目标位置 + + + + 选择是否隐藏在原位置创建的快捷方式(链接) + + + + 错误详情 + + + + 关于 FreeMove + + + + 警告 + + + + 正在移动文件... + + + + 正在完成... + + + + 语言已更改,程序将重新启动以应用新的语言设置。 + + + + 语言 + + + + Free Move + + + + 源文件夹: + + + + 目标位置: + + + + 浏览... + + + + 开始移动 + + + + 关闭 + + + + 将原位置的文件夹设为隐藏 + + + + 自动创建目标文件夹 + + + + 设置 + + + + 信息 + + + + 语言 + + + + 检查更新 + + + + 立即检查 + + + + 启动时检查 + + + + 权限检查 + + + + 安全模式 + + + + 不检查 + + + + 快速 + + + + 完全 + + + + 反馈问题 + + + + GitHub + + + + 关于 + + + + 英文 + + + + 简体中文 + + + + 本程序需要以管理员身份运行才能移动文件夹并创建链接。 + +请右键单击可执行文件,选择“以管理员身份运行”。 + + + + 需要管理员权限 + + + + 帮助 + + + + FreeMove 使用说明 + +源文件夹: 选择你要移动的文件夹(例如 Program Files 下的某个程序目录)。 +目标位置: 选择要把该文件夹移动到的目标路径(例如另一块磁盘)。 +浏览...: 打开文件夹选择对话框,用来选择源或目标文件夹。 + +开始移动: 开始将所选文件夹移动到目标位置,并在原路径创建一个目录链接(junction)。 +关闭: 关闭程序窗口。 + +将原位置的文件夹设为隐藏: + 移动完成后,把原位置创建的链接设为“隐藏”,在资源管理器中不明显显示。 + +自动创建目标文件夹: + 如果勾选,在需要时自动创建目标文件夹。 + +设置 → 检查更新: + - 立即检查: 立刻连接 GitHub 检查是否有新版本。 + - 启动时检查: 每次启动 FreeMove 时自动检查是否有新版本。 + +设置 → 权限检查: + - 不检查: 不预先检查任何文件权限(速度最快,但可能在后面操作时才失败)。 + - 快速: 只预检查 .exe 和 .dll 文件的权限(默认)。 + - 完全: 预检查所有文件的权限(最慢,但最安全)。 + +设置 → 安全模式: + 阻止移动关键系统目录(例如 Program Files)。强烈建议保持开启。 + +信息 → 反馈问题: + 打开 GitHub 的 Issue 页面,用于反馈 Bug 或提出建议。 + +信息 → GitHub: + 打开本项目的 GitHub 主页。 + +信息 → 关于: + 显示 FreeMove 的版本和授权信息。 + +语言: + - 英文 / 简体中文:切换界面语言(程序将重启以应用新的语言)。 + + + + diff --git a/FreeMove/Properties/Settings.Designer.cs b/FreeMove/Properties/Settings.Designer.cs index 84c6380..f2f2af5 100644 --- a/FreeMove/Properties/Settings.Designer.cs +++ b/FreeMove/Properties/Settings.Designer.cs @@ -1,10 +1,10 @@ //------------------------------------------------------------------------------ // -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 +// 此代码由工具生成。 +// 运行时版本:4.0.30319.42000 // -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. +// 对此文件的更改可能会导致不正确的行为,并且如果 +// 重新生成代码,这些更改将会丢失。 // //------------------------------------------------------------------------------ @@ -12,7 +12,7 @@ namespace FreeMove.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.1.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.13.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/FreeMove/Settings.cs b/FreeMove/Settings.cs index 9f2cb54..bf32b33 100644 --- a/FreeMove/Settings.cs +++ b/FreeMove/Settings.cs @@ -39,6 +39,9 @@ public enum PermissionCheckLevel public PermissionCheckLevel PermissionCheck = PermissionCheckLevel.Fast; + // UI language code, e.g. "en", "zh-Hans". null/empty = follow system language + public string LanguageCode = null; + public static bool AutoUpdate { set @@ -69,6 +72,21 @@ public static PermissionCheckLevel PermCheck } } + public static string Language + { + get + { + var LSett = Load(); + return LSett.LanguageCode; + } + set + { + var LSett = Load(); + LSett.LanguageCode = value; + Save(LSett); + } + } + private static void Save(Settings set) { XmlSerializer ser = new XmlSerializer(typeof(Settings)); @@ -86,10 +104,27 @@ private static Settings Load() if (File.Exists(GetSavePath())) { - using (FileStream fs = File.OpenRead(GetSavePath())) + try + { + using (FileStream fs = File.OpenRead(GetSavePath())) + { + XmlSerializer ser = new XmlSerializer(typeof(Settings)); + LoadedSettings = ser.Deserialize(fs) as Settings; + } + } + catch (InvalidOperationException) { - XmlSerializer ser = new XmlSerializer(typeof(Settings)); - LoadedSettings = ser.Deserialize(fs) as Settings; + // 配置文件格式与当前 Settings 不兼容(例如旧版本保存为 bool 的值现在改成了枚举) + // 删除损坏/旧格式配置文件,回退到默认设置 + try + { + File.Delete(GetSavePath()); + } + catch + { + // 忽略删除失败,使用默认设置继续运行 + } + LoadedSettings = null; } }