changeset 98:fac0636ae13b

Re #308: Make GTK# UI translatable * Make undo/redo menus translate on language change * Organise English language file * Resolve warnings by adding in dialogs that use translated strings when equipment amounts are out of range
author IBBoard <dev@ibboard.co.uk>
date Sun, 02 Jan 2011 21:03:15 +0000
parents 6d2c8ad0d8f1
children 8777e4f64d8e
files FrmMainWindow.cs UIControl/AbstractBaseEquipmentUIControl.cs gtk-gui/IBBoard.WarFoundry.GUI.GTK.FrmAddEquipment.cs gtk-gui/gui.stetic translations/en.translation translations/fr.translation
diffstat 6 files changed, 150 insertions(+), 75 deletions(-) [+]
line wrap: on
line diff
--- a/FrmMainWindow.cs	Sun Jan 02 15:50:29 2011 +0000
+++ b/FrmMainWindow.cs	Sun Jan 02 21:03:15 2011 +0000
@@ -40,7 +40,6 @@
 		private Preferences preferences;
 		private ILog logger = LogManager.GetLogger(typeof(FrmMainWindow));
 		private CommandStack commandStack;
-		private Dictionary<ToolButton, Category> categoryMap = new Dictionary<ToolButton, Category>();
 		private Dictionary<WFObjects.Unit, UnitDisplayWidget> unitToWidgetMap = new Dictionary<WFObjects.Unit,UnitDisplayWidget>();
 		private ObjectAddDelegate UnitAddedMethod;
 		private ObjectRemoveDelegate UnitRemovedMethod;
@@ -225,6 +224,7 @@
 			base.Translate();
 			SetAppTitle();
 			treeUnits.GetColumn(0).Title = Translation.GetTranslation("armyCategoryColumnTitle", "categories");
+			RebuildUndoRedoMenus();
 		}
 
 		private void Retranslate()
@@ -414,11 +414,6 @@
 			set { preferences = value; }
 		}
 
-		/*public AbstractNativeWarFoundryFactory Factory
-		{
-			get { return WarFoundryFactoryFactory.GetFactoryFactory().GetFactory(Constants.ExecutablePath, factoryType); }
-		}*/
-
 		protected void OnDeleteEvent(object sender, DeleteEventArgs a)
 		{
 			Application.Quit();
@@ -464,8 +459,8 @@
 		{
 			if (sender is ToolButton)
 			{
-				Category cat = null;
-				categoryMap.TryGetValue((ToolButton)sender, out cat);
+				ToolButton toolButton = (ToolButton)sender;
+				Category cat = (Category)toolButton.Data["Category"];
 
 				if (cat != null)
 				{
@@ -634,8 +629,6 @@
 			{
 				toolbar.Remove(toolbar.Children[i]);
 			}
-
-			categoryMap.Clear();
 		}
 
 		private void AddCategoryButtons(Category[] cats)
@@ -649,8 +642,7 @@
 					ToolButton button = new ToolButton("gtk-add");
 					button.Label = cat.Name;
 					button.TooltipText = Translation.GetTranslation("bttnCreateFromCat", "{0}", cat.Name);
-					//TODO: See if we can associate data in some way, the same as we can with SWF. For now we just use the map.
-					categoryMap.Add(button, cat);
+					button.Data["Category"] = cat;
 					button.Clicked += new System.EventHandler(OnAddUnitActivated);
 					toolbar.Insert(button, -1);
 				}
@@ -672,26 +664,33 @@
 			miUndo.Sensitive = undoMenuButton.Sensitive;
 			redoMenuButton.Sensitive = commandStack.CanRedo();
 			miRedo.Sensitive = redoMenuButton.Sensitive;
+
+			RebuildUndoRedoMenus();
+
+			bttnSaveArmy.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy != null;
+			miSaveArmy.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy != null;
+		}
+
+		private void RebuildUndoRedoMenus()
+		{
 			int redoLength = commandStack.RedoLength;
-
 			int maxRedo = Math.Min(10, redoLength);
 			
-			//TODO: Add tooltips
 			if (redoLength > 0)
 			{
 				Menu menu = new Menu();
 				Command com;
 				MenuItem mi;
-
+			
 				for (int i = 0; i < maxRedo; i++)
 				{
 					com = commandStack.PeekRedoCommand(i + 1);
-
+			
 					if (com == null)
 					{
 						break;
 					}
-
+			
 					mi = new MenuItem(com.Description);
 					mi.Activated += new EventHandler(RedoMenuActivated);
 					menu.Append(mi);
@@ -707,22 +706,22 @@
 			
 			int undoLength = commandStack.UndoLength;
 			int maxUndo = Math.Min(10, undoLength);
-
+			
 			if (undoLength > 0)
 			{
 				Menu menu = new Menu();
 				Command com;
 				MenuItem mi;
-
+			
 				for (int i = 0; i < maxUndo; i++)
 				{
 					com = commandStack.PeekUndoCommand(i + 1);
-
+			
 					if (com == null)
 					{
 						break;
 					}
-
+			
 					mi = new MenuItem(com.UndoDescription);
 					mi.Activated += new EventHandler(UndoMenuActivated);
 					menu.Add(mi);
@@ -735,9 +734,6 @@
 			{
 				undoMenuButton.Menu = null;
 			}
-
-			bttnSaveArmy.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy != null;
-			miSaveArmy.Sensitive = commandStack.IsDirty() && WarFoundryCore.CurrentArmy != null;
 		}
 
 		private void RedoMenuActivated(object sender, EventArgs e)
@@ -793,10 +789,13 @@
 
 		private bool OpenArmy()
 		{
-			FileChooserDialog fileDialog = new FileChooserDialog("Open army", this, FileChooserAction.Open, "Cancel", ResponseType.Cancel, "Open", ResponseType.Accept);
+			string title = Translation.GetTranslation("openArmyDialog", "open army");
+			string cancelText = Translation.GetTranslation("bttnCancel", "cancel");
+			string openText = Translation.GetTranslation("bttnOpen", "open");
+			FileChooserDialog fileDialog = new FileChooserDialog(title, this, FileChooserAction.Open, cancelText, ResponseType.Cancel, openText, ResponseType.Accept);
 			FileFilter filter = new FileFilter();
 			filter.AddPattern("*.army");
-			filter.Name = "WarFoundry Army files (*.army)";
+			filter.Name = Translation.GetTranslation("armyFileFilter", "WarFoundry .army files");
 			fileDialog.AddFilter(filter);
 			int response = fileDialog.Run();
 			string filePath = null;
@@ -814,7 +813,16 @@
 			if (filePath != null)
 			{
 				FileInfo file = new FileInfo(filePath);
-				Army army = WarFoundryLoader.GetDefault().LoadArmy(file);
+				Army army = null;
+
+				try
+				{
+					army = WarFoundryLoader.GetDefault().LoadArmy(file);
+				}
+				catch (Exception ex)
+				{
+					logger.Error("Error while loading army file " + filePath, ex);
+				}
 
 				if (army != null)
 				{
@@ -826,9 +834,8 @@
 				}
 				else
 				{
-					logger.ErrorFormat("Failed to load {0} as an army file", filePath);
-					MessageDialog dialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, file.Name + " could not be loaded.\n\nIf the file is an army file then please check your file loaders.");
-					dialog.Title = "Failed to open army";
+					MessageDialog dialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, Translation.GetTranslation("OpenFailed", "File open failed. Please check log file"));
+					dialog.Title = Translation.GetTranslation("OpenFailedTitle", "File open failed");
 					dialog.Run();
 					dialog.Hide();
 					dialog.Dispose();
@@ -856,10 +863,13 @@
 
 		private bool SaveCurrentArmyAs()
 		{
-			FileChooserDialog fileDialog = new FileChooserDialog("Save file as", this, FileChooserAction.Save, "Cancel", ResponseType.Cancel, "Save", ResponseType.Accept);
+			string title = Translation.GetTranslation("saveArmyDialog", "save army");
+			string cancelText = Translation.GetTranslation("bttnCancel", "cancel");
+			string saveText = Translation.GetTranslation("bttnSave", "save");
+			FileChooserDialog fileDialog = new FileChooserDialog(title, this, FileChooserAction.Save, cancelText, ResponseType.Cancel, saveText, ResponseType.Accept);
 			FileFilter filter = new FileFilter();
 			filter.AddPattern("*.army");
-			filter.Name = "WarFoundry Army files (*.army)";
+			filter.Name = Translation.GetTranslation("armyFileFilter", "WarFoundry .army files");
 			fileDialog.AddFilter(filter);
 			int response = fileDialog.Run();
 			string filePath = null;
@@ -881,7 +891,18 @@
 			
 			if (filePath != null)
 			{
-				if (WarFoundrySaver.GetSaver().Save(WarFoundryCore.CurrentArmy, filePath))
+				bool saveSuccess = false;
+
+				try
+				{
+					saveSuccess = WarFoundrySaver.GetSaver().Save(WarFoundryCore.CurrentArmy, filePath);
+				}
+				catch (Exception ex)
+				{
+					logger.Error("Error while saving army file to " + filePath, ex);
+				}
+
+				if (saveSuccess)
 				{
 					miSaveArmy.Sensitive = false;
 					bttnSaveArmy.Sensitive = false;
@@ -891,8 +912,8 @@
 				}
 				else
 				{
-					MessageDialog dialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok, "Failed to save file to " + filePath);
-					dialog.Title = "Army save failed";
+					MessageDialog dialog = new MessageDialog(this, DialogFlags.Modal, MessageType.Error, ButtonsType.Ok,  Translation.GetTranslation("SaveFailed", "File save failed. Please check log file"));
+					dialog.Title = Translation.GetTranslation("SaveFailedTitle", "File save failed");
 					dialog.Run();
 					dialog.Hide();
 					dialog.Dispose();
@@ -911,8 +932,14 @@
 
 				if (CommandStack.IsDirty())
 				{
-					MessageDialog dia = new MessageDialog(this, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.YesNo, "The army \"" + WarFoundryCore.CurrentArmy.Name + "\" has been modified.\r\nSave changes before closing army?");
-					dia.AddButton("Cancel", ResponseType.Cancel);
+					string message = Translation.GetTranslation("SaveChangesQuestion", "Save changes to army before closing?", WarFoundryCore.CurrentArmy.Name);
+					MessageDialog dia = new MessageDialog(this, DialogFlags.DestroyWithParent, MessageType.Question, ButtonsType.None, message);
+					dia.AddButton(Translation.GetTranslation("bttnDiscard", "lose changes"), ResponseType.No);
+					Button button = (Button)dia.AddButton(Translation.GetTranslation("bttnCancel", "cancel"), ResponseType.Cancel);
+					button.Image = new Image("gtk-cancel", IconSize.Button);
+					button = (Button)dia.AddButton(Translation.GetTranslation("bttnSave", "save"), ResponseType.Yes);
+					button.Image = new Image("gtk-save", IconSize.Button);
+					dia.Title = Translation.GetTranslation("SaveChangesTitle", "Save changes?");
 					ResponseType dr = (ResponseType)dia.Run();
 					dia.Hide();
 					dia.Dispose();
--- a/UIControl/AbstractBaseEquipmentUIControl.cs	Sun Jan 02 15:50:29 2011 +0000
+++ b/UIControl/AbstractBaseEquipmentUIControl.cs	Sun Jan 02 21:03:15 2011 +0000
@@ -21,7 +21,7 @@
 		protected int minNumber, maxNumber;
 		protected bool isRatioAmount;
 		protected double equipmentAmount;
-		
+
 		public AbstractBaseEquipmentUIControl(Unit unit, CommandStack commandStack)
 		{
 			this.unit = unit;
@@ -56,12 +56,12 @@
 		{
 			//Do nothing
 		}
-			
+
 		protected void HandleUnitEquipmentAmountChanged()
 		{
 			SetUnitEquipmentValuesFromUI();
 		}
-		
+
 		protected void SetUnitEquipmentLimits(UnitEquipmentItem equip)
 		{			
 			ui.IgnoreWidgets();
@@ -90,7 +90,7 @@
 			
 			ui.ListenToWidgets();
 		}
-		
+
 		protected void SetUnitEquipmentValuesFromEquipment(UnitEquipmentItem equip)
 		{			
 			isRatioAmount = UnitEquipmentUtil.GetEquipmentAmountIsRatio(unit, equip);
@@ -119,7 +119,7 @@
 			
 			SetUnitEquipmentValues();
 		}
-		
+
 		private void SetUnitEquipmentValues()
 		{			
 			ui.IgnoreWidgets();
@@ -144,7 +144,7 @@
 			{
 				string percentageTooLarge = Translation.GetTranslation("equipPercentageTooLarge", "the current percentage ({0}%) was larger than the maximum for the equipment item ({1}%) - the maximum value will be used instead", equipAmount, maxPercentage);
 				string percentageTooLargeTitle = Translation.GetTranslation("equipPercentageTooLargeTitle", "equipment percentage too large");
-				//				MessageBox.Show(ParentForm, percentageTooLarge, percentageTooLargeTitle);
+				ShowMessage(percentageTooLarge, percentageTooLargeTitle);
 				equipAmount = maxPercentage;
 			}
 			else
@@ -153,7 +153,7 @@
 				{
 					string percentageTooSmall = Translation.GetTranslation("equipPercentageTooSmall", "the current percentage ({0}%) was smaller than the minimum for the equipment item ({1}%) - the minimum value will be used instead", equipAmount, minPercentage);
 					string percentageTooSmallTitle = Translation.GetTranslation("equipPercentageTooSmallTitle", "equipment percentage too small");
-				//				MessageBox.Show(ParentForm, percentageTooSmall, percentageTooSmallTitle);
+					ShowMessage(percentageTooSmall, percentageTooSmallTitle);
 					equipAmount = minPercentage;
 				}
 
@@ -168,13 +168,22 @@
 			return Math.Min(Math.Max(calcedAmount, minNumber), maxNumber);
 		}
 
+		private void ShowMessage(string message, string title)
+		{
+			Gtk.MessageDialog dialog = new Gtk.MessageDialog(null, Gtk.DialogFlags.Modal, Gtk.MessageType.Warning, Gtk.ButtonsType.Ok, false, message);
+			dialog.Title = title;
+			dialog.Run();
+			dialog.Hide();
+			dialog.Dispose();
+		}
+
 		private void SetEquipmentAmountsFromNumber(int equipAmount)
 		{
 			if (equipAmount > maxNumber)
 			{
 				string amountTooLarge = Translation.GetTranslation("equipNumberTooLarge", "the current amount ({0}) was larger than the maximum for the equipment item ({1}) - the maximum value will be used instead", equipAmount, maxNumber);
 				string amountTooLargeTitle = Translation.GetTranslation("equipNumberTooLargeTitle", "equipment amount too large");
-				//MessageBox.Show(ParentForm, amountTooLarge, amountTooLargeTitle);
+				ShowMessage(amountTooLarge, amountTooLargeTitle);
 				equipAmount = maxNumber;
 			}
 			else
@@ -183,7 +192,7 @@
 				{
 					string amountTooSmall = Translation.GetTranslation("equipNumberTooSmall", "the current amount ({0}) was smaller than the minimum for the equipment item ({1}) - the minimum value will be used instead", equipAmount, minNumber);
 					string amountTooSmallTitle = Translation.GetTranslation("equipNumberTooSmallTitle", "equipment amount too small");
-				//MessageBox.Show(ParentForm, amountTooSmall, amountTooSmallTitle);
+					ShowMessage(amountTooSmall, amountTooSmallTitle);
 					equipAmount = minNumber;
 				}
 
@@ -221,7 +230,7 @@
 			int maxNumber = UnitEquipmentUtil.GetMaxEquipmentCount(unit, equip);
 			return Math.Max(0, maxNumber);
 		}
-		
+
 		protected int GetMinNumericLimit(UnitEquipmentItem equip)
 		{
 			int minNumber = UnitEquipmentUtil.GetMinEquipmentCount(unit, equip);
@@ -248,7 +257,7 @@
 		{
 			return Math.Round(percent, 1);
 		}
-		
+
 		public void Show()
 		{			
 			SetupUI();
--- a/gtk-gui/IBBoard.WarFoundry.GUI.GTK.FrmAddEquipment.cs	Sun Jan 02 15:50:29 2011 +0000
+++ b/gtk-gui/IBBoard.WarFoundry.GUI.GTK.FrmAddEquipment.cs	Sun Jan 02 21:03:15 2011 +0000
@@ -120,6 +120,7 @@
 			this.rbEquipAll = new global::Gtk.RadioButton("");
 			this.rbEquipAll.CanFocus = true;
 			this.rbEquipAll.Name = "rbEquipAll";
+			this.rbEquipAll.Active = true;
 			this.rbEquipAll.DrawIndicator = true;
 			this.rbEquipAll.UseUnderline = true;
 			this.rbEquipAll.Group = new global::GLib.SList(global::System.IntPtr.Zero);
--- a/gtk-gui/gui.stetic	Sun Jan 02 15:50:29 2011 +0000
+++ b/gtk-gui/gui.stetic	Sun Jan 02 21:03:15 2011 +0000
@@ -1189,6 +1189,7 @@
                         <property name="MemberName" />
                         <property name="CanFocus">True</property>
                         <property name="Label" translatable="yes" />
+                        <property name="Active">True</property>
                         <property name="DrawIndicator">True</property>
                         <property name="HasLabel">True</property>
                         <property name="UseUnderline">True</property>
@@ -1835,7 +1836,6 @@
                         <property name="MemberName" />
                         <property name="CanFocus">True</property>
                         <property name="Label" translatable="yes" />
-                        <property name="Active">True</property>
                         <property name="DrawIndicator">True</property>
                         <property name="HasLabel">True</property>
                         <property name="UseUnderline">True</property>
--- a/translations/en.translation	Sun Jan 02 15:50:29 2011 +0000
+++ b/translations/en.translation	Sun Jan 02 21:03:15 2011 +0000
@@ -1,8 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
-<translations xmlns="http://ibboard.co.uk/translation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" lang="en">
+<translations xmlns="http://ibboard.co.uk/translation" lang="en">
+<!-- Common -->
+<translation id="bttnCancel">Cancel</translation>
+<translation id="bttnOkay">OK</translation>
+<translation id="bttnClose">Close</translation>
+<translation id="bttnCreate">Create</translation>
+<!-- Main Window -->
+<translation id="statusPanelPoints">{0} pts / {1} pts</translation>
+<!-- Main Window / Menus -->
 <translation id="menuFile">_File</translation>
 <translation id="menuEdit">_Edit</translation>
 <translation id="menuHelp">_Help</translation>
+<!-- Main Window / Menus / File Menu -->
 <translation id="miNewArmy">Create _new army</translation>
 <translation id="miOpenArmy">_Open army</translation>
 <translation id="miSaveArmy">_Save army</translation>
@@ -12,25 +21,40 @@
 <translation id="miCloseArmy">_Close army</translation>
 <translation id="miReloadFiles">_Reload files</translation>
 <translation id="miExit">_Quit</translation>
+<!-- Main Window / Menus / Edit Menu -->
 <translation id="miUndo">_Undo</translation>
 <translation id="miRedo">_Redo</translation>
 <translation id="miPreferences">_Preferences</translation>
+<!-- Main Window / Menus / Help Menu -->
 <translation id="miAbout">_About</translation>
+<!-- Main Window / Toolbar buttons -->
 <translation id="bttnNewArmy">Create new army</translation>
 <translation id="bttnOpenArmy">Open army</translation>
 <translation id="bttnSaveArmy">Save army</translation>
 <translation id="bttnUndo">Undo</translation>
 <translation id="bttnRedo">Redo</translation>
 <translation id="bttnCreateFromCat">Add unit from {0}</translation>
+<!-- Main Window / Army Tree -->
 <translation id="armyCategoryColumnTitle">Army Categories</translation>
 <translation id="menuRemoveUnit">Remove Unit</translation>
+<!-- Main Window / Dialogs -->
 <translation id="armyFileFilter">WarFoundry Army Files (*.army)</translation>
-<translation id="bttnCancel">Cancel</translation>
-<translation id="bttnOkay">OK</translation>
-<translation id="bttnSelectSystem">Select system</translation>
+<!-- Main Window / Dialogs / Open -->
+<translation id="openArmyDialog">Open army</translation>
+<translation id="bttnOpen">Open</translation>
+<translation id="OpenFailed">WarFoundry could not open the specified file. Please check the log for more information.</translation>
+<translation id="OpenFailedTitle">File load failed</translation>
+<!-- Main Window / Dialogs / Save -->
 <translation id="saveArmyDialog">Save army</translation>
-<translation id="defaultUnitName">Unit of {0} {1}</translation>
-<translation id="statusPanelPoints">{0} pts / {1} pts</translation>
+<translation id="bttnSave">Save</translation>
+<translation id="SaveFailed">WarFoundry was unable to save the file. Please check the log for more details</translation>
+<translation id="SaveFailedTitle">File save failed</translation>
+<!-- Main Window / Dialogs / Save changes -->
+<translation id="SaveChangesQuestion">The army "{0}" has been modified.
+Save changes before closing army?</translation>
+<translation id="SaveChangesTitle">Unsaved changes</translation>
+<translation id="bttnDiscard">Close without saving</translation>
+<!-- UnitDisplayForm -->
 <translation id="bttnAddWeapon">Add</translation>
 <translation id="bttnEditWeapon">Edit</translation>
 <translation id="bttnRemoveWeapon">Remove</translation>
@@ -38,13 +62,18 @@
 <translation id="lblEquip">Equipment:</translation>
 <translation id="lblAbilities">Abilities:</translation>
 <translation id="lblNotes">Notes:</translation>
+<!-- New Army form -->
 <translation id="IBBoard.WarFoundry.GUI.GTK.FrmNewArmy">Create Army</translation>
 <translation id="lblGameSystem">Game systems:</translation>
 <translation id="lblRaceList">Races:</translation>
 <translation id="lblArmyName">Army name:</translation>
 <translation id="lblArmySize">Army size:</translation>
-<translation id="bttnCreate">Create</translation>
 <translation id="frmNewArmyRaceColumn">Race</translation>
+<!-- New Unit form -->
+<translation id="IBBoard.WarFoundry.GUI.GTK.FrmNewUnit">Add New {0} Choice</translation>
+<translation id="frmNewUnitNewUnitColumn">Unit Type</translation>
+<translation id="lblUnitList">Unit Type:</translation>
+<!-- Equipment Dialogs (Common) -->
 <translation id="equipPercentageTooLarge">The current percentage ({0}%) was larger than the maximum for the equipment item ({1}%). The maximum value will be used instead.</translation>
 <translation id="equipPercentageTooLargeTitle">Equipment percentage too large</translation>
 <translation id="equipPercentageTooSmall">The current percentage ({0}%) was smaller than the minimum for the equipment item ({1}%). The minimum value will be used instead.</translation>
@@ -53,35 +82,38 @@
 <translation id="equipNumberTooLargeTitle">Equipment amount too large</translation>
 <translation id="equipNumberTooSmall">The current amount ({0}) was smaller than the minimum for the equipment item ({1}). The minimum value will be used instead.</translation>
 <translation id="equipNumberTooSmallTitle">Equipment amount too small</translation>
-<translation id="IBBoard.WarFoundry.GUI.GTK.FrmNewUnit">Add New {0} Choice</translation>
-<translation id="frmNewUnitNewUnitColumn">Unit Type</translation>
-<translation id="lblUnitList">Unit Type:</translation>
-<translation id="IBBoard.WarFoundry.GUI.GTK.FrmAddEquipment">Add Equipment</translation>
-<translation id="frmAddEquipmentColumnTitle">Equipment</translation>
 <translation id="lblEquipAll">Equip All</translation>
 <translation id="lblPercent">%</translation>
 <translation id="lblAmount">Amount:</translation>
-<translation id="lblEquipment">Equipment:</translation>
+<translation id="lblItem">Equipment:</translation>
+<!-- Equipment Dialogs / Add -->
+<translation id="IBBoard.WarFoundry.GUI.GTK.FrmAddEquipment">Add Equipment</translation>
+<translation id="frmAddEquipmentColumnTitle">Equipment</translation>
+<!-- Equipment Dialogs / Edit -->
 <translation id="IBBoard.WarFoundry.GUI.GTK.FrmEditEquipment">Edit Equipment</translation>
 <translation id="frmEditEquipmentColumnTitle">Equipment</translation>
+<!-- Equipment Dialogs / Replace -->
 <translation id="IBBoard.WarFoundry.GUI.GTK.FrmReplaceEquipment">Replace Equipment</translation>
+<!-- Preferences -->
+<translation id="IBBoard.WarFoundry.GUI.GTK.FrmPreferences">Preferences</translation>
+<translation id="languagePrefSection">Language</translation>
+<translation id="lblLanguage">Language:</translation>
+<translation id="languagesGroup">Language</translation>
+<!-- About dialog -->
 <translation id="IBBoard.WarFoundry.GUI.GTK.FrmAbout">About WarFoundry</translation>
-<translation id="bttnClose">Close</translation>
-<translation id="bttnCredits">Credits</translation>
 <translation id="lblWarFoundryCopyright">© 2007-2010, IBBoard and others</translation>
 <translation id="lblWarFoundryDesc">WarFoundry is an open-source army creation tool that lets you create rosters for multiple game systems.</translation>
+<translation id="bttnCredits">Credits</translation>
+<!-- About dialog / credits -->
+<translation id="IBBoard.WarFoundry.GUI.GTK.FrmAboutCredits">Credits</translation>
+<translation id="lblDevelopers">Developers:</translation>	
+<translation id="lblTestersCommon">Testers (General WarFoundry):</translation>
+<translation id="lblTestersGtk">Testers (GTK UI):</translation>
+<!-- Export / HTML -->
 <translation id="exportBasicHtmlDialogTitle">Export army</translation>
 <translation id="exportBasicHtmlCancel">Cancel</translation>
 <translation id="exportBasicHtmlExport">Export</translation>
 <translation id="exportBasicHtmlHtmlFilter">HTML pages (*.html)</translation>
-<translation id="IBBoard.WarFoundry.GUI.GTK.FrmAboutCredits">Credits</translation>
-<translation id="lblDevelopers">Developers:</translation>	
-<translation id="lblTestersCommon">Testers (General WarFoundry):</translation>
-<translation id="lblTestersGtk">Testers (GTK UI):</translation>
-<translation id="IBBoard.WarFoundry.GUI.GTK.FrmPreferences">Preferences</translation>
-<translation id="languagePrefSection">Language</translation>
-<translation id="lblLanguage">Language:</translation>
-<translation id="languagesGroup">Language</translation>
 <translation id="armyHtmlOutputBodyHeader">{0} - {1}pts</translation>
 <translation id="armyHtmlOutputTableHeaderUnitName">Name</translation>
 <translation id="armyHtmlOutputTableHeaderUnitNotes">Notes</translation>
@@ -90,9 +122,8 @@
 <translation id="armyHtmlExportEquipAmountPercentage">{0}% ({1})</translation>
 <translation id="armyHtmlExportEquipAmountNumber">{0}</translation>
 <translation id="armyHtmlExportEquipAmountRatio">{0} for {1}</translation>
-<translation id="equipmentAmountAll">all ({1})</translation>
-<translation id="equipmentAmountPercentage">{0}% ({1})</translation>
-<translation id="equipmentAmountNumber">{0}</translation>
+<!-- API -->
+<translation id="defaultUnitName">Unit of {0} {1}</translation>
 <translation id="setEquipmentAmountCommandDescription">Set {0} amount for {1} to {2}</translation>
 <translation id="setEquipmentAmountCommandUndoDescription">Set {0} amount for {1} to {2}</translation>
 <translation id="replaceUnitEquipmentCommandDescription">Replace {0} with {1} for {2}</translation>
@@ -105,4 +136,7 @@
 <translation id="setUnitNameCommandUndoDescription">Rename "{0}" to "{1}"</translation>
 <translation id="setUnitSizeCommandDescription">Set size of {0} to {1}</translation>
 <translation id="setUnitSizeCommandUndoDescription">Set size of {0} to {1}</translation>
+<translation id="equipmentAmountAll">all ({1})</translation>
+<translation id="equipmentAmountPercentage">{0}% ({1})</translation>
+<translation id="equipmentAmountNumber">{0}</translation>
 </translations>
\ No newline at end of file
--- a/translations/fr.translation	Sun Jan 02 15:50:29 2011 +0000
+++ b/translations/fr.translation	Sun Jan 02 21:03:15 2011 +0000
@@ -127,4 +127,8 @@
 <translation id="bttnCreate">Créer</translation>
 <translation id="frmAddEquipmentColumnTitle">Équipement</translation>
 <translation id="lblPercent">%</translation>
+<translation id="bttnOpen">_Ouvrir</translation>
+<translation id="OpenFailed">WarFoundry ne peut pas ouvrir le fichier. Veillez vérifier le log pour plus d'informations</translation>
+<translation id="OpenFailedTitle">Échec de la ouvrir du fichier</translation>
+<translation id="bttnSave">Sauvegarder</translation>
 </translations>