diff --git a/Ultima/Maps/MapSizes.cs b/Ultima/Maps/MapSizes.cs
index e7b4126d..56e1bffa 100644
--- a/Ultima/Maps/MapSizes.cs
+++ b/Ultima/Maps/MapSizes.cs
@@ -17,6 +17,17 @@
namespace Ultima.Maps
{
+ ///
+ /// Static helper for localizing map detection messages.
+ ///
+ public static class MapSizesLocalization
+ {
+ ///
+ /// Optional localization getter for error messages (set by main application).
+ ///
+ public static Func? LocalizationGetter { get; set; }
+ }
+
public readonly struct MapSize : IEquatable
{
public MapSize(int width, int height)
@@ -135,9 +146,9 @@ private static bool TryDetect(Func resolve, int fileIndex, out M
if (!TryMeasureBlocks(resolve, fileIndex, out long blocks, out string source))
{
size = Fallback(fileIndex);
- evidence = string.Format(CultureInfo.InvariantCulture,
- "no map or statics index found for facet {0}; assuming {1}", fileIndex, size);
-
+ string template = MapSizesLocalization.LocalizationGetter?.Invoke("Ultima.Maps.MapSizes.NoMapOrStaticsIndex")
+ ?? "no map or statics index found for facet {0}; assuming {1}";
+ evidence = string.Format(CultureInfo.InvariantCulture, template, fileIndex, size);
return false;
}
@@ -149,17 +160,16 @@ private static bool TryDetect(Func resolve, int fileIndex, out M
}
size = candidate;
- evidence = string.Format(CultureInfo.InvariantCulture,
- "{0} holds {1:N0} blocks, which is {2}", source, blocks, candidate);
-
+ string template1 = MapSizesLocalization.LocalizationGetter?.Invoke("Ultima.Maps.MapSizes.HoldsBlocks")
+ ?? "{0} holds {1:N0} blocks, which is {2}";
+ evidence = string.Format(CultureInfo.InvariantCulture, template1, source, blocks, candidate);
return true;
}
size = Fallback(fileIndex);
- evidence = string.Format(CultureInfo.InvariantCulture,
- "{0} holds {1:N0} blocks, which matches no known shape for facet {2}; assuming {3}",
- source, blocks, fileIndex, size);
-
+ string template2 = MapSizesLocalization.LocalizationGetter?.Invoke("Ultima.Maps.MapSizes.HoldsBlocksNoMatch")
+ ?? "{0} holds {1:N0} blocks, which matches no known shape for facet {2}; assuming {3}";
+ evidence = string.Format(CultureInfo.InvariantCulture, template2, source, blocks, fileIndex, size);
return false;
}
diff --git a/UoFiddler.Controls/Classes/ClientFileSaveCommand.cs b/UoFiddler.Controls/Classes/ClientFileSaveCommand.cs
index a87d79ba..6fbad45a 100644
--- a/UoFiddler.Controls/Classes/ClientFileSaveCommand.cs
+++ b/UoFiddler.Controls/Classes/ClientFileSaveCommand.cs
@@ -91,7 +91,35 @@ public static bool Run(Control owner, FileType type, Action writeMul, st
Options.ChangedUltimaClass[dirtyKey] = false;
}
- FileSavedDialog.Show(owner?.FindForm(), outputDirectory, BuildMessage(result));
+ // 尝试通过反射访问 LocalizationService 来获取汉化
+ Func getLocalized = null;
+ try
+ {
+ var localizationServiceType = Type.GetType("UoFiddler.Localization.LocalizationService, UoFiddler");
+ if (localizationServiceType != null)
+ {
+ var getStringMethod = localizationServiceType.GetMethod("GetString",
+ System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ if (getStringMethod != null)
+ {
+ getLocalized = key => (string?)getStringMethod.Invoke(null, new object[] { key });
+ }
+ }
+ }
+ catch { }
+
+ string title = "Saved";
+ if (getLocalized != null)
+ {
+ var localizedTitle = getLocalized("Forms.FileSavedDialog.Title");
+ if (localizedTitle != null)
+ title = localizedTitle;
+ }
+
+ if (getLocalized != null)
+ FileSavedDialog.Show(owner?.FindForm(), outputDirectory, BuildMessage(result), title, getLocalized);
+ else
+ FileSavedDialog.Show(owner?.FindForm(), outputDirectory, BuildMessage(result));
return true;
}
@@ -133,7 +161,35 @@ private static bool ConfirmPreflight(Control owner, FileType type, ContainerForm
sb.AppendLine().AppendLine().Append("Save anyway?");
- return MessageBox.Show(owner?.FindForm(), sb.ToString(), "Save", MessageBoxButtons.YesNo,
+ // 尝试获取汉化文本
+ string confirmTitle = "Save";
+ string confirmQuestion = "Save anyway?";
+ try
+ {
+ var localizationServiceType = Type.GetType("UoFiddler.Localization.LocalizationService, UoFiddler");
+ if (localizationServiceType != null)
+ {
+ var getStringMethod = localizationServiceType.GetMethod("GetString",
+ System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ if (getStringMethod != null)
+ {
+ var localizedTitle = getStringMethod.Invoke(null, new object[] { "Forms.ClientFileSaveCommand.SaveConfirmTitle" });
+ if (localizedTitle is string title)
+ confirmTitle = title;
+
+ var localizedQuestion = getStringMethod.Invoke(null, new object[] { "Forms.ClientFileSaveCommand.SaveAnywayQuestion" });
+ if (localizedQuestion is string question)
+ confirmQuestion = question;
+ }
+ }
+ }
+ catch { }
+
+ // 替换英文问题为汉化版本
+ sb.Length -= "Save anyway?".Length;
+ sb.Append(confirmQuestion);
+
+ return MessageBox.Show(owner?.FindForm(), sb.ToString(), confirmTitle, MessageBoxButtons.YesNo,
MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) == DialogResult.Yes;
}
@@ -183,7 +239,25 @@ private static void ShowError(Control owner, FileType type, Exception error)
sb.AppendLine(where);
}
- MessageBox.Show(owner?.FindForm(), sb.ToString(), "Save failed", MessageBoxButtons.OK,
+ string errorTitle = "Save failed";
+ try
+ {
+ var localizationServiceType = Type.GetType("UoFiddler.Localization.LocalizationService, UoFiddler");
+ if (localizationServiceType != null)
+ {
+ var getStringMethod = localizationServiceType.GetMethod("GetString",
+ System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ if (getStringMethod != null)
+ {
+ var localizedTitle = getStringMethod.Invoke(null, new object[] { "Forms.ClientFileSaveCommand.SaveFailedTitle" });
+ if (localizedTitle is string title)
+ errorTitle = title;
+ }
+ }
+ }
+ catch { }
+
+ MessageBox.Show(owner?.FindForm(), sb.ToString(), errorTitle, MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
diff --git a/UoFiddler.Controls/Forms/AnimDataExportForm.cs b/UoFiddler.Controls/Forms/AnimDataExportForm.cs
index 19eac838..6b610dc4 100644
--- a/UoFiddler.Controls/Forms/AnimDataExportForm.cs
+++ b/UoFiddler.Controls/Forms/AnimDataExportForm.cs
@@ -8,6 +8,8 @@ namespace UoFiddler.Controls.Forms
{
public partial class AnimDataExportForm : Form
{
+ private Func? _localizationGetter;
+
public AnimDataExportForm()
{
InitializeComponent();
@@ -18,6 +20,30 @@ public AnimDataExportForm()
};
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.AnimDataExportForm.Title") ?? "Export AnimData";
+ lblAnimationsToExport.Text = _localizationGetter("Forms.AnimDataExportForm.lblAnimationsToExport") ?? "Animations to export:";
+ btnExport.Text = _localizationGetter("Forms.AnimDataExportForm.btnExport") ?? "Export";
+
+ // 更新下拉菜单项
+ var items = new List
+ {
+ _localizationGetter("Forms.AnimDataExportForm.ExportSelection.All") ?? "All (default-, blue-, and red-colored entries)",
+ _localizationGetter("Forms.AnimDataExportForm.ExportSelection.IncludeMissing") ?? "Include missing animation tile flag (default- and blue-colored entries)",
+ _localizationGetter("Forms.AnimDataExportForm.ExportSelection.OnlyValid") ?? "Only valid animations (default-colored entries)"
+ };
+ cboExportSelection.DataSource = items;
+ }
+
private void OnClickExport(object sender, EventArgs e)
{
var type = "json";
@@ -48,11 +74,18 @@ private void OnClickExport(object sender, EventArgs e)
var exported = ExportedAnimData.ToFile(dialog.FileName, AnimData, selection);
- MessageBox.Show($"Exported {exported.Data.Count} animdata entries to: {dialog.FileName}");
+ // 使用汉化的导出成功消息
+ string successMessage = _localizationGetter?.Invoke("Forms.AnimDataExportForm.ExportSuccessMessage") ?? $"Exported {exported.Data.Count} animdata entries to: {dialog.FileName}";
+ successMessage = string.Format(successMessage, exported.Data.Count, dialog.FileName);
+ MessageBox.Show(successMessage);
}
catch (Exception ex)
{
- MessageBox.Show($"Error exporting animdata: {ex.Message}", "AnimData Export", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
+ // 使用汉化的导出错误消息
+ string errorTitle = _localizationGetter?.Invoke("Forms.AnimDataExportForm.ExportErrorTitle") ?? "AnimData Export";
+ string errorMessage = _localizationGetter?.Invoke("Forms.AnimDataExportForm.ExportErrorMessage") ?? $"Error exporting animdata: {ex.Message}";
+ errorMessage = string.Format(errorMessage, ex.Message);
+ MessageBox.Show(errorMessage, errorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
}
diff --git a/UoFiddler.Controls/Forms/AnimDataImportForm.cs b/UoFiddler.Controls/Forms/AnimDataImportForm.cs
index 3081a939..fdd87786 100644
--- a/UoFiddler.Controls/Forms/AnimDataImportForm.cs
+++ b/UoFiddler.Controls/Forms/AnimDataImportForm.cs
@@ -9,6 +9,8 @@ namespace UoFiddler.Controls.Forms
{
public partial class AnimDataImportForm : Form
{
+ private Func? _localizationGetter;
+
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Action OnAfterImport { get; set; }
@@ -18,13 +20,40 @@ public AnimDataImportForm()
cboConflictAction.SelectedItem = "skip";
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.AnimDataImportForm.Title") ?? "Import AnimData";
+ label5.Text = _localizationGetter("Forms.AnimDataImportForm.label5") ?? "Import from:";
+ btnImport.Text = _localizationGetter("Forms.AnimDataImportForm.btnImport") ?? "Import";
+ label1.Text = _localizationGetter("Forms.AnimDataImportForm.label1") ?? "On conflict:";
+ cbErase.Text = _localizationGetter("Forms.AnimDataImportForm.cbErase") ?? "Erase animdata before importing";
+
+ // 更新下拉菜单项
+ var skipText = _localizationGetter("Forms.AnimDataImportForm.ConflictAction.Skip") ?? "skip";
+ var overwriteText = _localizationGetter("Forms.AnimDataImportForm.ConflictAction.Overwrite") ?? "overwrite";
+
+ cboConflictAction.Items.Clear();
+ cboConflictAction.Items.Add(skipText);
+ cboConflictAction.Items.Add(overwriteText);
+ cboConflictAction.SelectedIndex = 0;
+ }
+
private void OnClickImport(object sender, EventArgs e)
{
try
{
var fileName = txtImportFileName.Text;
var imported = ExportedAnimData.FromFile(fileName);
- var overwrite = cboConflictAction.Items[cboConflictAction.SelectedIndex].ToString() == "overwrite";
+ // SelectedIndex: 0 = skip, 1 = overwrite
+ var overwrite = cboConflictAction.SelectedIndex == 1;
// Create a new "working copy" AnimData to update, in case there's an exception thrown while processing.
// Shallow clone is okay, as UpdateAnimdata does not modify existing entries' members.
@@ -44,11 +73,18 @@ private void OnClickImport(object sender, EventArgs e)
// Swallow any error from the OnAfterImport callback
}
- MessageBox.Show($"Imported {importCount} animdata entries from: {fileName}\n\nDo not forget to save your changes!", "AnimData Import");
+ MessageBox.Show(
+ _localizationGetter?.Invoke("Forms.AnimDataImportForm.ImportSuccessMessage") ??
+ $"Imported {importCount} animdata entries from: {fileName}\n\nDo not forget to save your changes!",
+ _localizationGetter?.Invoke("Forms.AnimDataImportForm.ImportSuccessTitle") ?? "AnimData Import");
}
catch (Exception ex)
{
- MessageBox.Show($"Error importing animdata: {ex.Message}", "AnimData Import", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
+ var errorTitle = _localizationGetter?.Invoke("Forms.AnimDataImportForm.ImportErrorTitle") ?? "AnimData Import";
+ var errorMessageFormat = _localizationGetter?.Invoke("Forms.AnimDataImportForm.ImportErrorMessage") ?? "Error importing animdata: {0}";
+ var errorMessage = string.Format(errorMessageFormat, ex.Message);
+
+ MessageBox.Show(errorMessage, errorTitle, MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
diff --git a/UoFiddler.Controls/Forms/AnimationEditForm.Designer.cs b/UoFiddler.Controls/Forms/AnimationEditForm.Designer.cs
index b0a1642f..24187b16 100644
--- a/UoFiddler.Controls/Forms/AnimationEditForm.Designer.cs
+++ b/UoFiddler.Controls/Forms/AnimationEditForm.Designer.cs
@@ -1089,7 +1089,7 @@ private void InitializeComponent()
// SecondAnimColorComboBox
//
SecondAnimColorComboBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
- SecondAnimColorComboBox.Items.AddRange(new object[] { "Original", "Green", "Magenta", "Cyan", "Red", "Custom…" });
+ SecondAnimColorComboBox.Items.AddRange(new object[] { "原始", "绿色", "洋红色", "青色", "红色", "自定义…" });
SecondAnimColorComboBox.Location = new System.Drawing.Point(9, 98);
SecondAnimColorComboBox.Name = "SecondAnimColorComboBox";
SecondAnimColorComboBox.Size = new System.Drawing.Size(172, 23);
@@ -1211,7 +1211,7 @@ private void InitializeComponent()
// AnimationSpeedTrackBar
//
AnimationSpeedTrackBar.AutoSize = false;
- AnimationSpeedTrackBar.Location = new System.Drawing.Point(48, 22);
+ AnimationSpeedTrackBar.Location = new System.Drawing.Point(48, 35);
AnimationSpeedTrackBar.Margin = new System.Windows.Forms.Padding(4, 3, 4, 3);
AnimationSpeedTrackBar.Maximum = 14;
AnimationSpeedTrackBar.Name = "AnimationSpeedTrackBar";
diff --git a/UoFiddler.Controls/Forms/AnimationEditForm.cs b/UoFiddler.Controls/Forms/AnimationEditForm.cs
index 89006bfc..020347ca 100644
--- a/UoFiddler.Controls/Forms/AnimationEditForm.cs
+++ b/UoFiddler.Controls/Forms/AnimationEditForm.cs
@@ -38,6 +38,8 @@ public partial class AnimationEditForm : Form
private float _zoomFactor = 1.0f;
+ private Func? _localizationGetter;
+
// Second-animation overlay state
private bool _secondAnimActivated;
private int _secondAnimId;
@@ -114,8 +116,109 @@ public AnimationEditForm()
_loaded = false;
}
+ public void SetLocalization(Func? getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // Tab pages
+ FramePage.Text = _localizationGetter("Forms.AnimationEditForm.Tabs.Frame") ?? "Frame";
+ AnimationEditPage.Text = _localizationGetter("Forms.AnimationEditForm.Tabs.PreviewEdit") ?? "Preview/Edit";
+ GalleryPage.Text = _localizationGetter("Forms.AnimationEditForm.Tabs.Gallery") ?? "Gallery";
+
+ // TreeView context menu
+ addToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.Replace") ?? "Replace";
+ removeToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.Remove") ?? "Remove";
+ extractImagesToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExtractImages") ?? "Extract Images..";
+ asBmpToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExtractAsFormats.Bmp") ?? "As Bmp";
+ asTiffToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExtractAsFormats.Tiff") ?? "As Tiff";
+ asJpgToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExtractAsFormats.Jpg") ?? "As Jpg";
+ asPngToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExtractAsFormats.Png") ?? "As Png";
+ importToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.Import") ?? "Import..";
+ fromvdToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ImportFromVD") ?? "From .vd";
+ exportToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.Export") ?? "Export..";
+ tovdToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.TreeViewContextMenu.ExportToVD") ?? "To .vd";
+
+ // Palette context menu
+ exportToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.Export") ?? "Export..";
+ bmpToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ExportBmp") ?? "Bmp";
+ tiffToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ExportTiff") ?? "Tiff";
+ textToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ExportText") ?? "Text";
+ importToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.Import") ?? "Import..";
+ fromTxtToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ImportFromTxt") ?? "From Txt";
+ fromGifToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ImportFromGif") ?? "From Gif";
+ fromImageToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.PaletteContextMenu.ImportFromImage") ?? "From Image";
+
+ // Frames list view context menu
+ allDirectionsAddToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.AllDirectionsAdd") ?? "All directions add";
+ allDirectionsAddWithCanvasToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.AllDirectionsAddWithCanvas") ?? "All directions add with Canvas";
+ addDirectionsAddWithCanvasUniqueImageToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.AllDirectionsAddWithCanvasCv5GifStyle") ?? "All directions add with Canvas ( CV5 Gif Style )";
+ allDirectionsAddWithCanvasKRframeEditorColorCorrectorToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.AllDirectionsAddWithCanvasKRColorCorrector") ?? "All directions add with Canvas ( KRframeViewer Color Corrector)";
+ addToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.Add") ?? "Add";
+ addWithCanvasToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.AddWithCanvas") ?? "Add with Canvas";
+ replaceToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.Replace") ?? "Replace";
+ removeToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationEditForm.FramesListViewContextMenu.Remove") ?? "Remove";
+
+ // Frame page controls
+ groupBox1.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ExtraBackground") ?? "Extra background";
+ BackgroundRedLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.BackgroundRed") ?? "R";
+ BackgroundGreenLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.BackgroundGreen") ?? "G";
+ BackgroundBlueLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.BackgroundBlue") ?? "B";
+ groupBox2.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.PaletteConverter") ?? "Palette converter";
+ SetPalleteButton.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.SetPallete") ?? "Set";
+ rbRGB.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.RGB") ?? "RGB";
+ rbRBG.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.RBG") ?? "RBG";
+ rbGRB.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.GRB") ?? "GRB";
+ rbGBR.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.GBR") ?? "GBR";
+ rbBGR.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.BGR") ?? "BGR";
+ rbBRG.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorModes.BRG") ?? "BRG";
+ groupBox3.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorBalance") ?? "Color balance";
+ ColorRedLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorRed") ?? "R";
+ ColorGreenLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorGreen") ?? "G";
+ ColorBlueLabel.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ColorBlue") ?? "B";
+ ApplyButton.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.ApplyButton") ?? "Apply";
+ LockColorControlsCheckBox.Text = _localizationGetter("Forms.AnimationEditForm.FramePage.LockColorControls") ?? "Lock";
+
+ // Animation Edit page controls
+ ZoomLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.Zoom") ?? "Zoom:";
+ DrawFullRectangleToolStripButton.ToolTipText = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.DrawFullRectangle") ?? "Draw Full Rectangle";
+ DrawEmptyRectangleToolStripButton.ToolTipText = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.DrawEmptyRectangle") ?? "Draw Empty Rectangle";
+ DrawReferencialPointToolStripButton.ToolTipText = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.DrawReferencialPoint") ?? "Draw Referencial Point";
+ SecondAnimGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SecondAnimOverlay") ?? "Second Animation Overlay";
+ SecondAnimCheckBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.ShowOverlay") ?? "Show overlay";
+ SecondAnimIdLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SecondAnimFileId") ?? "ID";
+ SecondAnimOpacityLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SecondAnimOpacity") ?? "Opacity";
+ SecondAnimInFrontCheckBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.OnTop") ?? "On top";
+ SecondAnimBoxCheckBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.Box") ?? "Box";
+ FramesGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.AnimationFrames") ?? "Animation Frames";
+ SpeedGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.AnimationSpeed") ?? "Animation Speed";
+ LocationCenterGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.LocationCenter") ?? "Location Center";
+ CenterXLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.CenterX") ?? "X";
+ CenterYLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.CenterY") ?? "Y";
+ SameCenterButton.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SameCenter") ?? "Same Center";
+ ReferencialPointGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.ReferencialPoint") ?? "Referencial Point";
+ RefXLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.RefX") ?? "X";
+ RefYLabel.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.RefY") ?? "Y";
+ ToolStripLockButton.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.LockButton") ?? "Lock";
+ CoordinatesGroupBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.Coordinates") ?? "Coordinates";
+ SetCoordinatesButton.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SetCoordinates") ?? "Set";
+ SaveCoordinatesCheckBox.Text = _localizationGetter("Forms.AnimationEditForm.AnimationEditPage.SaveCoordinates") ?? "Save";
+
+ // Status bar items
+ SaveToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.StatusBar.SaveMenuItem") ?? "Save";
+ ShowOnlyValidToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.StatusBar.ShowOnlyValidMenuItem") ?? "Show Only Valid";
+ ExportAllToVDToolStripMenuItem.Text = _localizationGetter("Forms.AnimationEditForm.StatusBar.ExportAllToVD") ?? "Export All Valid To VD";
+ MiscToolStripButton.Text = _localizationGetter("Forms.AnimationEditForm.StatusBar.MiscButton") ?? "Misc";
+ }
+
// Indexed by MobType enum: Monster=0, Sea=1, Animal=2, Human=3, Equipment=4.
// Equipment composites onto a humanoid and shares the human action set.
+
private readonly string[][] _animNames =
{
new[] // Monster (22)
@@ -1313,7 +1416,7 @@ private void OnClickSave(object sender, EventArgs e)
AnimationEdit.Save(_fileType, Options.OutputPath);
Options.ChangedUltimaClass["Animations"] = false;
- MessageBox.Show($"AnimationFile saved to {Options.OutputPath}", "Saved", MessageBoxButtons.OK,
+ MessageBox.Show($"动画文件已保存到 {Options.OutputPath}", "已保存", MessageBoxButtons.OK,
MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
@@ -2806,8 +2909,8 @@ private void OnClickExportAllToVD(object sender, EventArgs e)
AnimationEdit.ExportToVD(_fileType, index, fileName);
}
- MessageBox.Show($"All Animations saved to {dialog.SelectedPath}",
- "Export", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
+ MessageBox.Show($"所有动画已保存到 {dialog.SelectedPath}",
+ "全部导出到VD", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
}
diff --git a/UoFiddler.Controls/Forms/AnimationListNewEntriesForm.cs b/UoFiddler.Controls/Forms/AnimationListNewEntriesForm.cs
index 3668631f..cfe5cac6 100644
--- a/UoFiddler.Controls/Forms/AnimationListNewEntriesForm.cs
+++ b/UoFiddler.Controls/Forms/AnimationListNewEntriesForm.cs
@@ -26,6 +26,7 @@ public partial class AnimationListNewEntriesForm : Form
private readonly string[][] _actionNames;
private readonly Func _isAlreadyDefinedCallback;
private readonly Action _addGraphicAction;
+ private readonly Func _localizationGetter;
private int _currentSelect;
private int _facing = 1;
@@ -35,8 +36,10 @@ public partial class AnimationListNewEntriesForm : Form
private AnimationFrame[] _animation;
public AnimationListNewEntriesForm(Func isAlreadyDefinedCallback,
- Action addGraphicAction, string[][] actionNames)
+ Action addGraphicAction, string[][] actionNames, Func localizationGetter = null)
{
+ _localizationGetter = localizationGetter;
+
InitializeComponent();
Icon = Options.GetFiddlerIcon();
@@ -190,6 +193,31 @@ private void OnLoad(object sender, EventArgs e)
}
tvAnimationList.EndUpdate();
+
+ // 应用汉化
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null)
+ return;
+
+ Text = _localizationGetter("Forms.AnimationListControl.NewEntriesForm.Title") ?? "Animationlist New Entries";
+ toolStripButton1.Text = _localizationGetter("Forms.AnimationListControl.NewEntriesForm.AddButton") ?? "Add";
+ animateToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.NewEntriesForm.AnimateMenuitem") ?? "Animate";
+
+ // 更新下拉框选项
+ string[] actionTypes = new[]
+ {
+ _localizationGetter("Forms.AnimationListControl.NewEntriesForm.ActionTypes.Monster") ?? "Monster",
+ _localizationGetter("Forms.AnimationListControl.NewEntriesForm.ActionTypes.SeaMonster") ?? "Sea Monster",
+ _localizationGetter("Forms.AnimationListControl.NewEntriesForm.ActionTypes.Animal") ?? "Animal",
+ _localizationGetter("Forms.AnimationListControl.NewEntriesForm.ActionTypes.HumanEquipment") ?? "Human/Equipment"
+ };
+
+ ComboBoxActionType.Items.Clear();
+ ComboBoxActionType.Items.AddRange(actionTypes);
}
private void ProcessBodyConverterTable(IEnumerable table)
diff --git a/UoFiddler.Controls/Forms/FileSavedDialog.cs b/UoFiddler.Controls/Forms/FileSavedDialog.cs
index aebcb92d..52711bf1 100644
--- a/UoFiddler.Controls/Forms/FileSavedDialog.cs
+++ b/UoFiddler.Controls/Forms/FileSavedDialog.cs
@@ -13,6 +13,7 @@ namespace UoFiddler.Controls.Forms
public sealed partial class FileSavedDialog : Form
{
private readonly string _filePath;
+ private Func? _localizationGetter;
public FileSavedDialog(string filePath, string message = null, string title = null)
{
@@ -32,6 +33,37 @@ public FileSavedDialog(string filePath, string message = null, string title = nu
pathLabel.Text = _filePath;
}
+ ///
+ /// Sets the localization getter and applies localized text.
+ ///
+ public void SetLocalization(Func? getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// Applies localized text to UI elements.
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // Localize title
+ var title = _localizationGetter("Forms.FileSavedDialog.Title");
+ if (title != null)
+ Text = title;
+
+ // Localize status label if not already set to custom message
+ var saveSuccess = _localizationGetter("Forms.FileSavedDialog.SaveSuccess");
+ if (saveSuccess != null && statusLabel.Text == "File saved successfully.")
+ statusLabel.Text = saveSuccess;
+
+ // Localize buttons
+ buttonOpenFolder.Text = _localizationGetter("Forms.FileSavedDialog.OpenFolder") ?? "Open Folder";
+ buttonOk.Text = _localizationGetter("Forms.FileSavedDialog.OK") ?? "OK";
+ }
+
private void OnOpenFolderClick(object sender, EventArgs e)
{
try
@@ -74,6 +106,23 @@ public static void Show(IWin32Window owner, string filePath, string message = nu
}
}
+ ///
+ /// Shows the file saved dialog with localization support.
+ ///
+ /// The owner form.
+ /// The path to the saved file.
+ /// Optional custom success message.
+ /// Optional custom dialog title.
+ /// Localization getter function.
+ public static void Show(IWin32Window owner, string filePath, string message, string title, Func getLocalized)
+ {
+ using (var dialog = new FileSavedDialog(filePath, message, title))
+ {
+ dialog.SetLocalization(getLocalized);
+ dialog.ShowDialog(owner);
+ }
+ }
+
///
/// Shows the file saved dialog without an owner.
///
diff --git a/UoFiddler.Controls/Forms/HueEditForm.cs b/UoFiddler.Controls/Forms/HueEditForm.cs
index f3aebe5b..b8ff00ab 100644
--- a/UoFiddler.Controls/Forms/HueEditForm.cs
+++ b/UoFiddler.Controls/Forms/HueEditForm.cs
@@ -25,6 +25,7 @@ public partial class HueEditForm : Form
private int _selected;
private int _secondSel;
private Bitmap _preview;
+ private Func? _localizationGetter;
private int Selected
{
@@ -70,6 +71,45 @@ public HueEditForm(int index)
pictureBoxPreview.Image = new Bitmap(pictureBoxPreview.Width, pictureBoxPreview.Height);
}
+ ///
+ /// 设置本地化函数
+ ///
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // 窗口标题 - 动态生成,保持索引信息
+ var titleFormat = _localizationGetter("Forms.HueEditForm.Title") ?? "HueEdit";
+ int hueIndex = int.Parse(Text.Split('/')[0].Replace("HueEdit ", "").Trim());
+ Text = $"{titleFormat} {hueIndex} / 0x{hueIndex:X}";
+
+ // 按钮
+ ColorPickerButton.Text = _localizationGetter("Forms.HueEditForm.ColorPickerButton") ?? "Color Picker";
+ SaveButton.Text = _localizationGetter("Forms.HueEditForm.SaveButton") ?? "Save";
+ Spread.Text = _localizationGetter("Forms.HueEditForm.Spread") ?? "Linear Gradient";
+ ExpGradientButton.Text = _localizationGetter("Forms.HueEditForm.ExpGradientButton") ?? "Exp Gradient";
+ InverseButton.Text = _localizationGetter("Forms.HueEditForm.InverseButton") ?? "Inverse";
+ ModifyRangeButton.Text = _localizationGetter("Forms.HueEditForm.ModifyRangeButton") ?? "Modify Range";
+ SetColorButton.Text = _localizationGetter("Forms.HueEditForm.SetColorButton") ?? "Set color";
+
+ // 标签
+ RLabel.Text = _localizationGetter("Forms.HueEditForm.RLabel") ?? "R:";
+ GLabel.Text = _localizationGetter("Forms.HueEditForm.GLabel") ?? "G:";
+ BLabel.Text = _localizationGetter("Forms.HueEditForm.BLabel") ?? "B:";
+
+ // 菜单项
+ itemToolStripMenuItem.Text = _localizationGetter("Forms.HueEditForm.itemToolStripMenuItem") ?? "Item";
+ animationToolStripMenuItem.Text = _localizationGetter("Forms.HueEditForm.animationToolStripMenuItem") ?? "Animation";
+ gumpToolStripMenuItem.Text = _localizationGetter("Forms.HueEditForm.gumpToolStripMenuItem") ?? "Gump";
+ hueOnlyGreyToolStripMenuItem.Text = _localizationGetter("Forms.HueEditForm.hueOnlyGreyToolStripMenuItem") ?? "Hue only Grey";
+ }
+
private int GetIndex(int x)
{
return (int)(x * 1.0 / (pictureBox.Width * 1.0 / _colors.Length * 1.0));
diff --git a/UoFiddler.Controls/Forms/HuePopUpForm.cs b/UoFiddler.Controls/Forms/HuePopUpForm.cs
index 323c04aa..132d56e4 100644
--- a/UoFiddler.Controls/Forms/HuePopUpForm.cs
+++ b/UoFiddler.Controls/Forms/HuePopUpForm.cs
@@ -18,6 +18,7 @@ namespace UoFiddler.Controls.Forms
public partial class HuePopUpForm : Form
{
private readonly Action _changeHueAction;
+ private Func? _localizationGetter;
public HuePopUpForm(Action changeHueAction, int hue)
{
@@ -41,6 +42,25 @@ public HuePopUpForm(Action changeHueAction, int hue)
}
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.HuePopUpForm.Title") ?? "Hue Picker";
+ toolStripButton1.Text = _localizationGetter("Forms.HuePopUpForm.OkButton") ?? "OK";
+ toolStripButton2.Text = _localizationGetter("Forms.HuePopUpForm.ClearButton") ?? "Clear";
+ HueOnlyGray.Text = _localizationGetter("Forms.HuePopUpForm.HueOnlyGrayCheckBox") ?? "Hue Only Gray (+0x8000)";
+
+ // 为内部 HuesControl 调用汉化
+ control.SetLocalization(_localizationGetter);
+ }
+
private void Click_OK(object sender, EventArgs e)
{
int selected = control.Selected;
diff --git a/UoFiddler.Controls/Forms/MapClearStaticsForm.cs b/UoFiddler.Controls/Forms/MapClearStaticsForm.cs
index 6eebb53d..748ea5d7 100644
--- a/UoFiddler.Controls/Forms/MapClearStaticsForm.cs
+++ b/UoFiddler.Controls/Forms/MapClearStaticsForm.cs
@@ -19,6 +19,7 @@ public partial class MapClearStaticsForm : Form
{
private readonly Action _refreshMap;
private readonly Ultima.Map _map;
+ private Func? _localizationGetter;
public MapClearStaticsForm(Action refreshMap, Ultima.Map map)
{
@@ -35,6 +36,24 @@ public MapClearStaticsForm(Action refreshMap, Ultima.Map map)
numericUpDownY2.Maximum = map.Height;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapClearStaticsForm.Title") ?? "Clear Statics";
+ label2.Text = _localizationGetter("Forms.MapClearStaticsForm.X1Label") ?? "X1";
+ label3.Text = _localizationGetter("Forms.MapClearStaticsForm.Y1Label") ?? "Y1";
+ label4.Text = _localizationGetter("Forms.MapClearStaticsForm.X2Label") ?? "X2";
+ label5.Text = _localizationGetter("Forms.MapClearStaticsForm.Y2Label") ?? "Y2";
+ button1.Text = _localizationGetter("Forms.MapClearStaticsForm.ClearButton") ?? "Clear";
+ }
+
private void OnClickClear(object sender, EventArgs e)
{
int blockX1 = (int)numericUpDownX1.Value;
@@ -78,7 +97,9 @@ private void OnClickClear(object sender, EventArgs e)
_map.ResetCache();
- MessageBox.Show("Done", "Clear Static", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
+ string title = _localizationGetter?.Invoke("Forms.MapClearStaticsForm.DoneTitle") ?? "Clear Statics";
+ string message = _localizationGetter?.Invoke("Forms.MapClearStaticsForm.DoneMessage") ?? "Done";
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
_refreshMap();
}
diff --git a/UoFiddler.Controls/Forms/MapDefragStaticsForm.Designer.cs b/UoFiddler.Controls/Forms/MapDefragStaticsForm.Designer.cs
index dc1b8b0b..55de86a5 100644
--- a/UoFiddler.Controls/Forms/MapDefragStaticsForm.Designer.cs
+++ b/UoFiddler.Controls/Forms/MapDefragStaticsForm.Designer.cs
@@ -159,9 +159,9 @@ private void InitializeComponent()
//
// labelCeiling
//
- this.labelCeiling.Location = new System.Drawing.Point(244, 25);
+ this.labelCeiling.Location = new System.Drawing.Point(240, 25);
this.labelCeiling.Name = "labelCeiling";
- this.labelCeiling.Size = new System.Drawing.Size(50, 17);
+ this.labelCeiling.Size = new System.Drawing.Size(56, 17);
this.labelCeiling.TabIndex = 1;
this.labelCeiling.Text = "ceiling:";
//
diff --git a/UoFiddler.Controls/Forms/MapDefragStaticsForm.cs b/UoFiddler.Controls/Forms/MapDefragStaticsForm.cs
index 1223bdcf..5e254045 100644
--- a/UoFiddler.Controls/Forms/MapDefragStaticsForm.cs
+++ b/UoFiddler.Controls/Forms/MapDefragStaticsForm.cs
@@ -32,6 +32,10 @@ public sealed partial class MapDefragStaticsForm : Form
private const string DefaultCollapseIds = "0x1797-0x179C";
private readonly Map _map;
+ private Func? _localizationGetter;
+
+ private string[] _idCeilingOptions;
+ private string[] _outOfBlockOptions;
private CancellationTokenSource _cancellation;
private bool _lastRunUsedFilters;
@@ -45,10 +49,14 @@ public MapDefragStaticsForm(Map map, string outputPath)
_map = map ?? throw new ArgumentNullException(nameof(map));
- comboBoxIdCeiling.Items.AddRange(new object[] { "tiledata", "art", "legacy 0x3FFF" });
+ // 保存原始英文值用于业务逻辑
+ _idCeilingOptions = new[] { "tiledata", "art", "legacy 0x3FFF" };
+ _outOfBlockOptions = new[] { "Drop", "Mask to 0-7", "Keep" };
+
+ comboBoxIdCeiling.Items.AddRange(_idCeilingOptions);
comboBoxIdCeiling.SelectedIndex = 0;
- comboBoxOutOfBlock.Items.AddRange(new object[] { "Drop", "Mask to 0-7", "Keep" });
+ comboBoxOutOfBlock.Items.AddRange(_outOfBlockOptions);
comboBoxOutOfBlock.SelectedIndex = 0;
checkBoxDropInvalidIds.Checked = true;
@@ -66,6 +74,70 @@ public MapDefragStaticsForm(Map map, string outputPath)
ActiveControl = buttonAnalyze;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapDefragStaticsForm.Title") ?? "Defrag Statics";
+ groupBoxSource.Text = _localizationGetter("Forms.MapDefragStaticsForm.Source") ?? "Source";
+ checkBoxAllowTruncation.Text = _localizationGetter("Forms.MapDefragStaticsForm.AllowTruncation") ?? "Discard the blocks past the configured map size";
+ groupBoxFilters.Text = _localizationGetter("Forms.MapDefragStaticsForm.Filters") ?? "Filters";
+ checkBoxDropInvalidIds.Text = _localizationGetter("Forms.MapDefragStaticsForm.DropInvalidIds") ?? "Drop statics with an unknown item id";
+ labelCeiling.Text = _localizationGetter("Forms.MapDefragStaticsForm.Ceiling") ?? "ceiling:";
+ labelOutOfBlock.Text = _localizationGetter("Forms.MapDefragStaticsForm.OutOfBlock") ?? "Out-of-block x/y offsets:";
+ checkBoxDropInvalidZ.Text = _localizationGetter("Forms.MapDefragStaticsForm.DropInvalidZ") ?? "Drop statics at z = -128";
+ checkBoxNormalizeHue.Text = _localizationGetter("Forms.MapDefragStaticsForm.NormalizeHue") ?? "Normalize negative hues to 0";
+ checkBoxBelowTerrain.Text = _localizationGetter("Forms.MapDefragStaticsForm.BelowTerrain") ?? "Drop statics buried under the land tile (never drawn)";
+ checkBoxRemoveDuplicates.Text = _localizationGetter("Forms.MapDefragStaticsForm.RemoveDuplicates") ?? "Remove duplicates (same id, x, y and z)";
+ checkBoxDuplicatesHue.Text = _localizationGetter("Forms.MapDefragStaticsForm.DuplicatesHue") ?? "compare hue too (legacy)";
+ checkBoxCollapseStacks.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseStacks") ?? "Collapse stacked statics sharing a cell down to one";
+ labelCollapseFlags.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseFlags") ?? "flags:";
+ checkBoxCollapseWet.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseWet") ?? "Wet";
+ checkBoxCollapseSurface.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseSurface") ?? "Surface";
+ checkBoxCollapseIgnoreZ.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseIgnoreZ") ?? "ignore z";
+ labelCollapseIds.Text = _localizationGetter("Forms.MapDefragStaticsForm.CollapseIds") ?? "item ids:";
+ checkBoxSortTiles.Text = _localizationGetter("Forms.MapDefragStaticsForm.SortTiles") ?? "Sort the statics within each block";
+ groupBoxOutput.Text = _localizationGetter("Forms.MapDefragStaticsForm.Output") ?? "Output folder";
+ buttonBrowse.Text = _localizationGetter("Forms.MapDefragStaticsForm.BrowseButton") ?? "Browse...";
+ buttonAnalyze.Text = _localizationGetter("Forms.MapDefragStaticsForm.AnalyzeButton") ?? "Analyze";
+ buttonDefrag.Text = _localizationGetter("Forms.MapDefragStaticsForm.DefragButton") ?? "Defrag";
+ buttonCancel.Text = _localizationGetter("Forms.MapDefragStaticsForm.CancelButton") ?? "Cancel";
+ buttonClose.Text = _localizationGetter("Forms.MapDefragStaticsForm.CloseButton") ?? "Close";
+
+ // 汉化下拉菜单项 - 保存选中的原始值
+ string selectedIdCeilingValue = comboBoxIdCeiling.SelectedIndex >= 0 ? _idCeilingOptions[comboBoxIdCeiling.SelectedIndex] : _idCeilingOptions[0];
+ string selectedOutOfBlockValue = comboBoxOutOfBlock.SelectedIndex >= 0 ? _outOfBlockOptions[comboBoxOutOfBlock.SelectedIndex] : _outOfBlockOptions[0];
+
+ comboBoxIdCeiling.Items.Clear();
+ foreach (string option in _idCeilingOptions)
+ {
+ string displayText = _localizationGetter($"Forms.MapDefragStaticsForm.IdCeilingOptions.{option}") ?? option;
+ comboBoxIdCeiling.Items.Add(displayText);
+ }
+ // 恢复选中项(通过原始值查找索引)
+ int idCeilingIndex = System.Array.IndexOf(_idCeilingOptions, selectedIdCeilingValue);
+ comboBoxIdCeiling.SelectedIndex = Math.Max(0, idCeilingIndex);
+
+ comboBoxOutOfBlock.Items.Clear();
+ foreach (string option in _outOfBlockOptions)
+ {
+ string displayText = _localizationGetter($"Forms.MapDefragStaticsForm.OutOfBlockOptions.{option}") ?? option;
+ comboBoxOutOfBlock.Items.Add(displayText);
+ }
+ // 恢复选中项(通过原始值查找索引)
+ int outOfBlockIndex = System.Array.IndexOf(_outOfBlockOptions, selectedOutOfBlockValue);
+ comboBoxOutOfBlock.SelectedIndex = Math.Max(0, outOfBlockIndex);
+
+ // 重新生成源描述(包含动态消息)
+ DescribeSource();
+ }
+
///
/// Shows what is about to be read and how it lines up with the configured map size. The
/// engine performs the authoritative check; this is here so the mismatch is visible before
@@ -78,11 +150,17 @@ private void DescribeSource()
var sb = new StringBuilder();
- sb.AppendLine($"Facet {_map.FileIndex} map size {_map.Width} x {_map.Height} blocks {_map.Width >> 3} x {_map.Height >> 3}");
+ string facetLabel = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.Facet") ?? "Facet";
+ string mapSizeLabel = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.MapSize") ?? "map size";
+ string blocksLabel = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.Blocks") ?? "blocks";
+
+ sb.AppendLine($"{facetLabel} {_map.FileIndex} {mapSizeLabel} {_map.Width} x {_map.Height} {blocksLabel} {_map.Width >> 3} x {_map.Height >> 3}");
if (indexPath == null || staticsPath == null)
{
- sb.AppendLine($"staidx{_map.FileIndex}.mul or statics{_map.FileIndex}.mul was not found in the loaded client.");
+ string notFoundMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.FilesNotFound")
+ ?? "staidx{0}.mul or statics{0}.mul was not found in the loaded client.";
+ sb.AppendLine(string.Format(notFoundMsg, _map.FileIndex));
textBoxSource.Text = sb.ToString();
buttonAnalyze.Enabled = false;
@@ -99,7 +177,9 @@ private void DescribeSource()
if (File.Exists(Path.Combine(Path.GetDirectoryName(indexPath) ?? string.Empty, $"staidx{_map.FileIndex}x.mul")))
{
- sb.AppendLine($"staidx{_map.FileIndex}x.mul is present - the client prefers those override files over this pair.");
+ string overrideMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.OverridePresent")
+ ?? "staidx{0}x.mul is present - the client prefers those override files over this pair.";
+ sb.AppendLine(string.Format(overrideMsg, _map.FileIndex));
}
textBoxSource.Text = sb.ToString();
@@ -110,10 +190,9 @@ private void DescribeSource()
if (indexBlocks > configuredBlocks)
{
labelGeometry.ForeColor = Options.DarkMode ? Color.OrangeRed : Color.Red;
- labelGeometry.Text = string.Format(CultureInfo.InvariantCulture,
- "staidx holds {0:N0} blocks but the configured map size covers only {1:N0}." + Environment.NewLine +
- "The statics in the surplus blocks would be discarded.",
- indexBlocks, configuredBlocks);
+ string surplusMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.SurplusBlocks")
+ ?? "staidx holds {0:N0} blocks but the configured map size covers only {1:N0}. The statics in the surplus blocks would be discarded.";
+ labelGeometry.Text = string.Format(CultureInfo.InvariantCulture, surplusMsg, indexBlocks, configuredBlocks);
_truncationAvailable = true;
checkBoxAllowTruncation.Enabled = true;
@@ -121,16 +200,16 @@ private void DescribeSource()
else if (indexBlocks < configuredBlocks)
{
labelGeometry.ForeColor = SystemColors.ControlText;
- labelGeometry.Text = string.Format(CultureInfo.InvariantCulture,
- "staidx holds {0:N0} blocks, the configured map size covers {1:N0}." + Environment.NewLine +
- "The blocks past the end of the index will be written empty.",
- indexBlocks, configuredBlocks);
+ string emptyBlocksMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.EmptyBlocks")
+ ?? "staidx holds {0:N0} blocks, the configured map size covers {1:N0}. The blocks past the end of the index will be written empty.";
+ labelGeometry.Text = string.Format(CultureInfo.InvariantCulture, emptyBlocksMsg, indexBlocks, configuredBlocks);
}
else
{
labelGeometry.ForeColor = SystemColors.ControlText;
- labelGeometry.Text = string.Format(CultureInfo.InvariantCulture,
- "staidx holds {0:N0} blocks, matching the configured map size.", indexBlocks);
+ string matchingMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.Messages.MatchingBlocks")
+ ?? "staidx holds {0:N0} blocks, matching the configured map size.";
+ labelGeometry.Text = string.Format(CultureInfo.InvariantCulture, matchingMsg, indexBlocks);
}
}
@@ -301,7 +380,7 @@ private void Start(bool dryRun)
}
catch (Exception ex)
{
- MessageBox.Show(this, ex.Message, "Defrag Statics", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show(this, ex.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
@@ -316,7 +395,9 @@ private void Start(bool dryRun)
progressBar.Style = ProgressBarStyle.Continuous;
progressBar.Value = 0;
- labelStatus.Text = dryRun ? "Analyzing..." : "Defragging...";
+ string analyzingMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.StatusAnalyzing") ?? "Analyzing...";
+ string defraggingMsg = _localizationGetter?.Invoke("Forms.MapDefragStaticsForm.StatusDefragging") ?? "Defragging...";
+ labelStatus.Text = dryRun ? analyzingMsg : defraggingMsg;
worker.RunWorkerAsync(options);
}
@@ -375,7 +456,7 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
labelStatus.Text = "Failed.";
progressBar.Value = 0;
- MessageBox.Show(this, e.Error.Message, "Defrag Statics", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ MessageBox.Show(this, e.Error.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
@@ -388,6 +469,11 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
using (var form = new MapDefragStaticsResultForm(result, _lastRunUsedFilters))
{
+ var getter = _localizationGetter;
+ if (getter != null)
+ {
+ form.SetLocalization(getter);
+ }
form.ShowDialog(this);
}
}
diff --git a/UoFiddler.Controls/Forms/MapDefragStaticsResultForm.cs b/UoFiddler.Controls/Forms/MapDefragStaticsResultForm.cs
index 3f00fae7..15951a3d 100644
--- a/UoFiddler.Controls/Forms/MapDefragStaticsResultForm.cs
+++ b/UoFiddler.Controls/Forms/MapDefragStaticsResultForm.cs
@@ -22,6 +22,7 @@ public sealed partial class MapDefragStaticsResultForm : Form
{
private readonly StaticsDefragResult _result;
private readonly bool _filtered;
+ private Func? _localizationGetter;
public MapDefragStaticsResultForm(StaticsDefragResult result, bool filtered)
{
@@ -39,6 +40,24 @@ public MapDefragStaticsResultForm(StaticsDefragResult result, bool filtered)
buttonOpenFolder.Enabled = !result.DryRun;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.Title") ?? "Defrag Statics - Result";
+ buttonVerify.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.VerifyButton") ?? "Verify output";
+ buttonSave.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.SaveButton") ?? "Save report...";
+ buttonCopy.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.CopyButton") ?? "Copy";
+ buttonOpenFolder.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.OpenFolderButton") ?? "Open output folder";
+ buttonClose.Text = _localizationGetter("Forms.MapDefragStaticsResultForm.CloseButton") ?? "Close";
+ }
+
///
/// Reads the output back and compares it against the file it was made from. With no filters
/// the two must hold exactly the same statics; with filters the output may only be missing
diff --git a/UoFiddler.Controls/Forms/MapDetailsForm.cs b/UoFiddler.Controls/Forms/MapDetailsForm.cs
index ae323bbd..8af894cb 100644
--- a/UoFiddler.Controls/Forms/MapDetailsForm.cs
+++ b/UoFiddler.Controls/Forms/MapDetailsForm.cs
@@ -9,6 +9,7 @@
*
***************************************************************************/
+using System;
using System.Drawing;
using System.Windows.Forms;
using Ultima;
@@ -18,6 +19,10 @@ namespace UoFiddler.Controls.Forms
{
public partial class MapDetailsForm : Form
{
+ private Func? _localizationGetter;
+ private Map _currentMap;
+ private Point _point;
+
public MapDetailsForm(Map currentMap, Point point)
{
InitializeComponent();
@@ -25,17 +30,50 @@ public MapDetailsForm(Map currentMap, Point point)
Icon = Options.GetFiddlerIcon();
TopMost = true;
- Tile currentTile = currentMap.Tiles.GetLandTile(point.X, point.Y);
- richTextBox.AppendText($"X: {point.X} Y: {point.Y}\n\n");
- richTextBox.AppendText("LandTile:\n");
- richTextBox.AppendText($"{TileData.LandTable[currentTile.Id].Name}: 0x{currentTile.Id:X} Altitude: {currentTile.Z}\n\n");
- HuedTile[] staticsAtPoint = currentMap.Tiles.GetStaticTiles(point.X, point.Y);
- richTextBox.AppendText("Statics:\n");
+ _currentMap = currentMap;
+ _point = point;
+
+ // 先生成英文内容
+ GenerateContent();
+ }
+
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapDetailsForm.Title") ?? "MapDetails";
+
+ // 重新生成内容以应用汉化
+ GenerateContent();
+ }
+
+ private void GenerateContent()
+ {
+ richTextBox.Clear();
+
+ string coordLabel = _localizationGetter?.Invoke("Forms.MapDetailsForm.Labels.Coordinate") ?? "X";
+ string landTileLabel = _localizationGetter?.Invoke("Forms.MapDetailsForm.Labels.LandTile") ?? "LandTile";
+ string altitudeLabel = _localizationGetter?.Invoke("Forms.MapDetailsForm.Labels.Altitude") ?? "Altitude";
+ string staticsLabel = _localizationGetter?.Invoke("Forms.MapDetailsForm.Labels.Statics") ?? "Statics";
+ string hueLabel = _localizationGetter?.Invoke("Forms.MapDetailsForm.Labels.Hue") ?? "Hue";
+
+ Tile currentTile = _currentMap.Tiles.GetLandTile(_point.X, _point.Y);
+ richTextBox.AppendText($"{coordLabel}: {_point.X} Y: {_point.Y}\n\n");
+ richTextBox.AppendText($"{landTileLabel}:\n");
+ richTextBox.AppendText($"{TileData.LandTable[currentTile.Id].Name}: 0x{currentTile.Id:X} {altitudeLabel}: {currentTile.Z}\n\n");
+ HuedTile[] staticsAtPoint = _currentMap.Tiles.GetStaticTiles(_point.X, _point.Y);
+ richTextBox.AppendText($"{staticsLabel}:\n");
foreach (HuedTile @static in staticsAtPoint)
{
ushort id = @static.Id;
- richTextBox.AppendText($"{TileData.ItemTable[id].Name}: 0x{id:X} Hue: {@static.Hue} Altitude: {@static.Z}\n");
+ richTextBox.AppendText($"{TileData.ItemTable[id].Name}: 0x{id:X} {hueLabel}: {@static.Hue} {altitudeLabel}: {@static.Z}\n");
}
}
}
-}
\ No newline at end of file
+}
diff --git a/UoFiddler.Controls/Forms/MapDiffApplyResultForm.cs b/UoFiddler.Controls/Forms/MapDiffApplyResultForm.cs
index 3aee339b..6f24909a 100644
--- a/UoFiddler.Controls/Forms/MapDiffApplyResultForm.cs
+++ b/UoFiddler.Controls/Forms/MapDiffApplyResultForm.cs
@@ -25,6 +25,7 @@ namespace UoFiddler.Controls.Forms
public sealed partial class MapDiffApplyResultForm : Form
{
private readonly MapDiffApplyResult _result;
+ private Func _localizationGetter;
public MapDiffApplyResultForm(MapDiffApplyResult result)
{
@@ -40,6 +41,24 @@ public MapDiffApplyResultForm(MapDiffApplyResult result)
buttonOpenFolder.Enabled = result.OutputMapPath != null || result.OutputIndexPath != null;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ Text = _localizationGetter("Forms.MapDiffApplyResultForm.Title") ?? "Diff to Map Copy - Result";
+ buttonVerify.Text = _localizationGetter("Forms.MapDiffApplyResultForm.buttonVerify") ?? "Verify output";
+ buttonSave.Text = _localizationGetter("Forms.MapDiffApplyResultForm.buttonSave") ?? "Save report...";
+ buttonCopy.Text = _localizationGetter("Forms.MapDiffApplyResultForm.buttonCopy") ?? "Copy";
+ buttonOpenFolder.Text = _localizationGetter("Forms.MapDiffApplyResultForm.buttonOpenFolder") ?? "Open output folder";
+ buttonClose.Text = _localizationGetter("Forms.MapDiffApplyResultForm.buttonClose") ?? "Close";
+ }
+
///
/// Reads the written map back and checks every block against what it should hold: the patch
/// where the diff covers a block inside the region, the unpatched map everywhere else.
diff --git a/UoFiddler.Controls/Forms/MapDiffInsertForm.cs b/UoFiddler.Controls/Forms/MapDiffInsertForm.cs
index 65b60a83..d55e6880 100644
--- a/UoFiddler.Controls/Forms/MapDiffInsertForm.cs
+++ b/UoFiddler.Controls/Forms/MapDiffInsertForm.cs
@@ -32,6 +32,8 @@ public partial class MapDiffInsertForm : Form
private CancellationTokenSource _cancellation;
+ private Func _localizationGetter;
+
/// Guards the round trip between a drag on the panel and the spinners it writes to.
private bool _syncingPreview;
@@ -82,6 +84,77 @@ public MapDiffInsertForm(Map currentMap)
ActiveControl = buttonCopy;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ Text = _localizationGetter("Forms.MapDiffInsertForm.Title") ?? "Diff to Map Copy";
+ groupBoxWhat.Text = _localizationGetter("Forms.MapDiffInsertForm.groupBoxWhat") ?? "Insert";
+ groupBoxFrom.Text = _localizationGetter("Forms.MapDiffInsertForm.groupBoxFrom") ?? "Region, in map tiles";
+ groupBoxPreview.Text = _localizationGetter("Forms.MapDiffInsertForm.groupBoxPreview") ?? "What will be inserted - drag to choose the region";
+
+ checkBoxMap.Text = _localizationGetter("Forms.MapDiffInsertForm.checkBoxMap") ?? "Map";
+ checkBoxStatics.Text = _localizationGetter("Forms.MapDiffInsertForm.checkBoxStatics") ?? "Statics";
+ RemoveDupl.Text = _localizationGetter("Forms.MapDiffInsertForm.RemoveDupl") ?? "remove duplicates";
+ checkBoxDuplicatesHue.Text = _localizationGetter("Forms.MapDiffInsertForm.checkBoxDuplicatesHue") ?? "comparing hue too (legacy)";
+ checkBoxPreviewStatics.Text = _localizationGetter("Forms.MapDiffInsertForm.checkBoxPreviewStatics") ?? "Show statics";
+ checkBoxPreviewPatched.Text = _localizationGetter("Forms.MapDiffInsertForm.checkBoxPreviewPatched") ?? "Mark the blocks the diff covers";
+
+ labelMapFormat.Text = _localizationGetter("Forms.MapDiffInsertForm.labelMapFormat") ?? "written as:";
+ label1.Text = _localizationGetter("Forms.MapDiffInsertForm.label1") ?? "X1";
+ label2.Text = _localizationGetter("Forms.MapDiffInsertForm.label2") ?? "Y1";
+ label3.Text = _localizationGetter("Forms.MapDiffInsertForm.label3") ?? "X2";
+ label4.Text = _localizationGetter("Forms.MapDiffInsertForm.label4") ?? "Y2";
+
+ buttonCopy.Text = _localizationGetter("Forms.MapDiffInsertForm.buttonCopy") ?? "Insert";
+ buttonCancel.Text = _localizationGetter("Forms.MapDiffInsertForm.buttonCancel") ?? "Cancel";
+ buttonClose.Text = _localizationGetter("Forms.MapDiffInsertForm.buttonClose") ?? "Close";
+
+ // 应用下拉框汉化
+ ApplyComboBoxLocalization();
+
+ // 刷新预览区域的汉化消息
+ UpdatePreview();
+ }
+
+ private string GetLocalizedMessage(string key, string defaultValue)
+ {
+ return _localizationGetter?.Invoke($"Forms.MapDiffInsertForm.Messages.{key}") ?? defaultValue;
+ }
+
+ private string GetLocalizedComboBoxFormat(string key, string defaultValue)
+ {
+ return _localizationGetter?.Invoke($"Forms.MapDiffInsertForm.ComboBoxFormats.{key}") ?? defaultValue;
+ }
+
+ private void ApplyComboBoxLocalization()
+ {
+ if (_localizationGetter == null || comboBoxMapFormat.Items.Count == 0) return;
+
+ bool uop = _workingMap.Tiles.IsUOPFormat;
+
+ // 第一项:与此客户端相同格式
+ string firstItemText = uop
+ ? GetLocalizedComboBoxFormat("SameFormatUOP", "the same format as this client (.uop)")
+ : GetLocalizedComboBoxFormat("SameFormatMUL", "the same format as this client (.mul)");
+ comboBoxMapFormat.Items[0] = firstItemText;
+
+ // 其他项保持原样(包含地图索引),但 LegacyMUL 文本可以汉化
+ // 第三项:map{index}LegacyMUL.uop
+ if (comboBoxMapFormat.Items.Count >= 3)
+ {
+ int index = _workingMap.FileIndex;
+ string legacyUopFormat = GetLocalizedComboBoxFormat("LegacyMUL", "LegacyMUL");
+ comboBoxMapFormat.Items[2] = $"map{index}{legacyUopFormat}.uop";
+ }
+ }
+
private void OnOptionChanged(object sender, EventArgs e)
{
comboBoxMapFormat.Enabled = checkBoxMap.Checked;
@@ -125,15 +198,25 @@ private void UpdatePreview()
var sb = new StringBuilder();
- sb.AppendLine($"region {region}");
+ // 获取区域标签和块标签的汉化文本
+ string regionLabel = GetLocalizedMessage("RegionLabel", "region");
+ string blockFormat = GetLocalizedMessage("BlocksLabel", "块 {0},{1} - {2},{3},{4} x {5}");
+ string diffDataFormat = GetLocalizedMessage("DiffDataLoaded", "差异数据已加载: {0:N0} 陆地块,{1:N0} 静态块");
+
+ // 构建输出,第一行使用汉化的块格式而不是 region.ToString()
+ sb.AppendLine(string.Format(CultureInfo.InvariantCulture,
+ blockFormat,
+ region.BlockX1, region.BlockY1, region.BlockX2, region.BlockY2,
+ region.BlockWidth, region.BlockHeight));
sb.AppendLine(string.Format(CultureInfo.InvariantCulture,
- "diff data loaded: {0:N0} land blocks, {1:N0} static blocks",
+ diffDataFormat,
patch.LandBlocksCount, patch.StaticBlocksCount));
if (region.TileX1 != x1 || region.TileY1 != y1 || region.TileX2 != x2 || region.TileY2 != y2)
{
+ string requestWideningFormat = GetLocalizedMessage("RequestWidened", "the request {0},{1} - {2},{3} was widened to whole 8-tile blocks");
sb.AppendLine(string.Format(CultureInfo.InvariantCulture,
- "the request {0},{1} - {2},{3} was widened to whole 8-tile blocks", x1, y1, x2, y2));
+ requestWideningFormat, x1, y1, x2, y2));
}
textBoxPreview.Text = sb.ToString();
@@ -251,7 +334,7 @@ private void OnClickCopy(object sender, EventArgs e)
SetRunning(true);
progressBar1.Value = 0;
- labelStatus.Text = "Inserting...";
+ labelStatus.Text = GetLocalizedMessage("Inserting", "Inserting...");
worker.RunWorkerAsync(options);
}
@@ -290,7 +373,7 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
if (e.Error is OperationCanceledException)
{
progressBar1.Value = 0;
- labelStatus.Text = "Cancelled. Nothing was written.";
+ labelStatus.Text = GetLocalizedMessage("Cancelled", "Cancelled. Nothing was written.");
return;
}
@@ -298,7 +381,7 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
if (e.Error != null)
{
progressBar1.Value = 0;
- labelStatus.Text = "Failed.";
+ labelStatus.Text = GetLocalizedMessage("Failed", "Failed.");
ShowError("Diff to Map Copy", e.Error);
@@ -308,10 +391,13 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
var result = (MapDiffApplyResult)e.Result;
progressBar1.Value = 100;
- labelStatus.Text = "Done.";
+ labelStatus.Text = GetLocalizedMessage("Done", "Done.");
using (var form = new MapDiffApplyResultForm(result))
{
+ if (_localizationGetter != null)
+ form.SetLocalization(_localizationGetter);
+
form.ShowDialog(this);
}
}
@@ -354,7 +440,7 @@ private void ShowError(string title, Exception error)
private void OnClickCancel(object sender, EventArgs e)
{
_cancellation?.Cancel();
- labelStatus.Text = "Cancelling...";
+ labelStatus.Text = GetLocalizedMessage("Cancelling", "Cancelling...");
}
private void OnClickClose(object sender, EventArgs e)
diff --git a/UoFiddler.Controls/Forms/MapMarkerForm.cs b/UoFiddler.Controls/Forms/MapMarkerForm.cs
index 9defb5c8..d2e624eb 100644
--- a/UoFiddler.Controls/Forms/MapMarkerForm.cs
+++ b/UoFiddler.Controls/Forms/MapMarkerForm.cs
@@ -20,6 +20,7 @@ public partial class MapMarkerForm : Form
{
private readonly Action _addOverlayAction;
private static Color _lastColor = Color.FromArgb(180, Color.Yellow);
+ private Func? _localizationGetter;
public MapMarkerForm(Action addOverlayAction, int x, int y, int map)
{
@@ -37,6 +38,22 @@ public MapMarkerForm(Action addOverlayAction, int
pictureBox1.BackColor = _lastColor;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapMarkerForm.Title") ?? "Add MapMarker";
+ label1.Text = _localizationGetter("Forms.MapMarkerForm.TextLabel") ?? "Text";
+ button1.Text = _localizationGetter("Forms.MapMarkerForm.ChooseColorButton") ?? "Choose Color";
+ button2.Text = _localizationGetter("Forms.MapMarkerForm.SaveButton") ?? "Save";
+ }
+
private void OnClickColor(object sender, EventArgs e)
{
if (colorDialog1.ShowDialog() != DialogResult.Cancel)
diff --git a/UoFiddler.Controls/Forms/MapMeltStaticsForm.cs b/UoFiddler.Controls/Forms/MapMeltStaticsForm.cs
index 69f265f8..52f3ff39 100644
--- a/UoFiddler.Controls/Forms/MapMeltStaticsForm.cs
+++ b/UoFiddler.Controls/Forms/MapMeltStaticsForm.cs
@@ -21,6 +21,7 @@ public partial class MapMeltStaticsForm : Form
{
private readonly Action _refreshMap;
private readonly Map _map;
+ private Func? _localizationGetter;
public MapMeltStaticsForm(Action refreshMap, Map map)
{
@@ -37,6 +38,24 @@ public MapMeltStaticsForm(Action refreshMap, Map map)
numericUpDownY2.Maximum = map.Height;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapMeltStaticsForm.Title") ?? "Melt Statics";
+ label2.Text = _localizationGetter("Forms.MapMeltStaticsForm.X1Label") ?? "X1";
+ label3.Text = _localizationGetter("Forms.MapMeltStaticsForm.Y1Label") ?? "Y1";
+ label4.Text = _localizationGetter("Forms.MapMeltStaticsForm.X2Label") ?? "X2";
+ label5.Text = _localizationGetter("Forms.MapMeltStaticsForm.Y2Label") ?? "Y2";
+ button1.Text = _localizationGetter("Forms.MapMeltStaticsForm.MeltButton") ?? "Melt";
+ }
+
private void OnClickMelt(object sender, EventArgs e)
{
SaveFileDialog dialog = new SaveFileDialog
@@ -122,7 +141,9 @@ private void OnClickMelt(object sender, EventArgs e)
_map.ResetCache();
- MessageBox.Show("Done", "Melt Static", MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
+ string title = _localizationGetter?.Invoke("Forms.MapMeltStaticsForm.DoneTitle") ?? "Melt Static";
+ string message = _localizationGetter?.Invoke("Forms.MapMeltStaticsForm.DoneMessage") ?? "Done";
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
_refreshMap();
}
diff --git a/UoFiddler.Controls/Forms/MapRegionCopyResultForm.cs b/UoFiddler.Controls/Forms/MapRegionCopyResultForm.cs
index 2ec9e964..b7ad1e42 100644
--- a/UoFiddler.Controls/Forms/MapRegionCopyResultForm.cs
+++ b/UoFiddler.Controls/Forms/MapRegionCopyResultForm.cs
@@ -24,6 +24,7 @@ namespace UoFiddler.Controls.Forms
public sealed partial class MapRegionCopyResultForm : Form
{
private readonly MapRegionCopyResult _result;
+ private Func? _localizationGetter;
public MapRegionCopyResultForm(MapRegionCopyResult result)
{
@@ -39,6 +40,24 @@ public MapRegionCopyResultForm(MapRegionCopyResult result)
buttonOpenFolder.Enabled = result.OutputMapPath != null || result.OutputIndexPath != null;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapRegionCopyResultForm.Title") ?? "Map and Statics Copy - Result";
+ buttonVerify.Text = _localizationGetter("Forms.MapRegionCopyResultForm.VerifyButton") ?? "Verify output";
+ buttonSave.Text = _localizationGetter("Forms.MapRegionCopyResultForm.SaveButton") ?? "Save report...";
+ buttonCopy.Text = _localizationGetter("Forms.MapRegionCopyResultForm.CopyButton") ?? "Copy";
+ buttonOpenFolder.Text = _localizationGetter("Forms.MapRegionCopyResultForm.OpenFolderButton") ?? "Open output folder";
+ buttonClose.Text = _localizationGetter("Forms.MapRegionCopyResultForm.CloseButton") ?? "Close";
+ }
+
///
/// Reads the written map back and checks it block by block: inside the pasted rectangle it
/// has to match the source, everywhere else the map it was made from.
diff --git a/UoFiddler.Controls/Forms/MapReplaceForm.Designer.cs b/UoFiddler.Controls/Forms/MapReplaceForm.Designer.cs
index 6383be9e..40006905 100644
--- a/UoFiddler.Controls/Forms/MapReplaceForm.Designer.cs
+++ b/UoFiddler.Controls/Forms/MapReplaceForm.Designer.cs
@@ -504,24 +504,24 @@ private void InitializeComponent()
// progressBar1
//
this.progressBar1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
- this.progressBar1.Location = new System.Drawing.Point(12, 884);
+ this.progressBar1.Location = new System.Drawing.Point(12, 844);
this.progressBar1.Name = "progressBar1";
- this.progressBar1.Size = new System.Drawing.Size(1440, 18);
+ this.progressBar1.Size = new System.Drawing.Size(1432, 18);
this.progressBar1.TabIndex = 5;
//
// labelStatus
//
this.labelStatus.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right)));
this.labelStatus.AutoEllipsis = true;
- this.labelStatus.Location = new System.Drawing.Point(12, 907);
+ this.labelStatus.Location = new System.Drawing.Point(12, 867);
this.labelStatus.Name = "labelStatus";
- this.labelStatus.Size = new System.Drawing.Size(1440, 17);
+ this.labelStatus.Size = new System.Drawing.Size(1432, 17);
this.labelStatus.TabIndex = 6;
//
// buttonCopy
//
this.buttonCopy.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
- this.buttonCopy.Location = new System.Drawing.Point(1204, 932);
+ this.buttonCopy.Location = new System.Drawing.Point(1196, 892);
this.buttonCopy.Name = "buttonCopy";
this.buttonCopy.Size = new System.Drawing.Size(80, 28);
this.buttonCopy.TabIndex = 7;
@@ -533,7 +533,7 @@ private void InitializeComponent()
//
this.buttonCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonCancel.Enabled = false;
- this.buttonCancel.Location = new System.Drawing.Point(1292, 932);
+ this.buttonCancel.Location = new System.Drawing.Point(1284, 892);
this.buttonCancel.Name = "buttonCancel";
this.buttonCancel.Size = new System.Drawing.Size(72, 28);
this.buttonCancel.TabIndex = 8;
@@ -545,7 +545,7 @@ private void InitializeComponent()
//
this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
this.buttonClose.DialogResult = System.Windows.Forms.DialogResult.Cancel;
- this.buttonClose.Location = new System.Drawing.Point(1380, 932);
+ this.buttonClose.Location = new System.Drawing.Point(1372, 892);
this.buttonClose.Name = "buttonClose";
this.buttonClose.Size = new System.Drawing.Size(80, 28);
this.buttonClose.TabIndex = 9;
@@ -564,7 +564,7 @@ private void InitializeComponent()
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.CancelButton = this.buttonClose;
- this.ClientSize = new System.Drawing.Size(1464, 972);
+ this.ClientSize = new System.Drawing.Size(1464, 1012);
this.Controls.Add(this.groupBoxSource);
this.Controls.Add(this.groupBoxWhat);
this.Controls.Add(this.groupBoxFrom);
diff --git a/UoFiddler.Controls/Forms/MapReplaceForm.cs b/UoFiddler.Controls/Forms/MapReplaceForm.cs
index 4c6c7674..a5f13425 100644
--- a/UoFiddler.Controls/Forms/MapReplaceForm.cs
+++ b/UoFiddler.Controls/Forms/MapReplaceForm.cs
@@ -31,6 +31,8 @@ namespace UoFiddler.Controls.Forms
public partial class MapReplaceForm : Form
{
private readonly Map _workingMap;
+ private Func? _localizationGetter;
+ private bool _initialized = false;
private CancellationTokenSource _cancellation;
private MapSize _detectedSize;
@@ -58,6 +60,82 @@ public partial class MapReplaceForm : Form
private ZSurveyRequest _zPending;
private CancellationTokenSource _zCancellation;
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ CompleteInitialization(); // 完成初始化,确保动态消息被汉化
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapReplaceForm.Title") ?? $"Map and Statics Copy - into map {_workingMap.FileIndex}";
+ groupBoxSource.Text = _localizationGetter("Forms.MapReplaceForm.GroupBoxSource") ?? "Copy from";
+ labelFolder.Text = _localizationGetter("Forms.MapReplaceForm.LabelFolder") ?? "Folder:";
+ buttonBrowse.Text = _localizationGetter("Forms.MapReplaceForm.ButtonBrowse") ?? "Browse...";
+ labelMap.Text = _localizationGetter("Forms.MapReplaceForm.LabelMap") ?? "Map:";
+ groupBoxWhat.Text = _localizationGetter("Forms.MapReplaceForm.GroupBoxWhat") ?? "Copy";
+ checkBoxMap.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxMap") ?? "Map";
+ labelMapFormat.Text = _localizationGetter("Forms.MapReplaceForm.LabelMapFormat") ?? "written as:";
+ checkBoxStatics.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxStatics") ?? "Statics";
+ RemoveDupl.Text = _localizationGetter("Forms.MapReplaceForm.RemoveDupl") ?? "remove duplicates";
+ checkBoxDuplicatesHue.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxDuplicatesHue") ?? "comparing hue too (legacy)";
+ groupBoxFrom.Text = _localizationGetter("Forms.MapReplaceForm.GroupBoxFrom") ?? "From region, in source map tiles";
+ label1.Text = _localizationGetter("Forms.MapReplaceForm.Label1") ?? "X1";
+ label2.Text = _localizationGetter("Forms.MapReplaceForm.Label2") ?? "Y1";
+ label3.Text = _localizationGetter("Forms.MapReplaceForm.Label3") ?? "X2";
+ label4.Text = _localizationGetter("Forms.MapReplaceForm.Label4") ?? "Y2";
+ groupBoxTo.Text = _localizationGetter("Forms.MapReplaceForm.GroupBoxTo") ?? "To position, in this map's tiles";
+ label6.Text = _localizationGetter("Forms.MapReplaceForm.Label6") ?? "X";
+ label7.Text = _localizationGetter("Forms.MapReplaceForm.Label7") ?? "Y";
+ labelZAdjust.Text = _localizationGetter("Forms.MapReplaceForm.LabelZAdjust") ?? "Z adjust";
+ checkBoxZClamp.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxZClamp") ?? "hold what passes the limit";
+ groupBoxPreview.Text = _localizationGetter("Forms.MapReplaceForm.GroupBoxPreview") ?? "What will be copied";
+ labelSourcePreview.Text = _localizationGetter("Forms.MapReplaceForm.LabelSourcePreview") ?? "From - drag to choose the region";
+ labelTargetPreview.Text = _localizationGetter("Forms.MapReplaceForm.LabelTargetPreview") ?? "To - drag to place it";
+ checkBoxPreviewStatics.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxPreviewStatics") ?? "Show statics";
+ checkBoxPreviewOverlay.Text = _localizationGetter("Forms.MapReplaceForm.CheckBoxPreviewOverlay") ?? "Show the piece in place";
+ buttonCopy.Text = _localizationGetter("Forms.MapReplaceForm.ButtonCopy") ?? "Copy";
+ buttonCancel.Text = _localizationGetter("Forms.MapReplaceForm.ButtonCancel") ?? "Cancel";
+ buttonClose.Text = _localizationGetter("Forms.MapReplaceForm.ButtonClose") ?? "Close";
+
+ // 汉化 ComboBox 项(类型 2 - 动态列表项汉化)
+ ApplyComboBoxLocalization();
+
+ // 刷新预览消息,应用动态文本汉化(类型 8 - 运行时动态文本)
+ UpdatePreview();
+ }
+
+ private void ApplyComboBoxLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ bool uop = _workingMap.Tiles.IsUOPFormat;
+
+ // 清空并重新添加翻译后的项
+ comboBoxMapFormat.Items.Clear();
+
+ // 第一项:与客户端相同格式
+ string sameFormatKey = uop ? "SameFormatUOP" : "SameFormatMUL";
+ string sameFormatText = _localizationGetter($"Forms.MapReplaceForm.ComboBoxFormats.{sameFormatKey}")
+ ?? (uop ? "the same format as this client (.uop)" : "the same format as this client (.mul)");
+ comboBoxMapFormat.Items.Add(sameFormatText);
+
+ // 第二项:map{0}.mul
+ string mapMulTemplate = _localizationGetter("Forms.MapReplaceForm.ComboBoxFormats.MapMUL")
+ ?? "map{0}.mul";
+ comboBoxMapFormat.Items.Add(string.Format(mapMulTemplate, _workingMap.FileIndex));
+
+ // 第三项:map{0}LegacyMUL.uop
+ string legacyTemplate = _localizationGetter("Forms.MapReplaceForm.ComboBoxFormats.LegacyMUL")
+ ?? "map{0}LegacyMUL.uop";
+ comboBoxMapFormat.Items.Add(string.Format(legacyTemplate, _workingMap.FileIndex));
+
+ comboBoxMapFormat.SelectedIndex = ClientFileSaveFormats.DefaultIndex(Options.SaveFormat);
+ }
+
public MapReplaceForm(Map currentMap)
{
InitializeComponent();
@@ -115,11 +193,24 @@ public MapReplaceForm(Map currentMap)
_zWorker.DoWork += OnZWorkerDoWork;
_zWorker.RunWorkerCompleted += OnZWorkerCompleted;
- OnSourceMapChanged(this, EventArgs.Empty);
- OnOptionChanged(this, EventArgs.Empty);
+ // 不在这里初始化,等待 SetLocalization 被调用
+ // OnSourceMapChanged(this, EventArgs.Empty);
+ // OnOptionChanged(this, EventArgs.Empty);
ActiveControl = buttonBrowse;
}
+
+ ///
+ /// 完成初始化 - 在 SetLocalization 之后调用
+ ///
+ private void CompleteInitialization()
+ {
+ if (_initialized) return;
+ _initialized = true;
+
+ OnSourceMapChanged(this, EventArgs.Empty);
+ OnOptionChanged(this, EventArgs.Empty);
+ }
private SupportedMap SelectedMap => comboBoxMapID.SelectedItem as SupportedMap;
@@ -173,7 +264,8 @@ private void OnClickBrowse(object sender, EventArgs e)
{
using (var dialog = new FolderBrowserDialog
{
- Description = "Select the folder holding the map files to copy from",
+ Description = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SelectFolderDialog")
+ ?? "Select the folder holding the map files to copy from",
ShowNewFolderButton = false,
SelectedPath = Directory.Exists(textBoxFolder.Text) ? textBoxFolder.Text : string.Empty
})
@@ -248,19 +340,41 @@ private void Detect()
RebuildSourceMap(map);
- labelDetected.Text = _detectionKnown ? $"folder holds {_detectedSize}" : "size not recognised";
+ string sizeNotRecognised = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SizeNotRecognised") ?? "size not recognised";
+ string folderHoldsTemplate = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.FolderHolds") ?? "folder holds {0}";
+
+ labelDetected.Text = _detectionKnown ? string.Format(folderHoldsTemplate, _detectedSize) : sizeNotRecognised;
if (_detectionKnown && _detectedSize.Width == map.Width && _detectedSize.Height == map.Height)
{
labelSizeWarning.ForeColor = SystemColors.ControlText;
- labelSizeWarning.Text = _detectionEvidence;
+ // 将 evidence 中的英文消息汉化
+ string localizedEvidence = _detectionEvidence;
+ if (_localizationGetter != null && _detectionEvidence != null)
+ {
+ string template = _localizationGetter("Forms.MapReplaceForm.PreviewMessages.NoMapOrStaticsIndex")
+ ?? "no map or statics index found for facet {0}; assuming {1}";
+ // 尝试汉化 evidence 中的模板消息
+ localizedEvidence = _detectionEvidence.Replace(
+ "no map or statics index found for facet",
+ template.Split(';')[0]);
+ }
+ labelSizeWarning.Text = localizedEvidence;
}
else
{
labelSizeWarning.ForeColor = Options.DarkMode ? Color.OrangeRed : Color.Red;
- labelSizeWarning.Text = _detectionKnown
- ? $"This folder holds {_detectedSize} for map {map.Id}, not the {map.Width}x{map.Height} selected.{Environment.NewLine}Pick the entry that matches."
- : _detectionEvidence;
+ if (_detectionKnown)
+ {
+ string template = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SizeCheckMismatch")
+ ?? "This folder holds {0} for map {1}, not the {2} selected.{3}Pick the entry that matches.";
+ labelSizeWarning.Text = string.Format(template, _detectedSize, map.Id,
+ $"{map.Width}x{map.Height}", Environment.NewLine);
+ }
+ else
+ {
+ labelSizeWarning.Text = _detectionEvidence;
+ }
}
UpdatePreview();
@@ -326,7 +440,7 @@ private void UpdatePreviewRectangles()
if (map == null)
{
- textBoxPreview.Text = "Choose a folder and a map.";
+ textBoxPreview.Text = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.ChooseFolderAndMap") ?? "Choose a folder and a map.";
return;
}
@@ -356,17 +470,24 @@ private void UpdatePreviewRectangles()
var sb = new StringBuilder();
// The panels carry the shape now, so this is only the numbers.
- sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "from {0},{1} - {2},{3} {4} x {5} blocks",
+ string sourceFormat = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SourceFormat")
+ ?? "from {0},{1} - {2},{3} {4} x {5} blocks";
+ string destinationFormat = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.DestinationFormat")
+ ?? "to {0},{1} - {2},{3}";
+ string widenedFormat = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.WidenedFormat")
+ ?? "{0},{1} - {2},{3} widened to whole blocks";
+
+ sb.AppendLine(string.Format(CultureInfo.InvariantCulture, sourceFormat,
source.TileX1, source.TileY1, source.TileX2, source.TileY2, source.BlockWidth, source.BlockHeight));
- sb.AppendLine(string.Format(CultureInfo.InvariantCulture, "to {0},{1} - {2},{3}",
+ sb.AppendLine(string.Format(CultureInfo.InvariantCulture, destinationFormat,
destination.TileX1, destination.TileY1, destination.TileX2, destination.TileY2));
bool snapped = source.TileX1 != x1 || source.TileY1 != y1 || source.TileX2 != x2 || source.TileY2 != y2;
if (snapped)
{
- sb.AppendLine(string.Format(CultureInfo.InvariantCulture,
- "{0},{1} - {2},{3} widened to whole blocks", x1, y1, x2, y2));
+ sb.AppendLine(string.Format(CultureInfo.InvariantCulture, widenedFormat,
+ x1, y1, x2, y2));
}
textBoxPreview.Text = sb.ToString();
@@ -406,7 +527,7 @@ private void RebuildSourceMap(SupportedMap map)
previewSource.Map = _sourceMap;
previewSource.MapSize = map == null ? default : new MapSize(map.Width, map.Height);
- previewSource.Message = _sourceMap == null ? "Choose a folder to copy from" : null;
+ previewSource.Message = _sourceMap == null ? (_localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.ChooseFolderToCopyFrom") ?? "Choose a folder to copy from") : null;
previewTarget.OverlayMap = checkBoxPreviewOverlay.Checked ? _sourceMap : null;
}
@@ -519,7 +640,8 @@ private void UpdateZ()
_zPending = request;
labelZRange.ForeColor = SystemColors.ControlText;
- labelZRange.Text = "reading the heights in this region...";
+ labelZRange.Text = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.ReadingHeights")
+ ?? "reading the heights in this region...";
_zDebounce.Stop();
_zDebounce.Start();
@@ -623,13 +745,19 @@ private void ShowZ()
// Kept short: this sits on one line beside the spinners, and an ellipsis in the middle
// of the warning is worse than no warning at all.
- sb.Append(CultureInfo.InvariantCulture,
- $"region z land {Span(_zSurvey.Land, 0)}, statics {Span(_zSurvey.Statics, 0)}");
+ string regionTemplate = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.RegionZ")
+ ?? "region z land {0}, statics {1}";
+
+ sb.Append(string.Format(CultureInfo.InvariantCulture,
+ regionTemplate, Span(_zSurvey.Land, 0), Span(_zSurvey.Statics, 0)));
if (adjust != 0)
{
- sb.Append(CultureInfo.InvariantCulture,
- $" -> land {Span(_zSurvey.Land, adjust)}, statics {Span(_zSurvey.Statics, adjust)}");
+ string adjustTemplate = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.RegionZAdjusted")
+ ?? " -> land {0}, statics {1}";
+
+ sb.Append(string.Format(CultureInfo.InvariantCulture,
+ adjustTemplate, Span(_zSurvey.Land, adjust), Span(_zSurvey.Statics, adjust)));
}
long past = _zSurvey.OutOfRange(adjust);
@@ -642,18 +770,24 @@ private void ShowZ()
return;
}
- sb.Append(CultureInfo.InvariantCulture,
- $" - {past:N0} past the limit, {(checkBoxZClamp.Checked ? "held there" : "refused")}");
+ string limitTemplate = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.RegionZOutOfRange")
+ ?? " - {0:N0} past the limit, {1}";
+ string limitAction = checkBoxZClamp.Checked
+ ? (_localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.HeldThere") ?? "held there")
+ : (_localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.Refused") ?? "refused");
+
+ sb.Append(string.Format(CultureInfo.InvariantCulture,
+ limitTemplate, past, limitAction));
labelZRange.ForeColor = Options.DarkMode ? Color.OrangeRed : Color.Red;
labelZRange.Text = sb.ToString();
}
- private static string Span(ZHistogram z, int adjust)
+ private string Span(ZHistogram z, int adjust)
{
if (!z.HasTiles)
{
- return "none";
+ return _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.StaticsNone") ?? "none";
}
return string.Format(CultureInfo.InvariantCulture, "{0}..{1}",
@@ -682,30 +816,34 @@ private void OnClickCopy(object sender, EventArgs e)
if (!Directory.Exists(textBoxFolder.Text))
{
- Fail("Choose the folder holding the map files to copy from.");
-
+ string msg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.ChooseFolderForCopy")
+ ?? "Choose the folder holding the map files to copy from.";
+ Fail(msg);
return;
}
if (!checkBoxMap.Checked && !checkBoxStatics.Checked)
{
- Fail("Nothing is selected to copy.");
-
+ string msg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.NothingSelected")
+ ?? "Nothing is selected to copy.";
+ Fail(msg);
return;
}
if (!_detectionKnown)
{
- Fail($"The size of map {map.Id} in that folder could not be worked out.{Environment.NewLine}{Environment.NewLine}{_detectionEvidence}");
+ string msg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SizeCouldNotBeDetermined")
+ ?? $"The size of map {map.Id} in that folder could not be worked out.{Environment.NewLine}{Environment.NewLine}{_detectionEvidence}";
+ Fail(string.Format(msg, map.Id, Environment.NewLine, _detectionEvidence));
return;
}
if (_detectedSize.Width != map.Width || _detectedSize.Height != map.Height)
{
- Fail($"That folder holds {_detectedSize} for map {map.Id}, but {map} is selected." +
- $"{Environment.NewLine}{Environment.NewLine}{_detectionEvidence}" +
- $"{Environment.NewLine}{Environment.NewLine}Pick the entry that matches, or the wrong blocks will be read.");
+ string template = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.SizeMismatchError")
+ ?? $"That folder holds {{0}} for map {{1}}, but {{2}} is selected.{{3}}{{3}}{{4}}{{3}}{{3}}Pick the entry that matches, or the wrong blocks will be read.";
+ Fail(string.Format(template, _detectedSize, map.Id, map, Environment.NewLine, _detectionEvidence));
return;
}
@@ -719,7 +857,9 @@ private void OnClickCopy(object sender, EventArgs e)
SetRunning(true);
progressBar1.Value = 0;
- labelStatus.Text = "Copying...";
+ string copyingMsg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.Copying")
+ ?? "Copying...";
+ labelStatus.Text = copyingMsg;
worker.RunWorkerAsync(options);
}
@@ -787,8 +927,16 @@ private void OnProgress(MapCopyProgress progress)
}
progressBar1.Value = Math.Min(100, Math.Max(0, (int)(progress.BlocksDone * 100L / progress.BlocksTotal)));
+
+ string stageText = progress.Stage switch
+ {
+ "Copying land" => _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.CopyingLand") ?? "Copying land",
+ "Copying statics" => _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.CopyingStatics") ?? "Copying statics",
+ _ => progress.Stage
+ };
+
labelStatus.Text = string.Format(CultureInfo.InvariantCulture, "{0}: {1:N0} of {2:N0} blocks",
- progress.Stage, progress.BlocksDone, progress.BlocksTotal);
+ stageText, progress.BlocksDone, progress.BlocksTotal);
}
private void OnWorkerDoWork(object sender, DoWorkEventArgs e)
@@ -803,27 +951,47 @@ private void OnWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
if (e.Error is OperationCanceledException)
{
progressBar1.Value = 0;
- labelStatus.Text = "Cancelled. Nothing was written.";
-
+ string cancelledMsg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.Cancelled")
+ ?? "Cancelled. Nothing was written.";
+ labelStatus.Text = cancelledMsg;
return;
}
if (e.Error != null)
{
progressBar1.Value = 0;
- labelStatus.Text = "Failed.";
+ string failedMsg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.Failed")
+ ?? "Failed.";
+ labelStatus.Text = failedMsg;
ShowError("Map and Statics Copy", e.Error);
-
return;
}
var result = (MapRegionCopyResult)e.Result;
progressBar1.Value = 100;
- labelStatus.Text = "Done.";
+ string doneMsg = _localizationGetter?.Invoke("Forms.MapReplaceForm.PreviewMessages.Done")
+ ?? "Done.";
+ labelStatus.Text = doneMsg;
using (var form = new MapRegionCopyResultForm(result))
{
+ // 通过反射尝试获取 LocalizationService 的 GetString 方法
+ try
+ {
+ var localizationServiceType = Type.GetType("UoFiddler.Localization.LocalizationService, UoFiddler");
+ if (localizationServiceType != null)
+ {
+ var getStringMethod = localizationServiceType.GetMethod("GetString",
+ System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
+ if (getStringMethod != null)
+ {
+ form.SetLocalization(key => (string?)getStringMethod.Invoke(null, new object[] { key }));
+ }
+ }
+ }
+ catch { }
+
form.ShowDialog(this);
}
}
@@ -887,7 +1055,9 @@ private void SetRunning(bool running)
private void Fail(string message)
{
- MessageBox.Show(this, message, "Map and Statics Copy", MessageBoxButtons.OK, MessageBoxIcon.Error);
+ string title = _localizationGetter?.Invoke("Forms.MapReplaceForm.WindowTitle")
+ ?? "Map and Statics Copy";
+ MessageBox.Show(this, message, title, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
protected override void OnFormClosing(FormClosingEventArgs e)
diff --git a/UoFiddler.Controls/Forms/MapReplaceTilesForm.cs b/UoFiddler.Controls/Forms/MapReplaceTilesForm.cs
index b9209a7f..1f30fe87 100644
--- a/UoFiddler.Controls/Forms/MapReplaceTilesForm.cs
+++ b/UoFiddler.Controls/Forms/MapReplaceTilesForm.cs
@@ -23,6 +23,7 @@ public partial class MapReplaceTilesForm : Form
{
private readonly Map _map;
private List _toReplace;
+ private Func? _localizationGetter;
public MapReplaceTilesForm(Map map)
{
@@ -31,6 +32,21 @@ public MapReplaceTilesForm(Map map)
_map = map;
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.MapReplaceTilesForm.Title") ?? "Map - replace tiles";
+ label5.Text = _localizationGetter("Forms.MapReplaceTilesForm.ReplaceFromLabel") ?? "Replace From";
+ button2.Text = _localizationGetter("Forms.MapReplaceTilesForm.ReplaceButton") ?? "Replace";
+ }
+
private void OnReplace(object sender, EventArgs e)
{
using (new WaitCursorScope(this))
diff --git a/UoFiddler.Controls/Forms/MultisHelpForm.Designer.cs b/UoFiddler.Controls/Forms/MultisHelpForm.Designer.cs
index 7401afd0..85e61ee5 100644
--- a/UoFiddler.Controls/Forms/MultisHelpForm.Designer.cs
+++ b/UoFiddler.Controls/Forms/MultisHelpForm.Designer.cs
@@ -51,12 +51,12 @@ private void InitializeComponent()
//
// _columnKey
//
- _columnKey.Text = "Shortcut / Control";
+ _columnKey.Text = "快捷方式 / 控制";
_columnKey.Width = 180;
//
// _columnAction
//
- _columnAction.Text = "Action";
+ _columnAction.Text = "操作";
_columnAction.Width = 420;
//
// _btnClose
@@ -67,7 +67,7 @@ private void InitializeComponent()
_btnClose.Name = "_btnClose";
_btnClose.Size = new System.Drawing.Size(75, 27);
_btnClose.TabIndex = 1;
- _btnClose.Text = "Close";
+ _btnClose.Text = "关闭";
_btnClose.UseVisualStyleBackColor = true;
//
// MultisHelpForm
@@ -85,7 +85,7 @@ private void InitializeComponent()
Padding = new System.Windows.Forms.Padding(8);
ShowInTaskbar = false;
StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
- Text = "Multis — Keyboard Shortcuts & Controls";
+ Text = "多重组件 — 键盘快捷方式和控制";
ResumeLayout(false);
}
diff --git a/UoFiddler.Controls/Forms/MultisHelpForm.cs b/UoFiddler.Controls/Forms/MultisHelpForm.cs
index e41f2a2c..2d5a3c49 100644
--- a/UoFiddler.Controls/Forms/MultisHelpForm.cs
+++ b/UoFiddler.Controls/Forms/MultisHelpForm.cs
@@ -9,6 +9,7 @@
*
***************************************************************************/
+using System;
using System.Drawing;
using System.Windows.Forms;
using UoFiddler.Controls.Classes;
@@ -17,27 +18,74 @@ namespace UoFiddler.Controls.Forms
{
public partial class MultisHelpForm : Form
{
+ private Func? _localizationGetter;
+
public MultisHelpForm()
{
InitializeComponent();
+ }
+
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null)
+ {
+ // 如果没有汉化,使用默认英文
+ PopulateShortcuts();
+ return;
+ }
+
+ // 应用窗口标题
+ Text = _localizationGetter("Forms.MultisControl.HelpForm.Title") ?? "Multis — Keyboard Shortcuts & Controls";
+
+ // 应用列标题
+ _columnKey.Text = _localizationGetter("Forms.MultisControl.HelpForm.ColumnShortcut") ?? "Shortcut / Control";
+ _columnAction.Text = _localizationGetter("Forms.MultisControl.HelpForm.ColumnAction") ?? "Action";
+
+ // 应用按钮文本
+ _btnClose.Text = _localizationGetter("Forms.MultisControl.HelpForm.ButtonClose") ?? "Close";
+
+ // 清除并重新填充列表
+ _listView.Items.Clear();
PopulateShortcuts();
}
private void PopulateShortcuts()
{
- AddHeader("Preview");
- Add("Fit preview to window", "Toggle button on toolbar — scales to fit or shows at 100% with scrollbars");
-
- AddHeader("Zoom (100% mode only)");
- Add("Ctrl + Mouse Wheel", "Zoom In / Out");
- Add("Shift + = (Plus key)", "Zoom In");
- Add("- (Minus key)", "Zoom Out");
- Add("Numpad +", "Zoom In");
- Add("Numpad -", "Zoom Out");
- Add("Ctrl + 0", "Reset zoom to 100%");
-
- AddHeader("Panning (100% mode only)");
- Add("Left-click drag", "Pan the view");
+ // Preview 部分
+ AddHeader(GetLocalizedString("Forms.MultisControl.HelpForm.HeaderPreview", "Preview"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.PreviewFit", "Fit preview to window"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.PreviewFitDesc", "Toggle button on toolbar — scales to fit or shows at 100% with scrollbars"));
+
+ // Zoom 部分
+ AddHeader(GetLocalizedString("Forms.MultisControl.HelpForm.HeaderZoom", "Zoom (100% mode only)"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomCtrlWheel", "Ctrl + Mouse Wheel"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomCtrlWheelDesc", "Zoom In / Out"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomShiftPlus", "Shift + = (Plus key)"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomShiftPlusDesc", "Zoom In"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomMinus", "- (Minus key)"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomMinusDesc", "Zoom Out"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomNumpadPlus", "Numpad +"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomNumpadPlusDesc", "Zoom In"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomNumpadMinus", "Numpad -"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomNumpadMinusDesc", "Zoom Out"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.ZoomCtrl0", "Ctrl + 0"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.ZoomCtrl0Desc", "Reset zoom to 100%"));
+
+ // Panning 部分
+ AddHeader(GetLocalizedString("Forms.MultisControl.HelpForm.HeaderPanning", "Panning (100% mode only)"));
+ Add(GetLocalizedString("Forms.MultisControl.HelpForm.PanningLeftDrag", "Left-click drag"),
+ GetLocalizedString("Forms.MultisControl.HelpForm.PanningLeftDragDesc", "Pan the view"));
+ }
+
+ private string GetLocalizedString(string key, string fallback)
+ {
+ return _localizationGetter?.Invoke(key) ?? fallback;
}
private void AddHeader(string text)
diff --git a/UoFiddler.Controls/Forms/TileDataFilterForm.cs b/UoFiddler.Controls/Forms/TileDataFilterForm.cs
index 830d2c78..278d9209 100644
--- a/UoFiddler.Controls/Forms/TileDataFilterForm.cs
+++ b/UoFiddler.Controls/Forms/TileDataFilterForm.cs
@@ -10,6 +10,7 @@
***************************************************************************/
using System;
+using System.Collections.Generic;
using System.Windows.Forms;
using Ultima;
using UoFiddler.Controls.Classes;
@@ -20,6 +21,7 @@ public partial class TileDataFilterForm : Form
{
private readonly Action _applyItemFilterAction;
private readonly Action _applyLandFilterAction;
+ private Func? _localizationGetter;
public TileDataFilterForm(Action applyItemFilterAction, Action applyLandFilterAction)
{
@@ -32,6 +34,125 @@ public TileDataFilterForm(Action applyItemFilterAction, Action
+ /// Sets the localization getter and applies localized text.
+ ///
+ public void SetLocalization(Func? getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// Applies localized text to UI elements.
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // Localize title
+ var title = _localizationGetter("Forms.TileDataFilterForm.Title");
+ if (title != null)
+ Text = title;
+
+ // Localize tab pages - look for TabPage controls named tabPageItems and tabPageLand
+ foreach (TabPage page in tabcontrol.TabPages)
+ {
+ if (page.Name == "tabPageItems")
+ {
+ var itemsTab = _localizationGetter("Forms.TileDataFilterForm.ItemsTab");
+ if (itemsTab != null)
+ page.Text = itemsTab;
+ }
+ else if (page.Name == "tabPageLand")
+ {
+ var landTab = _localizationGetter("Forms.TileDataFilterForm.LandTab");
+ if (landTab != null)
+ page.Text = landTab;
+ }
+ }
+
+ // Map textbox names to their corresponding label names and JSON keys
+ // The label names are defined in Designer.cs (e.g., label1, label2, etc.)
+ var textboxToLabelName = new Dictionary
+ {
+ { "textBoxName", ("label1", "Forms.TileDataFilterForm.Labels.Name") },
+ { "textBoxAnim", ("label2", "Forms.TileDataFilterForm.Labels.Anim") },
+ { "textBoxWeight", ("label3", "Forms.TileDataFilterForm.Labels.Weight") },
+ { "textBoxQuality", ("label4", "Forms.TileDataFilterForm.Labels.Quality") },
+ { "textBoxQuantity", ("label5", "Forms.TileDataFilterForm.Labels.Quantity") },
+ { "textBoxHue", ("label8", "Forms.TileDataFilterForm.Labels.Hue") },
+ { "textBoxStackOff", ("label7", "Forms.TileDataFilterForm.Labels.StackOff") },
+ { "textBoxValue", ("label6", "Forms.TileDataFilterForm.Labels.Value") },
+ { "textBoxHeigth", ("label11", "Forms.TileDataFilterForm.Labels.Height") }, // label11.Text = "Heigth" (typo in Designer)
+ { "textBoxUnk1", ("label10", "Forms.TileDataFilterForm.Labels.MiscData") },
+ { "textBoxUnk2", ("label9", "Forms.TileDataFilterForm.Labels.Unk2") },
+ { "textBoxUnk3", ("label12", "Forms.TileDataFilterForm.Labels.Unk3") },
+ { "textBoxNameLand", ("label23", "Forms.TileDataFilterForm.Labels.NameLand") },
+ { "textBoxTexID", ("label24", "Forms.TileDataFilterForm.Labels.TexID") }
+ };
+
+ // Create a map of label names to controls for quick lookup
+ var labelMap = new Dictionary();
+ foreach (Control control in GetAllControls(this))
+ {
+ if (control is Label && !string.IsNullOrEmpty(control.Name))
+ {
+ labelMap[control.Name] = control;
+ }
+ }
+
+ // Now apply localizations to each label based on its mapped textbox
+ foreach (var textbox in textboxToLabelName)
+ {
+ if (labelMap.TryGetValue(textbox.Value.labelName, out Control? labelControl))
+ {
+ if (labelControl is Label label)
+ {
+ var localized = _localizationGetter(textbox.Value.jsonKey);
+ if (localized != null)
+ label.Text = localized;
+ }
+ }
+ }
+
+ // Localize buttons
+ foreach (Control control in GetAllControls(this))
+ {
+ if (control is Button button)
+ {
+ if (button.Text == "Apply Filter" || button.Text == "应用过滤器")
+ {
+ var applyButton = _localizationGetter("Forms.TileDataFilterForm.ApplyButton");
+ if (applyButton != null)
+ button.Text = applyButton;
+ }
+ else if (button.Text == "Reset Filter" || button.Text == "重置过滤器")
+ {
+ var resetButton = _localizationGetter("Forms.TileDataFilterForm.ResetButton");
+ if (resetButton != null)
+ button.Text = resetButton;
+ }
+ }
+ }
+
+ // Re-initialize flag checkboxes with localized names
+ InitFlagCheckBoxes();
+ }
+
+ ///
+ /// Helper method to recursively get all controls.
+ ///
+ private IEnumerable GetAllControls(Control container)
+ {
+ foreach (Control control in container.Controls)
+ {
+ yield return control;
+ foreach (Control child in GetAllControls(control))
+ yield return child;
+ }
+ }
+
private void InitFlagCheckBoxes()
{
string[] enumNames = Enum.GetNames(typeof(TileFlag));
@@ -42,7 +163,10 @@ private void InitFlagCheckBoxes()
checkedListBox1.Items.Clear();
for (int i = 1; i < maxLength; ++i)
{
- checkedListBox1.Items.Add(enumNames[i], false);
+ string flagName = enumNames[i];
+ // 获取汉化文本,如果没有就用原始英文
+ string displayName = _localizationGetter?.Invoke($"Forms.TileDataControl.TileFlags.{flagName}") ?? flagName;
+ checkedListBox1.Items.Add(displayName, false);
}
checkedListBox1.EndUpdate();
@@ -51,7 +175,10 @@ private void InitFlagCheckBoxes()
checkedListBox2.Items.Clear();
for (int i = 1; i < maxLength; ++i)
{
- checkedListBox2.Items.Add(enumNames[i], false);
+ string flagName = enumNames[i];
+ // 获取汉化文本,如果没有就用原始英文
+ string displayName = _localizationGetter?.Invoke($"Forms.TileDataControl.TileFlags.{flagName}") ?? flagName;
+ checkedListBox2.Items.Add(displayName, false);
}
checkedListBox2.EndUpdate();
}
diff --git a/UoFiddler.Controls/Forms/TileDataHelpForm.cs b/UoFiddler.Controls/Forms/TileDataHelpForm.cs
index dc4bbf60..1f3ab14a 100644
--- a/UoFiddler.Controls/Forms/TileDataHelpForm.cs
+++ b/UoFiddler.Controls/Forms/TileDataHelpForm.cs
@@ -9,6 +9,7 @@
*
***************************************************************************/
+using System;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
@@ -18,155 +19,183 @@ namespace UoFiddler.Controls.Forms
{
public partial class TileDataHelpForm : Form
{
+ private Func? _localizationGetter;
+
public TileDataHelpForm()
{
InitializeComponent();
PopulateFields();
}
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ this.Text = _localizationGetter("Forms.TileDataHelpForm.Title") ?? "TileData Help";
+
+ // Localize column header
+ var fieldHeader = _localizationGetter("Forms.TileDataHelpForm.FieldColumnHeader") ?? "Field";
+ _columnField.Text = fieldHeader;
+
+ // Localize Close button
+ var closeButton = _localizationGetter("Forms.TileDataHelpForm.CloseButton") ?? "Close";
+ _btnClose.Text = closeButton;
+
+ // Clear and re-populate with localized content
+ _listView.Items.Clear();
+ PopulateFields();
+ }
+
private void PopulateFields()
{
- AddHeader("Editing many entries");
- Add("Multi-select",
- "Ctrl+click and Shift+click select several entries at once. The right hand pane keeps showing the entry "
- + "you picked last, and 'Save Changes' writes to every selected entry.",
+ // Helper function to get localized text
+ Func GetLocalized = (string key) =>
+ {
+ return _localizationGetter?.Invoke(key) ?? null;
+ };
+
+ // Editing many entries section
+ AddHeader(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.Title") ?? "Editing many entries");
+ Add(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.MultiSelect.Title") ?? "Multi-select",
+ GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.MultiSelect.Description")
+ ?? "Ctrl+click and Shift+click select several entries at once. The right hand pane keeps showing the entry you picked last, and 'Save Changes' writes to every selected entry.",
"multi");
- Add("Empty boxes",
- "With more than one entry selected, a box the entries disagree on comes up empty, and an empty box is "
- + "left alone when you save - the entries keep their own values. Fill it in to give them all the same "
- + "value. Because empty means 'leave alone', a name cannot be cleared across a multi-selection; select "
- + "the entry on its own to do that.",
+ Add(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.EmptyBoxes.Title") ?? "Empty boxes",
+ GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.EmptyBoxes.Description")
+ ?? "With more than one entry selected, a box the entries disagree on comes up empty, and an empty box is left alone when you save - the entries keep their own values. Fill it in to give them all the same value. Because empty means 'leave alone', a name cannot be cleared across a multi-selection; select the entry on its own to do that.",
"multi");
- Add("Greyed flags",
- "A flag that is set on some of the selected entries but not all shows greyed, and a greyed flag is left "
- + "alone when you save. Clicking it cycles leave alone -> set on all -> clear on all. A flag they all "
- + "already agree on just toggles.",
+ Add(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.GreyedFlags.Title") ?? "Greyed flags",
+ GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.GreyedFlags.Description")
+ ?? "A flag that is set on some of the selected entries but not all shows greyed, and a greyed flag is left alone when you save. Clicking it cycles leave alone -> set on all -> clear on all. A flag they all already agree on just toggles.",
"multi");
- Add("Copy / Paste special",
- "Right-click an entry and choose 'Copy tile data' to remember it, then select any number of entries and "
- + "choose 'Paste special...' to pick which of the copied fields and flags to write onto them.",
+ Add(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.CopyPasteSpecial.Title") ?? "Copy / Paste special",
+ GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.CopyPasteSpecial.Description")
+ ?? "Right-click an entry and choose 'Copy tile data' to remember it, then select any number of entries and choose 'Paste special...' to pick which of the copied fields and flags to write onto them.",
"multi");
- Add("Undo",
- "Misc -> 'Undo last bulk apply' puts back the values the entries had before the last apply. Only the "
- + "most recent apply is kept, and it is forgotten when tiledata is reloaded.",
+ Add(GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.Undo.Title") ?? "Undo",
+ GetLocalized("Forms.TileDataHelpForm.EditingManyEntries.Undo.Description")
+ ?? "Misc -> 'Undo last bulk apply' puts back the values the entries had before the last apply. Only the most recent apply is kept, and it is forgotten when tiledata is reloaded.",
"multi");
- AddHeader("Items");
- Add("Name", "This field is for the name of the item, which can be a maximum of 20 characters.", "items");
- Add("Animation", "This field is for the animation ID associated with the item.", "items");
- Add("Weight", "This field is for the weight of the item.", "items");
- Add("Layer", new StringBuilder()
- .AppendLine("This field is for the layer of the item:")
- .AppendLine("")
- .AppendLine("1 One handed weapon")
- .AppendLine("2 Two handed weapon, shield, or misc.")
- .AppendLine("3 Shoes")
- .AppendLine("4 Pants")
- .AppendLine("5 Shirt")
- .AppendLine("6 Helm / Line")
- .AppendLine("7 Gloves")
- .AppendLine("8 Ring")
- .AppendLine("9 Talisman")
- .AppendLine("10 Neck")
- .AppendLine("11 Hair")
- .AppendLine("12 Waist (half apron)")
- .AppendLine("13 Torso (inner) (chest armor)")
- .AppendLine("14 Bracelet")
- .AppendLine("15 Unused (but backpackers for backpackers go to 21)")
- .AppendLine("16 Facial Hair")
- .AppendLine("17 Torso (middle) (surcoat, tunic, full apron, sash)")
- .AppendLine("18 Earrings")
- .AppendLine("19 Arms")
- .AppendLine("20 Back (cloak)")
- .AppendLine("21 Backpack")
- .AppendLine("22 Torso (outer) (robe)")
- .AppendLine("23 Legs (outer) (skirt / kilt)")
- .AppendLine("24 Legs (inner) (leg armor)")
- .AppendLine("25 Mount (horse, ostard, etc)")
- .AppendLine("26 NPC Buy Restock container")
- .AppendLine("27 NPC Buy no restock container")
- .Append("28 NPC Sell container")
- .ToString(), "items");
- Add("Quantity", "This field is for the quantity of the item.", "items");
- Add("Value", "This field is for the value of the item.", "items");
- Add("Stacking Offset", new StringBuilder()
- .AppendLine("StackOff refers to the stacking offset in pixels when multiple items are stacked.")
- .Append("A higher StackOff value means the items will appear further apart from each other within the stack.")
- .ToString(), "items");
- Add("Hue", "This field is for the hue (color) of the item.", "items");
- Add("Unknown 2", "This field is for the second unknown value.", "items");
- Add("Misc Data", "Old UO Demo weapon template definition", "items");
- Add("Height", "This field is for the height of the item.", "items");
- Add("Unknown 3", "This field is for the third unknown value.", "items");
-
- AddHeader("Land Tiles");
- Add("Name", "This field is for the name of the land tile, which can be a maximum of 20 characters.", "land");
- Add("Texture ID", "This field is for the texture ID associated with the land tile.", "land");
-
- AddHeader("Flags");
- Add("Background", "Not yet documented.", "flags");
- Add("Weapon", "Not yet documented.", "flags");
- Add("Transparent", "Not yet documented.", "flags");
- Add("Translucent", "The tile is rendered with partial alpha-transparency.", "flags");
- Add("Wall", "The tile is a wall.", "flags");
- Add("Damaging", "The tile can cause damage when moved over.", "flags");
- Add("Impassable", "The tile may not be moved over or through.", "flags");
- Add("Wet", "Not yet documented.", "flags");
- Add("Unknown1", "Unknown.", "flags");
- Add("Surface", "The tile is a surface. It may be moved over, but not through.", "flags");
- Add("Bridge", "The tile is a stair, ramp, or ladder.", "flags");
- Add("Generic", "The tile is stackable.", "flags");
- Add("Window", "The tile is a window. Like NoShoot, tiles with this flag block line of sight.", "flags");
- Add("NoShoot", "The tile blocks line of sight.", "flags");
- Add("ArticleA", "For single-amount tiles, the string \"a \" should be prepended to the tile name.", "flags");
- Add("ArticleAn", "For single-amount tiles, the string \"an \" should be prepended to the tile name.", "flags");
- Add("ArticleThe", "Probably article \"The\" prepended to the tile name.", "flags");
- Add("Foliage", "The tile becomes translucent when walked behind. Boat masts also have this flag.", "flags");
- Add("PartialHue", "Only gray pixels will be hued.", "flags");
- Add("NoHouse", "NoHouse or Unknown. Needs further research.", "flags");
- Add("Map", "The tile is a map in the cartography sense. Unknown usage.", "flags");
- Add("Container", "The tile is a container.", "flags");
- Add("Wearable", "The tile may be equipped.", "flags");
- Add("LightSource", "The tile gives off light.", "flags");
- Add("Animation", "The tile is animated.", "flags");
- Add("HoverOver", "Gargoyles can fly over, or NoDiagonal.", "flags");
- Add("NoDiagonal", "NoDiagonal (Unknown3).", "flags");
- Add("Armor", "Not yet documented.", "flags");
- Add("Roof", "The tile is a slanted roof.", "flags");
- Add("Door", "The tile is a door. Tiles with this flag can be moved through by ghosts and GMs.", "flags");
- Add("StairBack", "Not yet documented.", "flags");
- Add("StairRight", "Not yet documented.", "flags");
- Add("AlphaBlend", "Blend Alphas, tile blending.", "flags");
- Add("UseNewArt", "Uses new art style? Something related to the nodraw tile?", "flags");
- Add("ArtUsed", "Has art being used?", "flags");
- Add("Unused8", "Unused or unknown yet.", "flags");
- Add("NoShadow", "Disallow shadow on this tile, light source? lava?", "flags");
- Add("PixelBleed", "Let pixels bleed in to other tiles? Is this Disabling Texture Clamp?", "flags");
- Add("PlayAnimOnce", "Play tile animation once.", "flags");
- Add("MultiMovable", "Movable multi? Cool ships and vehicles etc? Something related to the masts.", "flags");
- Add("Unused10", "Unused or unknown yet.", "flags");
- Add("Unused11", "Unused or unknown yet.", "flags");
- Add("Unused12", "Unused or unknown yet.", "flags");
- Add("Unused13", "Unused or unknown yet.", "flags");
- Add("Unused14", "Unused or unknown yet.", "flags");
- Add("Unused15", "Unused or unknown yet.", "flags");
- Add("Unused16", "Unused or unknown yet.", "flags");
- Add("Unused17", "Unused or unknown yet.", "flags");
- Add("Unused18", "Unused or unknown yet.", "flags");
- Add("Unused19", "Unused or unknown yet.", "flags");
- Add("Unused20", "Unused or unknown yet.", "flags");
- Add("Unused21", "Unused or unknown yet.", "flags");
- Add("Unused22", "Unused or unknown yet.", "flags");
- Add("Unused23", "Unused or unknown yet.", "flags");
- Add("Unused24", "Unused or unknown yet.", "flags");
- Add("Unused25", "Unused or unknown yet.", "flags");
- Add("Unused26", "Unused or unknown yet.", "flags");
- Add("Unused27", "Unused or unknown yet.", "flags");
- Add("Unused28", "Unused or unknown yet.", "flags");
- Add("Unused29", "Unused or unknown yet.", "flags");
- Add("Unused30", "Unused or unknown yet.", "flags");
- Add("Unused31", "Unused or unknown yet.", "flags");
- Add("Unused32", "Unused or unknown yet.", "flags");
+ // Items section
+ AddHeader(GetLocalized("Forms.TileDataHelpForm.Items.Title") ?? "Items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Name.Title") ?? "Name",
+ GetLocalized("Forms.TileDataHelpForm.Items.Name.Description")
+ ?? "This field is for the name of the item, which can be a maximum of 20 characters.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Animation.Title") ?? "Animation",
+ GetLocalized("Forms.TileDataHelpForm.Items.Animation.Description")
+ ?? "This field is for the animation ID associated with the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Weight.Title") ?? "Weight",
+ GetLocalized("Forms.TileDataHelpForm.Items.Weight.Description")
+ ?? "This field is for the weight of the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Layer.Title") ?? "Layer",
+ GetLocalized("Forms.TileDataHelpForm.Items.Layer.Description")
+ ?? "This field is for the layer of the item:\n\n1 One handed weapon\n2 Two handed weapon, shield, or misc.\n3 Shoes\n4 Pants\n5 Shirt\n6 Helm / Line\n7 Gloves\n8 Ring\n9 Talisman\n10 Neck\n11 Hair\n12 Waist (half apron)\n13 Torso (inner) (chest armor)\n14 Bracelet\n15 Unused (but backpackers for backpackers go to 21)\n16 Facial Hair\n17 Torso (middle) (surcoat, tunic, full apron, sash)\n18 Earrings\n19 Arms\n20 Back (cloak)\n21 Backpack\n22 Torso (outer) (robe)\n23 Legs (outer) (skirt / kilt)\n24 Legs (inner) (leg armor)\n25 Mount (horse, ostard, etc)\n26 NPC Buy Restock container\n27 NPC Buy no restock container\n28 NPC Sell container", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Quantity.Title") ?? "Quantity",
+ GetLocalized("Forms.TileDataHelpForm.Items.Quantity.Description")
+ ?? "This field is for the quantity of the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Value.Title") ?? "Value",
+ GetLocalized("Forms.TileDataHelpForm.Items.Value.Description")
+ ?? "This field is for the value of the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.StackingOffset.Title") ?? "Stacking Offset",
+ GetLocalized("Forms.TileDataHelpForm.Items.StackingOffset.Description")
+ ?? "StackOff refers to the stacking offset in pixels when multiple items are stacked.\nA higher StackOff value means the items will appear further apart from each other within the stack.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Hue.Title") ?? "Hue",
+ GetLocalized("Forms.TileDataHelpForm.Items.Hue.Description")
+ ?? "This field is for the hue (color) of the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Unknown2.Title") ?? "Unknown 2",
+ GetLocalized("Forms.TileDataHelpForm.Items.Unknown2.Description")
+ ?? "This field is for the second unknown value.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.MiscData.Title") ?? "Misc Data",
+ GetLocalized("Forms.TileDataHelpForm.Items.MiscData.Description")
+ ?? "Old UO Demo weapon template definition", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Height.Title") ?? "Height",
+ GetLocalized("Forms.TileDataHelpForm.Items.Height.Description")
+ ?? "This field is for the height of the item.", "items");
+ Add(GetLocalized("Forms.TileDataHelpForm.Items.Unknown3.Title") ?? "Unknown 3",
+ GetLocalized("Forms.TileDataHelpForm.Items.Unknown3.Description")
+ ?? "This field is for the third unknown value.", "items");
+
+ // Land Tiles section
+ AddHeader(GetLocalized("Forms.TileDataHelpForm.LandTiles.Title") ?? "Land Tiles");
+ Add(GetLocalized("Forms.TileDataHelpForm.LandTiles.Name.Title") ?? "Name",
+ GetLocalized("Forms.TileDataHelpForm.LandTiles.Name.Description")
+ ?? "This field is for the name of the land tile, which can be a maximum of 20 characters.", "land");
+ Add(GetLocalized("Forms.TileDataHelpForm.LandTiles.TextureID.Title") ?? "Texture ID",
+ GetLocalized("Forms.TileDataHelpForm.LandTiles.TextureID.Description")
+ ?? "This field is for the texture ID associated with the land tile.", "land");
+
+ // Flags section
+ AddHeader(GetLocalized("Forms.TileDataHelpForm.Flags.Title") ?? "Flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Background.Title") ?? "Background", GetLocalized("Forms.TileDataHelpForm.Flags.Background.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Weapon.Title") ?? "Weapon", GetLocalized("Forms.TileDataHelpForm.Flags.Weapon.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Transparent.Title") ?? "Transparent", GetLocalized("Forms.TileDataHelpForm.Flags.Transparent.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Translucent.Title") ?? "Translucent", GetLocalized("Forms.TileDataHelpForm.Flags.Translucent.Description") ?? "The tile is rendered with partial alpha-transparency.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Wall.Title") ?? "Wall", GetLocalized("Forms.TileDataHelpForm.Flags.Wall.Description") ?? "The tile is a wall.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Damaging.Title") ?? "Damaging", GetLocalized("Forms.TileDataHelpForm.Flags.Damaging.Description") ?? "The tile can cause damage when moved over.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Impassable.Title") ?? "Impassable", GetLocalized("Forms.TileDataHelpForm.Flags.Impassable.Description") ?? "The tile may not be moved over or through.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Wet.Title") ?? "Wet", GetLocalized("Forms.TileDataHelpForm.Flags.Wet.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unknown1.Title") ?? "Unknown1", GetLocalized("Forms.TileDataHelpForm.Flags.Unknown1.Description") ?? "Unknown.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Surface.Title") ?? "Surface", GetLocalized("Forms.TileDataHelpForm.Flags.Surface.Description") ?? "The tile is a surface. It may be moved over, but not through.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Bridge.Title") ?? "Bridge", GetLocalized("Forms.TileDataHelpForm.Flags.Bridge.Description") ?? "The tile is a stair, ramp, or ladder.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Generic.Title") ?? "Generic", GetLocalized("Forms.TileDataHelpForm.Flags.Generic.Description") ?? "The tile is stackable.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Window.Title") ?? "Window", GetLocalized("Forms.TileDataHelpForm.Flags.Window.Description") ?? "The tile is a window. Like NoShoot, tiles with this flag block line of sight.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.NoShoot.Title") ?? "NoShoot", GetLocalized("Forms.TileDataHelpForm.Flags.NoShoot.Description") ?? "The tile blocks line of sight.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.ArticleA.Title") ?? "ArticleA", GetLocalized("Forms.TileDataHelpForm.Flags.ArticleA.Description") ?? "For single-amount tiles, the string \"a \" should be prepended to the tile name.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.ArticleAn.Title") ?? "ArticleAn", GetLocalized("Forms.TileDataHelpForm.Flags.ArticleAn.Description") ?? "For single-amount tiles, the string \"an \" should be prepended to the tile name.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.ArticleThe.Title") ?? "ArticleThe", GetLocalized("Forms.TileDataHelpForm.Flags.ArticleThe.Description") ?? "Probably article \"The\" prepended to the tile name.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Foliage.Title") ?? "Foliage", GetLocalized("Forms.TileDataHelpForm.Flags.Foliage.Description") ?? "The tile becomes translucent when walked behind. Boat masts also have this flag.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.PartialHue.Title") ?? "PartialHue", GetLocalized("Forms.TileDataHelpForm.Flags.PartialHue.Description") ?? "Only gray pixels will be hued.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.NoHouse.Title") ?? "NoHouse", GetLocalized("Forms.TileDataHelpForm.Flags.NoHouse.Description") ?? "NoHouse or Unknown. Needs further research.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Map.Title") ?? "Map", GetLocalized("Forms.TileDataHelpForm.Flags.Map.Description") ?? "The tile is a map in the cartography sense. Unknown usage.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Container.Title") ?? "Container", GetLocalized("Forms.TileDataHelpForm.Flags.Container.Description") ?? "The tile is a container.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Wearable.Title") ?? "Wearable", GetLocalized("Forms.TileDataHelpForm.Flags.Wearable.Description") ?? "The tile may be equipped.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.LightSource.Title") ?? "LightSource", GetLocalized("Forms.TileDataHelpForm.Flags.LightSource.Description") ?? "The tile gives off light.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Animation.Title") ?? "Animation", GetLocalized("Forms.TileDataHelpForm.Flags.Animation.Description") ?? "The tile is animated.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.HoverOver.Title") ?? "HoverOver", GetLocalized("Forms.TileDataHelpForm.Flags.HoverOver.Description") ?? "Gargoyles can fly over, or NoDiagonal.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.NoDiagonal.Title") ?? "NoDiagonal", GetLocalized("Forms.TileDataHelpForm.Flags.NoDiagonal.Description") ?? "NoDiagonal (Unknown3).", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Armor.Title") ?? "Armor", GetLocalized("Forms.TileDataHelpForm.Flags.Armor.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Roof.Title") ?? "Roof", GetLocalized("Forms.TileDataHelpForm.Flags.Roof.Description") ?? "The tile is a slanted roof.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Door.Title") ?? "Door", GetLocalized("Forms.TileDataHelpForm.Flags.Door.Description") ?? "The tile is a door. Tiles with this flag can be moved through by ghosts and GMs.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.StairBack.Title") ?? "StairBack", GetLocalized("Forms.TileDataHelpForm.Flags.StairBack.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.StairRight.Title") ?? "StairRight", GetLocalized("Forms.TileDataHelpForm.Flags.StairRight.Description") ?? "Not yet documented.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.AlphaBlend.Title") ?? "AlphaBlend", GetLocalized("Forms.TileDataHelpForm.Flags.AlphaBlend.Description") ?? "Blend Alphas, tile blending.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.UseNewArt.Title") ?? "UseNewArt", GetLocalized("Forms.TileDataHelpForm.Flags.UseNewArt.Description") ?? "Uses new art style? Something related to the nodraw tile?", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.ArtUsed.Title") ?? "ArtUsed", GetLocalized("Forms.TileDataHelpForm.Flags.ArtUsed.Description") ?? "Has art being used?", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused8.Title") ?? "Unused8", GetLocalized("Forms.TileDataHelpForm.Flags.Unused8.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.NoShadow.Title") ?? "NoShadow", GetLocalized("Forms.TileDataHelpForm.Flags.NoShadow.Description") ?? "Disallow shadow on this tile, light source? lava?", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.PixelBleed.Title") ?? "PixelBleed", GetLocalized("Forms.TileDataHelpForm.Flags.PixelBleed.Description") ?? "Let pixels bleed in to other tiles? Is this Disabling Texture Clamp?", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.PlayAnimOnce.Title") ?? "PlayAnimOnce", GetLocalized("Forms.TileDataHelpForm.Flags.PlayAnimOnce.Description") ?? "Play tile animation once.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.MultiMovable.Title") ?? "MultiMovable", GetLocalized("Forms.TileDataHelpForm.Flags.MultiMovable.Description") ?? "Movable multi? Cool ships and vehicles etc? Something related to the masts.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused10.Title") ?? "Unused10", GetLocalized("Forms.TileDataHelpForm.Flags.Unused10.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused11.Title") ?? "Unused11", GetLocalized("Forms.TileDataHelpForm.Flags.Unused11.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused12.Title") ?? "Unused12", GetLocalized("Forms.TileDataHelpForm.Flags.Unused12.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused13.Title") ?? "Unused13", GetLocalized("Forms.TileDataHelpForm.Flags.Unused13.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused14.Title") ?? "Unused14", GetLocalized("Forms.TileDataHelpForm.Flags.Unused14.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused15.Title") ?? "Unused15", GetLocalized("Forms.TileDataHelpForm.Flags.Unused15.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused16.Title") ?? "Unused16", GetLocalized("Forms.TileDataHelpForm.Flags.Unused16.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused17.Title") ?? "Unused17", GetLocalized("Forms.TileDataHelpForm.Flags.Unused17.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused18.Title") ?? "Unused18", GetLocalized("Forms.TileDataHelpForm.Flags.Unused18.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused19.Title") ?? "Unused19", GetLocalized("Forms.TileDataHelpForm.Flags.Unused19.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused20.Title") ?? "Unused20", GetLocalized("Forms.TileDataHelpForm.Flags.Unused20.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused21.Title") ?? "Unused21", GetLocalized("Forms.TileDataHelpForm.Flags.Unused21.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused22.Title") ?? "Unused22", GetLocalized("Forms.TileDataHelpForm.Flags.Unused22.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused23.Title") ?? "Unused23", GetLocalized("Forms.TileDataHelpForm.Flags.Unused23.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused24.Title") ?? "Unused24", GetLocalized("Forms.TileDataHelpForm.Flags.Unused24.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused25.Title") ?? "Unused25", GetLocalized("Forms.TileDataHelpForm.Flags.Unused25.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused26.Title") ?? "Unused26", GetLocalized("Forms.TileDataHelpForm.Flags.Unused26.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused27.Title") ?? "Unused27", GetLocalized("Forms.TileDataHelpForm.Flags.Unused27.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused28.Title") ?? "Unused28", GetLocalized("Forms.TileDataHelpForm.Flags.Unused28.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused29.Title") ?? "Unused29", GetLocalized("Forms.TileDataHelpForm.Flags.Unused29.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused30.Title") ?? "Unused30", GetLocalized("Forms.TileDataHelpForm.Flags.Unused30.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused31.Title") ?? "Unused31", GetLocalized("Forms.TileDataHelpForm.Flags.Unused31.Description") ?? "Unused or unknown yet.", "flags");
+ Add(GetLocalized("Forms.TileDataHelpForm.Flags.Unused32.Title") ?? "Unused32", GetLocalized("Forms.TileDataHelpForm.Flags.Unused32.Description") ?? "Unused or unknown yet.", "flags");
if (_listView.Items.Count > 0)
{
diff --git a/UoFiddler.Controls/Forms/TileDataSyncPreviewForm.cs b/UoFiddler.Controls/Forms/TileDataSyncPreviewForm.cs
index 0bc681fe..edfedc97 100644
--- a/UoFiddler.Controls/Forms/TileDataSyncPreviewForm.cs
+++ b/UoFiddler.Controls/Forms/TileDataSyncPreviewForm.cs
@@ -27,6 +27,7 @@ private sealed class Row
private readonly List _rows = new();
private readonly Dictionary _rowByItem = new();
+ private Func? _localizationGetter;
public IReadOnlyList AcceptedChanges
{
@@ -80,6 +81,42 @@ public TileDataSyncPreviewForm(IReadOnlyList changes)
UpdateSummary();
}
+ ///
+ /// Set localization for TileDataSyncPreviewForm
+ ///
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// Apply localization to all UI elements
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // 窗口标题
+ this.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.Title") ?? "Sync from TileData — Preview";
+
+ // 表格列头
+ actionColumn.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.ColumnAction") ?? "Action";
+ numberColumn.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.ColumnNumber") ?? "Number";
+ oldTextColumn.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.ColumnCurrentText") ?? "Current text";
+ newTextColumn.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.ColumnNewText") ?? "New text";
+
+ // 按钮
+ checkAllButton.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.CheckAllButton") ?? "Check all";
+ uncheckAllButton.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.UncheckAllButton") ?? "Uncheck all";
+ uncheckRemovesButton.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.UncheckRemovesButton") ?? "Uncheck removes";
+ applyButton.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.ApplyButton") ?? "Apply";
+ cancelButton.Text = _localizationGetter("Forms.TileDataSyncPreviewForm.CancelButton") ?? "Cancel";
+
+ // 重新更新 Summary 标签以应用汉化的模板
+ UpdateSummary();
+ }
+
protected override void OnShown(EventArgs e)
{
base.OnShown(e);
@@ -165,7 +202,10 @@ private void UpdateSummary()
}
}
- summaryLabel.Text = $"Will apply: Add {selAdd}/{totalAdd} Update {selUpdate}/{totalUpdate} Remove {selRemove}/{totalRemove}";
+ // 使用汉化的 Summary 模板
+ string template = _localizationGetter?.Invoke("Forms.TileDataSyncPreviewForm.WillApplyTemplate")
+ ?? "Will apply: Add {0}/{1} Update {2}/{3} Remove {4}/{5}";
+ summaryLabel.Text = string.Format(template, selAdd, totalAdd, selUpdate, totalUpdate, selRemove, totalRemove);
}
private void SetCheckedForAll(bool value)
diff --git a/UoFiddler.Controls/Helpers/RichTextBoxExtensions.cs b/UoFiddler.Controls/Helpers/RichTextBoxExtensions.cs
index 136aa835..c944b5fc 100644
--- a/UoFiddler.Controls/Helpers/RichTextBoxExtensions.cs
+++ b/UoFiddler.Controls/Helpers/RichTextBoxExtensions.cs
@@ -9,6 +9,7 @@
*
***************************************************************************/
+using System;
using System.Windows.Forms;
namespace UoFiddler.Controls.Helpers
@@ -16,6 +17,11 @@ namespace UoFiddler.Controls.Helpers
public static class RichTextBoxExtensions
{
public static void AddBasicContextMenu(this RichTextBox richTextBox)
+ {
+ AddBasicContextMenu(richTextBox, null);
+ }
+
+ public static void AddBasicContextMenu(this RichTextBox richTextBox, Func? getLocalized)
{
if (richTextBox.ContextMenuStrip != null)
{
@@ -24,13 +30,15 @@ public static void AddBasicContextMenu(this RichTextBox richTextBox)
ContextMenuStrip menuStrip = new ContextMenuStrip { ShowImageMargin = false };
- ToolStripMenuItem menuItemCopy = new ToolStripMenuItem("Copy");
+ string copyText = getLocalized?.Invoke("Forms.ItemsControl.DetailTextBoxContextMenu.Copy") ?? "Copy";
+ ToolStripMenuItem menuItemCopy = new ToolStripMenuItem(copyText);
menuItemCopy.Click += (sender, e) => richTextBox.Copy();
menuStrip.Items.Add(menuItemCopy);
menuStrip.Items.Add(new ToolStripSeparator());
- ToolStripMenuItem menuItemSelectAll = new ToolStripMenuItem("Select All");
+ string selectAllText = getLocalized?.Invoke("Forms.ItemsControl.DetailTextBoxContextMenu.SelectAll") ?? "Select All";
+ ToolStripMenuItem menuItemSelectAll = new ToolStripMenuItem(selectAllText);
menuItemSelectAll.Click += (sender, e) => richTextBox.SelectAll();
menuStrip.Items.Add(menuItemSelectAll);
diff --git a/UoFiddler.Controls/Plugin/PluginBase.cs b/UoFiddler.Controls/Plugin/PluginBase.cs
index d653ed01..098bc93c 100644
--- a/UoFiddler.Controls/Plugin/PluginBase.cs
+++ b/UoFiddler.Controls/Plugin/PluginBase.cs
@@ -9,6 +9,7 @@
*
***************************************************************************/
+using System;
using System.Windows.Forms;
using Microsoft.Extensions.Logging;
using UoFiddler.Controls.Classes;
@@ -26,6 +27,11 @@ public abstract class PluginBase
public abstract string Author { get; }
public abstract string Version { get; }
+ ///
+ /// 静态属性:汉化字符串获取器,由主程序在启动时设置
+ ///
+ public static Func LocalizationGetter { get; set; }
+
///
/// Per-plugin logger, categorized by the concrete plugin type. Resolved on demand
/// since plugins are instantiated via Activator and cannot take constructor parameters.
diff --git a/UoFiddler.Controls/UserControls/AnimDataControl.cs b/UoFiddler.Controls/UserControls/AnimDataControl.cs
index 7e0ad8ce..956ee2dc 100644
--- a/UoFiddler.Controls/UserControls/AnimDataControl.cs
+++ b/UoFiddler.Controls/UserControls/AnimDataControl.cs
@@ -45,6 +45,10 @@ public AnimDataControl()
private HuePopUpForm _showForm;
private int _customHue = 0;
private bool _hueOnlyGray = false;
+ private Func? _localizationGetter;
+ private string _baseGraphicLabelPrefix = "Base Graphic: ";
+ private string _graphicLabelPrefix = "Graphic: ";
+ private string _hueLabelPrefix = "Hue: ";
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
private int CurrFrame
@@ -56,7 +60,7 @@ private int CurrFrame
{
var newGraphic = _currentSelect + value;
- toolStripStatusGraphic.Text = $"Graphic: {newGraphic} (0x{newGraphic:X})";
+ toolStripStatusGraphic.Text = $"{_graphicLabelPrefix}{newGraphic} (0x{newGraphic:X})";
MainPictureBox.FrameIndex = value;
_currentFrame = value;
}
@@ -88,8 +92,8 @@ private int CurrentSelect
}
treeViewFrames.EndUpdate();
- toolStripStatusBaseGraphic.Text = $"Base Graphic: {value} (0x{value:X})";
- toolStripStatusGraphic.Text = $"Graphic: {value} (0x{value:X})";
+ toolStripStatusBaseGraphic.Text = $"{_baseGraphicLabelPrefix}{value} (0x{value:X})";
+ toolStripStatusGraphic.Text = $"{_graphicLabelPrefix}{value} (0x{value:X})";
_currentSelect = value;
@@ -104,7 +108,7 @@ private void MainPictureBox_FrameChanged(object sender, EventArgs e)
{
var newGraphic = _currentSelect + MainPictureBox.FrameIndex;
- toolStripStatusGraphic.Text = $"Graphic: {newGraphic} (0x{newGraphic:X})";
+ toolStripStatusGraphic.Text = $"{_graphicLabelPrefix}{newGraphic} (0x{newGraphic:X})";
}
private void SetPicture()
@@ -302,6 +306,7 @@ private void OnClickExport(object sender, EventArgs e)
{
TopMost = true
};
+ _exportForm.SetLocalization(_localizationGetter);
_exportForm.Show();
}
@@ -318,6 +323,7 @@ private void OnClickImport(object sender, EventArgs e)
TopMost = true,
OnAfterImport = Reload
};
+ _importForm.SetLocalization(_localizationGetter);
_importForm.Show();
}
@@ -577,7 +583,11 @@ private void OnClickSave(object sender, EventArgs e)
Options.ChangedUltimaClass["Animdata"] = false;
}
- FileSavedDialog.Show(FindForm(), Options.OutputPath, "File saved successfully.");
+ // 获取汉化的保存成功消息
+ string message = _localizationGetter?.Invoke("Forms.FileSavedDialog.SaveSuccess") ?? "File saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Save Success";
+
+ FileSavedDialog.Show(FindForm(), Options.OutputPath, message, title, _localizationGetter ?? (k => null));
}
private void OnClickRemoveAnim(object sender, EventArgs e)
@@ -688,6 +698,7 @@ private void OnClick_Hue(object sender, EventArgs e)
? new HuePopUpForm(ChangeHue, 1)
: new HuePopUpForm(ChangeHue, _customHue - 1);
+ _showForm.SetLocalization(key => _localizationGetter?.Invoke(key));
_showForm.TopMost = true;
_showForm.Show();
}
@@ -698,7 +709,12 @@ private void OnClick_ExportAsGif(object sender, EventArgs e)
{
var outputFile = Path.Combine(Options.OutputPath, $"AnimData {Utils.FormatExportId(_currentSelect)}.gif");
MainPictureBox.Frames.ToGif(outputFile, delay: 150, showFrameBounds: MainPictureBox.ShowFrameBounds);
- MessageBox.Show($"Saved to {outputFile}");
+
+ var title = _localizationGetter?.Invoke("Forms.AnimDataControl.ExportGifDialog.Title") ?? "Saved";
+ var message = _localizationGetter?.Invoke("Forms.AnimDataControl.ExportGifDialog.Message") ?? "Saved to {0}";
+ message = string.Format(message, outputFile);
+
+ MessageBox.Show(message, title);
}
}
@@ -728,6 +744,64 @@ private void SearchByIdToolStripTextBox_KeyUp(object sender, KeyEventArgs e)
}
}
+ ///
+ /// 设置本地化(从 MainForm 调用)
+ ///
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// 应用汉化
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // GroupBox 标题
+ groupBox1.Text = _localizationGetter("Forms.AnimDataControl.PreviewGroupBox") ?? "Preview";
+ groupBox2.Text = _localizationGetter("Forms.AnimDataControl.DataGroupBox") ?? "Data";
+ groupBox4.Text = _localizationGetter("Forms.AnimDataControl.FramesGroupBox") ?? "Frames";
+
+ // Label
+ label1.Text = _localizationGetter("Forms.AnimDataControl.StartDelayLabel") ?? "Start Delay";
+ label2.Text = _localizationGetter("Forms.AnimDataControl.FrameDelayLabel") ?? "Frame Delay";
+
+ // Button
+ button2.Text = _localizationGetter("Forms.AnimDataControl.AddButton") ?? "Add";
+ button5.Text = _localizationGetter("Forms.AnimDataControl.RemoveButton") ?? "Remove";
+ button6.Text = _localizationGetter("Forms.AnimDataControl.SaveButton") ?? "Save";
+ button7.Text = _localizationGetter("Forms.AnimDataControl.ImportButton") ?? "Import...";
+ button8.Text = _localizationGetter("Forms.AnimDataControl.ExportButton") ?? "Export...";
+
+ // ToolStripMenuItem
+ addToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.AddMenuItem") ?? "Add";
+ removeToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.RemoveMenuItem") ?? "Remove";
+ hueToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.HueMenuItem") ?? "Hue";
+ animateToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.AnimateMenuItem") ?? "Animate";
+ showFrameBoundsToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.ShowFrameBoundsMenuItem") ?? "Show frame bounds";
+ exportAsAnimatedGifToolStripMenuItem.Text = _localizationGetter("Forms.AnimDataControl.ExportGifMenuItem") ?? "Export as animated Gif";
+
+ // ToolStrip
+ searchByIdToolStripLabel.Text = _localizationGetter("Forms.AnimDataControl.IndexLabel") ?? "Index:";
+ toolStripDropDownButton1.Text = _localizationGetter("Forms.AnimDataControl.SettingsButton") ?? "Settings";
+
+ // CheckBox
+ checkBoxRelative.Text = _localizationGetter("Forms.AnimDataControl.RelativeCheckBox") ?? "Relative";
+
+ // 状态栏标签前缀
+ _baseGraphicLabelPrefix = _localizationGetter("Forms.AnimDataControl.BaseGraphicLabel") ?? "Base Graphic: ";
+ _graphicLabelPrefix = _localizationGetter("Forms.AnimDataControl.GraphicLabel") ?? "Graphic: ";
+ _hueLabelPrefix = _localizationGetter("Forms.AnimDataControl.HueLabel") ?? "Hue: ";
+
+ // 设置初始状态栏显示
+ toolStripStatusBaseGraphic.Text = $"{_baseGraphicLabelPrefix}0 (0x0)";
+ toolStripStatusGraphic.Text = $"{_graphicLabelPrefix}0 (0x0)";
+ toolStripStatusHue.Text = _hueLabelPrefix + "0";
+ }
+
public static bool Select(int graphic)
{
if (_refMarker == null)
diff --git a/UoFiddler.Controls/UserControls/AnimationListControl.cs b/UoFiddler.Controls/UserControls/AnimationListControl.cs
index 3cc2df5c..fb235d33 100644
--- a/UoFiddler.Controls/UserControls/AnimationListControl.cs
+++ b/UoFiddler.Controls/UserControls/AnimationListControl.cs
@@ -37,6 +37,11 @@ public AnimationListControl()
listView1.Height += SystemInformation.HorizontalScrollBarHeight;
}
+ private Func? _localizationGetter;
+ private string _graphicLabelPrefix = "Graphic: ";
+ private string _baseGraphicLabelPrefix = "Base Graphic: ";
+ private string _hueLabelPrefix = "Hue: ";
+
public string[][] GetActionNames { get; } = {
// Monster
new[]
@@ -349,9 +354,9 @@ private void SetPicture()
_defHue = hue;
}
- BaseGraphicLabel.Text = $"BaseGraphic: {body} (0x{body:X})";
- GraphicLabel.Text = $"Graphic: {_currentSelect} (0x{_currentSelect:X})";
- HueLabel.Text = $"Hue: {hue + 1} (0x{hue + 1:X})";
+ BaseGraphicLabel.Text = $"{_baseGraphicLabelPrefix}{body} (0x{body:X})";
+ GraphicLabel.Text = $"{_graphicLabelPrefix}{_currentSelect} (0x{_currentSelect:X})";
+ HueLabel.Text = $"{_hueLabelPrefix}{hue + 1} (0x{hue + 1:X})";
LoadListViewFrames();
}
@@ -365,9 +370,9 @@ private void ClearPicture()
MainPictureBox.Frames = null;
LoadListViewFrames();
- BaseGraphicLabel.Text = "BaseGraphic:";
- GraphicLabel.Text = "Graphic: ";
- HueLabel.Text = "Hue:";
+ BaseGraphicLabel.Text = _baseGraphicLabelPrefix;
+ GraphicLabel.Text = _graphicLabelPrefix;
+ HueLabel.Text = _hueLabelPrefix;
}
private void TreeViewMobs_AfterSelect(object sender, TreeViewEventArgs e)
@@ -597,7 +602,9 @@ private void AddUopActionNodes(TreeNode parent, int body, int actionType)
? GetActionNames[actionType][i]
: $"Action{i}";
- parent.Nodes.Add(new TreeNode($"{i} {actionName}") { Tag = i });
+ // 使用汉化后的动作名称
+ string displayName = GetLocalizedActionName(actionName);
+ parent.Nodes.Add(new TreeNode($"{i} {displayName}") { Tag = i });
}
}
@@ -681,7 +688,9 @@ private void PopulateActionNodes(TreeNode bodyNode)
continue;
}
- bodyNode.Nodes.Add(new TreeNode($"{i} {GetActionNames[actionType][i]}") { Tag = i });
+ // 使用汉化后的动作名称
+ string displayName = GetLocalizedActionName(GetActionNames[actionType][i]);
+ bodyNode.Nodes.Add(new TreeNode($"{i} {displayName}") { Tag = i });
}
}
}
@@ -858,6 +867,7 @@ private void OnClick_Hue(object sender, EventArgs e)
? new HuePopUpForm(ChangeHue, _defHue + 1)
: new HuePopUpForm(ChangeHue, _customHue - 1);
+ _showForm.SetLocalization(key => _localizationGetter?.Invoke(key));
_showForm.TopMost = true;
_showForm.Show();
}
@@ -977,6 +987,7 @@ private void OnClickAnimationEdit(object sender, EventArgs e)
_animEditFormEntry = new AnimationEditForm();
//animEditEntry.TopMost = true; // TODO: should it be topMost?
+ _animEditFormEntry.SetLocalization(_localizationGetter);
_animEditFormEntry.Show();
}
@@ -989,7 +1000,7 @@ private void OnClickFindNewEntries(object sender, EventArgs e)
return;
}
- _animNewEntryForm = new AnimationListNewEntriesForm(IsAlreadyDefined, AddGraphic, GetActionNames)
+ _animNewEntryForm = new AnimationListNewEntriesForm(IsAlreadyDefined, AddGraphic, GetActionNames, _localizationGetter)
{
TopMost = true
};
@@ -1050,7 +1061,9 @@ private void RewriteXml(object sender, EventArgs e)
dom.Save(fileName);
}
- MessageBox.Show("XML saved", "Rewrite", MessageBoxButtons.OK, MessageBoxIcon.Information,
+ string message = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.RewriteMessage") ?? "XML saved";
+ string title = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.RewriteTitle") ?? "Rewrite";
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information,
MessageBoxDefaultButton.Button1);
}
@@ -1139,8 +1152,12 @@ private void ExtractImage(ImageFormat imageFormat)
newBitmap.Save(fileName, imageFormat);
}
- MessageBox.Show($"{what} saved to {fileName}", "Saved", MessageBoxButtons.OK, MessageBoxIcon.Information,
- MessageBoxDefaultButton.Button1);
+ // 获取汉化标题和消息
+ string title = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportSingleFrameTitle") ?? "Saved";
+ string messageTemplate = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportSingleFrameMessage") ?? "{0} saved to {1}";
+ string message = string.Format(messageTemplate, what, fileName);
+
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
private void OnClickExtractAnimBmp(object sender, EventArgs e)
@@ -1190,7 +1207,18 @@ private void ExportAnimationFrames(ImageFormat imageFormat)
}
}
- FileSavedDialog.Show(FindForm(), Options.OutputPath, $"Files with following format {fileName}-X.{fileExtension} saved successfully.");
+ string message = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportFramesMessage")
+ ?? $"Files with following format {fileName}-X.{fileExtension} saved successfully.";
+
+ if (_localizationGetter != null)
+ {
+ string title = _localizationGetter("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), Options.OutputPath, message, title, _localizationGetter);
+ }
+ else
+ {
+ FileSavedDialog.Show(FindForm(), Options.OutputPath, message);
+ }
}
private void OnClickExportFrameBmp(object sender, EventArgs e)
@@ -1227,7 +1255,7 @@ private void ExportSingleFrame(ImageFormat imageFormat)
}
string fileExtension = Utils.GetFileExtensionFor(imageFormat);
- string fileName = Path.Combine(Options.OutputPath, $"{what} {Utils.FormatExportId(_currentSelect)}");
+ string fileName = Path.Combine(Options.OutputPath, $"{what} {Utils.FormatExportId(_currentSelect)}-{(int)listView1.SelectedItems[0].Tag}.{fileExtension}");
Bitmap bit = MainPictureBox.Frames[(int)listView1.SelectedItems[0].Tag].Bitmap;
using (Bitmap newBitmap = new Bitmap(bit.Width, bit.Height))
@@ -1239,8 +1267,15 @@ private void ExportSingleFrame(ImageFormat imageFormat)
newGraph.Save();
}
- newBitmap.Save($"{fileName}-{(int)listView1.SelectedItems[0].Tag}.{fileExtension}", imageFormat);
+ newBitmap.Save(fileName, imageFormat);
}
+
+ // 获取汉化标题和消息
+ string title = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportSingleFrameTitle") ?? "Saved";
+ string messageTemplate = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportSingleFrameMessage") ?? "{0} saved to {1}";
+ string message = string.Format(messageTemplate, what, fileName);
+
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Information, MessageBoxDefaultButton.Button1);
}
private void OnClickExportAllThumbnailsBmp(object sender, EventArgs e)
@@ -1329,7 +1364,20 @@ private void ExportAllThumbnails(ImageFormat imageFormat)
}
}
- FileSavedDialog.Show(FindForm(), thumbnailPath, "All thumbnails saved successfully.");
+ // Localize message and title
+ string message = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportAllThumbnailsMessage")
+ ?? "All thumbnails saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportAllThumbnailsTitle")
+ ?? "Saved";
+
+ if (_localizationGetter != null)
+ {
+ FileSavedDialog.Show(FindForm(), thumbnailPath, message, title, _localizationGetter);
+ }
+ else
+ {
+ FileSavedDialog.Show(FindForm(), thumbnailPath, message);
+ }
}
private void ExportAnimatedGif(bool looping)
@@ -1342,7 +1390,109 @@ private void ExportAnimatedGif(bool looping)
var outputFile = Path.Combine(Options.OutputPath, $"{(_displayType == 1 ? "Equipment" : "Mob")} {_currentSelect}.gif");
MainPictureBox.Frames.ToGif(outputFile, looping: looping, delay: 150, showFrameBounds: MainPictureBox.ShowFrameBounds);
- FileSavedDialog.Show(FindForm(), outputFile, "InGame Anim saved successfully.");
+ // Localize message and title
+ string message = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportAnimatedGifMessage")
+ ?? "InGame Anim saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.AnimationListControl.Messages.ExportAnimatedGifTitle")
+ ?? "Saved";
+
+ if (_localizationGetter != null)
+ {
+ FileSavedDialog.Show(FindForm(), outputFile, message, title, _localizationGetter);
+ }
+ else
+ {
+ FileSavedDialog.Show(FindForm(), outputFile, message);
+ }
+ }
+
+ ///
+ /// 设置本地化获取器
+ ///
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// 应用本地化到所有 UI 元素
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // 搜索标签
+ searchToolStripLabel.Text = _localizationGetter("Forms.AnimationListControl.searchToolStripLabel") ?? "Search:";
+
+ // 右键菜单项
+ removeToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.removeToolStripMenuItem") ?? "Remove";
+
+ // 标签页
+ tabPage1.Text = _localizationGetter("Forms.AnimationListControl.tabPage1") ?? "Animation";
+ tabPage2.Text = _localizationGetter("Forms.AnimationListControl.tabPage2") ?? "Thumbnail List";
+
+ // 导出图像菜单
+ extractImageToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.extractImageToolStripMenuItem") ?? "Export Image..";
+ asBMpToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asBMpToolStripMenuItem") ?? "As Bmp";
+ asTiffToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asTiffToolStripMenuItem") ?? "As Tiff";
+ asJpgToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asJpgToolStripMenuItem") ?? "As Jpg";
+ asPngToolStripMenuItem2.Text = _localizationGetter("Forms.AnimationListControl.asPngToolStripMenuItem2") ?? "As Png";
+
+ // 导出动画菜单
+ extractAnimationToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.extractAnimationToolStripMenuItem") ?? "Export Animation..";
+ asBmpToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationListControl.asBmpToolStripMenuItem1") ?? "As Bmp";
+ asTiffToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationListControl.asTiffToolStripMenuItem1") ?? "As Tiff";
+ asJpgToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationListControl.asJpgToolStripMenuItem1") ?? "As Jpg";
+ asPngToolStripMenuItem1.Text = _localizationGetter("Forms.AnimationListControl.asPngToolStripMenuItem1") ?? "As Png";
+ asAnimatedGifToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asAnimatedGifToolStripMenuItem") ?? "As animated Gif (looping)";
+ asAnimatedGifnoLoopingToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asAnimatedGifnoLoopingToolStripMenuItem") ?? "As animated Gif (no looping)";
+
+ // 导出帧菜单
+ exportFrameToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.exportFrameToolStripMenuItem") ?? "Export Frame..";
+ asBmpToolStripMenuItem2.Text = _localizationGetter("Forms.AnimationListControl.asBmpToolStripMenuItem2") ?? "As Bmp";
+ asTiffToolStripMenuItem2.Text = _localizationGetter("Forms.AnimationListControl.asTiffToolStripMenuItem2") ?? "As Tiff";
+ asJpgToolStripMenuItem2.Text = _localizationGetter("Forms.AnimationListControl.asJpgToolStripMenuItem2") ?? "As Jpg";
+ asPngToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.asPngToolStripMenuItem") ?? "As Png";
+
+ // 导出所有缩略图菜单
+ exportAllThumbnailsToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.ContextMenu.exportAllThumbnailsToolStripMenuItem") ?? "Export All Thumbnails..";
+ asBmpToolStripMenuItem3.Text = _localizationGetter("Forms.AnimationListControl.ContextMenu.asBmpToolStripMenuItem3") ?? "As Bmp";
+ asTiffToolStripMenuItem3.Text = _localizationGetter("Forms.AnimationListControl.ContextMenu.asTiffToolStripMenuItem3") ?? "As Tiff";
+ asJpgToolStripMenuItem3.Text = _localizationGetter("Forms.AnimationListControl.ContextMenu.asJpgToolStripMenuItem3") ?? "As Jpg";
+ asPngToolStripMenuItem3.Text = _localizationGetter("Forms.AnimationListControl.ContextMenu.asPngToolStripMenuItem3") ?? "As Png";
+
+ // 帧设置组
+ groupBoxSettings.Text = _localizationGetter("Forms.AnimationListControl.groupBoxSettings") ?? "Frames";
+ directionLabel.Text = _localizationGetter("Forms.AnimationListControl.directionLabel") ?? "Direction";
+ ShowFrameBoundsCheckBox.Text = _localizationGetter("Forms.AnimationListControl.ShowFrameBoundsCheckBox") ?? "Show frame bounds";
+ AnimateCheckBox.Text = _localizationGetter("Forms.AnimationListControl.AnimateCheckBox") ?? "Animate";
+
+ // 设置菜单
+ SettingsButton.Text = _localizationGetter("Forms.AnimationListControl.SettingsButton") ?? "Settings";
+ sortAlphaToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.sortAlphaToolStripMenuItem") ?? "Sort alphabetical";
+ hueToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.hueToolStripMenuItem") ?? "Hue";
+ rewriteXmlToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.rewriteXmlToolStripMenuItem") ?? "Rewrite Xml";
+ tryToFindNewGraphicsToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.tryToFindNewGraphicsToolStripMenuItem") ?? "Try to find new Graphics";
+ animationEditToolStripMenuItem.Text = _localizationGetter("Forms.AnimationListControl.animationEditToolStripMenuItem") ?? "Animation edit";
+
+ // 状态栏标签
+ _graphicLabelPrefix = _localizationGetter("Forms.AnimationListControl.GraphicLabel") ?? "Graphic: ";
+ _baseGraphicLabelPrefix = _localizationGetter("Forms.AnimationListControl.BaseGraphicLabel") ?? "Base Graphic: ";
+ _hueLabelPrefix = _localizationGetter("Forms.AnimationListControl.HueLabel") ?? "Hue: ";
+
+ GraphicLabel.Text = _graphicLabelPrefix;
+ BaseGraphicLabel.Text = _baseGraphicLabelPrefix;
+ HueLabel.Text = _hueLabelPrefix;
+ }
+
+ ///
+ /// 获取动作名称的本地化文本(汉化)
+ ///
+ private string GetLocalizedActionName(string actionName)
+ {
+ if (_localizationGetter == null) return actionName;
+ return _localizationGetter($"Forms.AnimationListControl.ActionNames.{actionName}") ?? actionName;
}
private void OnClickExtractAnimGifLooping(object sender, EventArgs e)
diff --git a/UoFiddler.Controls/UserControls/ClilocControl.cs b/UoFiddler.Controls/UserControls/ClilocControl.cs
index 794489d5..e2d2ce7f 100644
--- a/UoFiddler.Controls/UserControls/ClilocControl.cs
+++ b/UoFiddler.Controls/UserControls/ClilocControl.cs
@@ -42,6 +42,78 @@ public ClilocControl()
private SortOrder _sortOrder;
private int _sortColumn;
private bool _loaded;
+ private Func? _localizationGetter;
+
+ ///
+ /// Set localization for CliLocControl
+ ///
+ public void SetLocalization(Func getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// Apply localization to all UI elements
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // 工具栏按钮和文本框
+ GotoEntry.Text = _localizationGetter("Forms.CliLocControl.GotoEntry") ?? "Enter Number";
+ GotoButton.Text = _localizationGetter("Forms.CliLocControl.GotoButton") ?? "Goto";
+ FindEntry.Text = _localizationGetter("Forms.CliLocControl.FindEntry") ?? "Enter Text";
+ FindButton.Text = _localizationGetter("Forms.CliLocControl.FindButton") ?? "Find";
+ RegexToolStripButton.Text = _localizationGetter("Forms.CliLocControl.RegexToolStripButton") ?? "Use regular expression";
+ toolStripButton1.Text = _localizationGetter("Forms.CliLocControl.SaveButton") ?? "Save";
+ ClilocExportButton.Text = _localizationGetter("Forms.CliLocControl.ExportButton") ?? "Export";
+ toolStripDropDownButton1.Text = _localizationGetter("Forms.CliLocControl.ImportButton") ?? "Import";
+
+ // 右键菜单项
+ copyCliLocNumberToolStripMenuItem.Text = _localizationGetter("Forms.CliLocControl.copyCliLocNumberToolStripMenuItem") ?? "Copy CliLoc Number";
+ copyCliLocTextToolStripMenuItem.Text = _localizationGetter("Forms.CliLocControl.copyCliLocTextToolStripMenuItem") ?? "Copy CliLoc Text";
+ addEntryToolStripMenuItem.Text = _localizationGetter("Forms.CliLocControl.addEntryToolStripMenuItem") ?? "Add Entry";
+ deleteEntryToolStripMenuItem.Text = _localizationGetter("Forms.CliLocControl.deleteEntryToolStripMenuItem") ?? "Delete Entry";
+
+ // 导入菜单项 (CSV 保持英文,不汉化)
+ // cSVToolStripMenuItem.Text 保持 "CSV"
+ tileDataToolStripMenuItem.Text = _localizationGetter("Forms.CliLocControl.tileDataToolStripMenuItem") ?? "Sync from TileData";
+
+ // 语言下拉菜单项
+ LangComboBox.Items.Clear();
+ LangComboBox.Items.Add(_localizationGetter("Forms.CliLocControl.LangComboBoxEnglish") ?? "English");
+ LangComboBox.Items.Add(_localizationGetter("Forms.CliLocControl.LangComboBoxGerman") ?? "German");
+ LangComboBox.Items.Add(_localizationGetter("Forms.CliLocControl.LangComboBoxCustom1") ?? "Custom 1");
+ LangComboBox.Items.Add(_localizationGetter("Forms.CliLocControl.LangComboBoxCustom2") ?? "Custom 2");
+
+ // 表格列头
+ if (dataGridView1.Columns.Count > 0)
+ {
+ dataGridView1.Columns[0].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnNumber") ?? "Number";
+ dataGridView1.Columns[1].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnText") ?? "Text";
+ if (dataGridView1.Columns.Count > 2)
+ {
+ dataGridView1.Columns[2].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnFlag") ?? "Flag";
+ }
+ }
+ }
+
+ ///
+ /// Apply column headers localization
+ ///
+ private void ApplyColumnHeaders()
+ {
+ if (dataGridView1.Columns.Count > 0)
+ {
+ dataGridView1.Columns[0].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnNumber") ?? "Number";
+ dataGridView1.Columns[1].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnText") ?? "Text";
+ if (dataGridView1.Columns.Count > 2)
+ {
+ dataGridView1.Columns[2].HeaderText = _localizationGetter("Forms.CliLocControl.ColumnFlag") ?? "Flag";
+ }
+ }
+ }
///
/// Sets Language and loads cliloc
@@ -72,7 +144,9 @@ private int Lang
if (!string.IsNullOrEmpty(_cliloc?.LoadWarning))
{
- MessageBox.Show(this, _cliloc.LoadWarning, "Cliloc parsed with warnings",
+ string warningTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.ClilocLoadWarningTitle")
+ ?? "Cliloc parsed with warnings";
+ MessageBox.Show(this, _cliloc.LoadWarning, warningTitle,
MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
}
@@ -109,6 +183,8 @@ private void OnLoad(object sender, EventArgs e)
dataGridView1.DataSource = _source;
if (dataGridView1.Columns.Count > 0)
{
+ // 应用列头汉化
+ ApplyColumnHeaders();
dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
dataGridView1.Columns[0].Width = 60;
dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.None;
@@ -187,6 +263,8 @@ private void OnLangChange(object sender, EventArgs e)
if (dataGridView1.Columns.Count > 0)
{
+ // 应用列头汉化
+ ApplyColumnHeaders();
dataGridView1.Columns[0].HeaderCell.SortGlyphDirection = SortOrder.Ascending;
dataGridView1.Columns[0].Width = 60;
dataGridView1.Columns[1].HeaderCell.SortGlyphDirection = SortOrder.None;
@@ -215,9 +293,14 @@ private void GotoNr(object sender, EventArgs e)
}
}
+ string gotoNotFoundMessage = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.NumberNotFound")
+ ?? "Number not found.";
+ string gotoTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.GotoTitle")
+ ?? "Goto";
+
MessageBox.Show(
- "Number not found.",
- "Goto",
+ gotoNotFoundMessage,
+ gotoTitle,
MessageBoxButtons.OK,
MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
@@ -227,7 +310,11 @@ private void FindEntryClick(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(FindEntry.Text) || FindEntry.Text == _searchTextPlaceholder)
{
- MessageBox.Show("Please provide search text", "Find Entry", MessageBoxButtons.OK, MessageBoxIcon.Error,
+ string message = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.PleaseProvideSearchText")
+ ?? "Please provide search text";
+ string title = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.FindEntryTitle")
+ ?? "Find Entry";
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
return;
@@ -256,7 +343,12 @@ private void FindEntryClick(object sender, EventArgs e)
return;
}
- MessageBox.Show(hasErrors ? "Invalid regular expression." : "Entry not found.", "Find Entry",
+ string msgContent = hasErrors
+ ? (_localizationGetter?.Invoke("Forms.CliLocControl.Messages.InvalidRegex") ?? "Invalid regular expression.")
+ : (_localizationGetter?.Invoke("Forms.CliLocControl.Messages.EntryNotFound") ?? "Entry not found.");
+ string msgTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.FindEntryTitle")
+ ?? "Find Entry";
+ MessageBox.Show(msgContent, msgTitle,
MessageBoxButtons.OK, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
}
@@ -282,7 +374,11 @@ private void FindPreviousEntry()
{
if (string.IsNullOrEmpty(FindEntry.Text) || FindEntry.Text == _searchTextPlaceholder)
{
- MessageBox.Show("Please provide search text", "Find Entry", MessageBoxButtons.OK, MessageBoxIcon.Error,
+ string message = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.PleaseProvideSearchText")
+ ?? "Please provide search text";
+ string title = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.FindEntryTitle")
+ ?? "Find Entry";
+ MessageBox.Show(message, title, MessageBoxButtons.OK, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
return;
@@ -318,7 +414,12 @@ private void FindPreviousEntry()
return;
}
- MessageBox.Show(hasErrors ? "Invalid regular expression." : "Entry not found.", "Find Entry",
+ string notFoundMessage = hasErrors
+ ? (_localizationGetter?.Invoke("Forms.CliLocControl.Messages.InvalidRegex") ?? "Invalid regular expression.")
+ : (_localizationGetter?.Invoke("Forms.CliLocControl.Messages.EntryNotFound") ?? "Entry not found.");
+ string dialogTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.FindEntryTitle")
+ ?? "Find Entry";
+ MessageBox.Show(notFoundMessage, dialogTitle,
MessageBoxButtons.OK, MessageBoxIcon.Error,
MessageBoxDefaultButton.Button1);
}
@@ -349,7 +450,10 @@ private void OnClickSave(object sender, EventArgs e)
dataGridView1.Invalidate();
Options.ChangedUltimaClass["CliLoc"] = false;
- FileSavedDialog.Show(FindForm(), Options.OutputPath, "CliLoc saved successfully.");
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title")
+ ?? "Saved";
+
+ FileSavedDialog.Show(FindForm(), Options.OutputPath, null, title, key => _localizationGetter?.Invoke(key));
}
private void OnCell_dbClick(object sender, DataGridViewCellEventArgs e)
@@ -558,15 +662,21 @@ private void OnClickExportCSV(object sender, EventArgs e)
}
}
- FileSavedDialog.Show(FindForm(), fileName, "CliLoc saved successfully.");
+ // 使用支持汉化的 Show 重载
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), fileName, "CliLoc saved successfully.", title, key => _localizationGetter?.Invoke(key));
}
private void OnClickImportCSV(object sender, EventArgs e)
{
+ // 获取汉化的标题
+ string dialogTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.ImportChooseFileTitle")
+ ?? "Choose csv file to import";
+
OpenFileDialog dialog = new OpenFileDialog
{
Multiselect = false,
- Title = "Choose csv file to import",
+ Title = dialogTitle,
CheckFileExists = true,
Filter = "csv files (*.csv)|*.csv"
};
@@ -640,16 +750,26 @@ private void OnClickImportCSV(object sender, EventArgs e)
}
}
+ // 获取汉化的消息框文本
+ string doneTitle = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.ImportDoneTitle")
+ ?? "Import Done";
+
if (count > 0)
{
Options.ChangedUltimaClass["CliLoc"] = true;
_source.ResetBindings(false);
dataGridView1.Invalidate();
- MessageBox.Show(this, $"{count} entries changed.", "Import Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
+
+ string messageTemplate = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.ImportEntriesChanged")
+ ?? "{0} entries changed.";
+ string message = string.Format(messageTemplate, count);
+ MessageBox.Show(this, message, doneTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else
{
- MessageBox.Show(this, "No entries changed.", "Import Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
+ string noChangeMessage = _localizationGetter?.Invoke("Forms.CliLocControl.Messages.ImportNoEntriesChanged")
+ ?? "No entries changed.";
+ MessageBox.Show(this, noChangeMessage, doneTitle, MessageBoxButtons.OK, MessageBoxIcon.Information);
}
}
}
@@ -673,6 +793,7 @@ private void TileDataToolStripMenuItem_Click(object sender, EventArgs e)
}
preview = new TileDataSyncPreviewForm(changes);
+ preview.SetLocalization(_localizationGetter);
}
catch
{
diff --git a/UoFiddler.Controls/UserControls/DressControl.cs b/UoFiddler.Controls/UserControls/DressControl.cs
index d3ae25ec..e6984672 100644
--- a/UoFiddler.Controls/UserControls/DressControl.cs
+++ b/UoFiddler.Controls/UserControls/DressControl.cs
@@ -44,6 +44,9 @@ public DressControl()
private int[] _displayedItems = Array.Empty();
private Color[] _displayedColors = Array.Empty();
+ // Localization support
+ private Func? _localizationGetter;
+
private int GetSelectedObjType()
{
return listViewItems.SelectedIndices.Count > 0
@@ -181,6 +184,58 @@ public void SetHue(int index, int color)
_hues[index] = color;
}
+ ///
+ /// Sets the localization getter and applies localized text.
+ ///
+ public void SetLocalization(Func? getLocalized)
+ {
+ _localizationGetter = getLocalized;
+ ApplyLocalization();
+ }
+
+ ///
+ /// Applies localized text to UI elements.
+ ///
+ private void ApplyLocalization()
+ {
+ if (_localizationGetter == null) return;
+
+ // Buttons and Labels
+ FindNextItemButton.Text = _localizationGetter("Forms.DressControl.FindNextItemButton") ?? "Find next";
+ button1.Text = _localizationGetter("Forms.DressControl.ExportReportButton") ?? "Export Report";
+ LayerSort.Text = _localizationGetter("Forms.DressControl.LayerSort") ?? "Layer Sort";
+ buttonDress.Text = _localizationGetter("Forms.DressControl.DressItemButton") ?? "Dress Item";
+ checkBoxfemale.Text = _localizationGetter("Forms.DressControl.FemaleCheckBox") ?? "Female";
+ checkBoxHuman.Text = _localizationGetter("Forms.DressControl.HumanRadio") ?? "Human";
+ checkBoxElve.Text = _localizationGetter("Forms.DressControl.ElfRadio") ?? "Elf";
+ checkBoxGargoyle.Text = _localizationGetter("Forms.DressControl.GargoyleRadio") ?? "Gargoyle";
+ groupBox1.Text = _localizationGetter("Forms.DressControl.MountGroupBox") ?? "Mount";
+ groupBoxAnimate.Text = _localizationGetter("Forms.DressControl.FacingActionGroupBox") ?? "Facing/Action";
+ listViewItemsColumn.Text = _localizationGetter("Forms.DressControl.ItemColumnHeader") ?? "Item";
+
+ // Context Menu 1 (Wear List)
+ unDressToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.UnDress") ?? "UnDress";
+ huToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.Hue") ?? "Hue";
+ hueToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.HueEllipsis") ?? "Hue..";
+ unDressAllToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.UnDressAll") ?? "UnDress All";
+
+ // Context Menu 2 (Picture)
+ showAnimationToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.ShowAnimation") ?? "Show Animation";
+ animateToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.Animate") ?? "Animate";
+ extractImageToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.ExportImage") ?? "Export Image..";
+ asBmpToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsBmp") ?? "As Bmp";
+ asTiffToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsTiff") ?? "As Tiff";
+ asJpgToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsJpg") ?? "As Jpg";
+ asPngToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsPng") ?? "As Png";
+ extractAnimationToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.ExportAnimation") ?? "Export Animation..";
+ asBmpToolStripMenuItem1.Text = _localizationGetter("Forms.DressControl.AsBmp") ?? "As Bmp";
+ asTiffToolStripMenuItem1.Text = _localizationGetter("Forms.DressControl.AsTiff") ?? "As Tiff";
+ asJpgToolStripMenuItem1.Text = _localizationGetter("Forms.DressControl.AsJpg") ?? "As Jpg";
+ asPngToolStripMenuItem1.Text = _localizationGetter("Forms.DressControl.AsPng") ?? "As Png";
+ asAnimatedGifToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsAnimatedGifLooping") ?? "As animated Gif (looping)";
+ asAnimatedGifnoLoopingToolStripMenuItem.Text = _localizationGetter("Forms.DressControl.AsAnimatedGifNoLooping") ?? "As animated Gif (no looping)";
+ }
+
///
/// Reload when loaded
///
@@ -798,14 +853,25 @@ private void UpdateSelection(int objType)
pictureBoxDress.Invalidate();
TextBox.Clear();
+
+ // Get localized labels
+ string objTypeLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.ObjType") ?? "Objtype";
+ string layerLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.Layer") ?? "Layer";
+ string gumpIdLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.GumpID") ?? "GumpID";
+ string hueLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.Hue") ?? "Hue";
+ string animationLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.Animation") ?? "Animation";
+ string validGumpLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.ValidGump") ?? "ValidGump";
+ string validAnimLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.ValidAnim") ?? "ValidAnim";
+ string validLayerLabel = _localizationGetter?.Invoke("Forms.DressControl.InfoLabels.ValidLayer") ?? "ValidLayer";
+
TextBox.AppendText(
- $"Objtype: 0x{objType:X4}\nLayer: 0x{TileData.ItemTable[objType].Quality:X2}\n");
- TextBox.AppendText($"GumpID: 0x{gump:X4} (0x{gumpOrig:X4})\nHue: {hue + 1}\n");
- TextBox.AppendText($"Animation: 0x{ani:X4} (0x{TileData.ItemTable[objType].Animation:X4})\n");
+ $"{objTypeLabel}: 0x{objType:X4}\n{layerLabel}: 0x{TileData.ItemTable[objType].Quality:X2}\n");
+ TextBox.AppendText($"{gumpIdLabel}: 0x{gump:X4} (0x{gumpOrig:X4})\n{hueLabel}: {hue + 1}\n");
+ TextBox.AppendText($"{animationLabel}: 0x{ani:X4} (0x{TileData.ItemTable[objType].Animation:X4})\n");
TextBox.AppendText(
- $"ValidGump: {Gumps.IsValidIndex(gump)}\nValidAnim: {Animations.IsActionDefined(ani, 0, 0)}\n");
+ $"{validGumpLabel}: {Gumps.IsValidIndex(gump)}\n{validAnimLabel}: {Animations.IsActionDefined(ani, 0, 0)}\n");
TextBox.AppendText(
- $"ValidLayer: {Array.IndexOf(_drawOrder, TileData.ItemTable[objType].Quality) != -1}");
+ $"{validLayerLabel}: {Array.IndexOf(_drawOrder, TileData.ItemTable[objType].Quality) != -1}");
}
private void OnClick_Animate(object sender, EventArgs e)
@@ -988,13 +1054,13 @@ private void OnClick_ChangeDisplay(object sender, EventArgs e)
{
groupBoxAnimate.Visible = false;
animateToolStripMenuItem.Visible = false;
- showAnimationToolStripMenuItem.Text = "Show Animation";
+ showAnimationToolStripMenuItem.Text = _localizationGetter?.Invoke("Forms.DressControl.ShowAnimation") ?? "Show Animation";
}
else
{
groupBoxAnimate.Visible = true;
animateToolStripMenuItem.Visible = true;
- showAnimationToolStripMenuItem.Text = "Show Paperdoll";
+ showAnimationToolStripMenuItem.Text = _localizationGetter?.Invoke("Forms.DressControl.ShowPaperdoll") ?? "Show Paperdoll";
}
RefreshDrawing();
@@ -1346,7 +1412,9 @@ private void ExportImage(ImageFormat imageFormat)
string fileName = Path.Combine(outputPath, $"Dress PD.{fileExtension}");
DressPic.Image.Save(fileName, imageFormat);
- FileSavedDialog.Show(FindForm(), fileName, "Paperdoll saved successfully.");
+ string message = _localizationGetter?.Invoke("Forms.DressControl.ExportMessages.PaperdollSaved") ?? "Paperdoll saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), fileName, message, title, key => _localizationGetter?.Invoke(key));
}
else
{
@@ -1360,8 +1428,9 @@ private void ExportImage(ImageFormat imageFormat)
DressPic.Image.Save(fileName, imageFormat);
}
-
- FileSavedDialog.Show(FindForm(), fileName, "InGame saved successfully.");
+ string message = _localizationGetter?.Invoke("Forms.DressControl.ExportMessages.InGameSaved") ?? "InGame saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), fileName, message, title, key => _localizationGetter?.Invoke(key));
}
}
@@ -1397,7 +1466,9 @@ private void ExportAnimation(ImageFormat imageFormat)
_animation[i].Save(Path.Combine(path, $"{fileName}-{i}.{fileExtension}"), imageFormat);
}
- FileSavedDialog.Show(FindForm(), path, "InGame Anim saved successfully.");
+ string message = _localizationGetter?.Invoke("Forms.DressControl.ExportMessages.AnimSaved") ?? "InGame Anim saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), path, message, title, key => _localizationGetter?.Invoke(key));
}
private void ExportAnimatedGif(bool looping)
@@ -1432,7 +1503,9 @@ private void ExportAnimatedGif(bool looping)
stream.WriteByte(0);
}
- FileSavedDialog.Show(FindForm(), outputFile, "InGame Anim saved successfully.");
+ string message = _localizationGetter?.Invoke("Forms.DressControl.ExportMessages.AnimSaved") ?? "InGame Anim saved successfully.";
+ string title = _localizationGetter?.Invoke("Forms.FileSavedDialog.Title") ?? "Saved";
+ FileSavedDialog.Show(FindForm(), outputFile, message, title, key => _localizationGetter?.Invoke(key));
}
private void OnClickExtractAnimGifLooping(object sender, EventArgs e)
{
@@ -1706,7 +1779,10 @@ private void OnClickBuildAnimationList(object sender, EventArgs e)
tex.WriteLine("