diff options
5 files changed, 487 insertions, 479 deletions
diff --git a/main/po/Makefile.am b/main/po/Makefile.am index 0b44e025eb..14d6750416 100644 --- a/main/po/Makefile.am +++ b/main/po/Makefile.am @@ -11,7 +11,7 @@ MO_FILES = $(foreach po,$(FILES), $(INSTALL_DIR)/$(basename $(po))/LC_MESSAGES/$ all: $(GMO_FILES) post-strip-mnemonics update-po: - $(MDTOOL_RUN) gettext-update -f:$(top_srcdir)/Main.sln + $(MDTOOL_RUN) gettext-update --sort -f:$(top_srcdir)/Main.sln $(GMO_FILES): $(LC_BUILD)/%/LC_MESSAGES/$(PACKAGE).mo: %.po strip-mnemonics $(MKDIR_P) $(dir $@) diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs index 04f0d6d85f..74a5a2c965 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationNodeBuilder.cs @@ -131,7 +131,7 @@ namespace MonoDevelop.Gettext.NodeBuilders void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project, Translation translation) { try { - project.UpdateTranslations (monitor, translation); + project.UpdateTranslations (monitor, false, translation); Gtk.Application.Invoke ((o, args) => { POEditorWidget.ReloadWidgets (); }); diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs index e6cc4c2e18..01e255d42a 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext.NodeBuilders/TranslationProjectNodeBuilder.cs @@ -162,7 +162,7 @@ namespace MonoDevelop.Gettext.NodeBuilders void UpdateTranslationsAsync (ProgressMonitor monitor, TranslationProject project) { try { - project.UpdateTranslations (monitor); + project.UpdateTranslations (monitor, false); Gtk.Application.Invoke ((o, args) => { POEditorWidget.ReloadWidgets (); }); diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs index 5be0513971..6baf226108 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/GettextTool.cs @@ -41,6 +41,7 @@ namespace MonoDevelop.Gettext bool help; string file; string project; + bool sort; public async Task<int> Run (string[] arguments) { @@ -54,6 +55,7 @@ namespace MonoDevelop.Gettext Console.WriteLine ("gettext-update [options] [project-file]"); Console.WriteLine ("--f --file:FILE Project or solution file to build."); Console.WriteLine ("--p --project:PROJECT Name of the project to build."); + Console.WriteLine ("--sort Sorts the output po file"); Console.WriteLine (); return 0; } @@ -99,11 +101,11 @@ namespace MonoDevelop.Gettext Console.WriteLine ("The project '" + item.FileName + "' is not a translation project"); return 1; } - tp.UpdateTranslations (monitor); + tp.UpdateTranslations (monitor, sort); } else { foreach (TranslationProject p in solution.GetAllItems <TranslationProject>()) - p.UpdateTranslations (monitor); + p.UpdateTranslations (monitor, sort); } return 0; @@ -151,6 +153,10 @@ namespace MonoDevelop.Gettext project = value; break; + case "sort": + sort = true; + break; + default: throw new Exception("Unknown option '" + option + "'"); } diff --git a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs index 14e4396528..4cfaf6d88c 100644 --- a/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs +++ b/main/src/addins/MonoDevelop.Gettext/MonoDevelop.Gettext/TranslationProject.cs @@ -1,475 +1,477 @@ -// -// TranslationProject.cs -// -// Author: -// Mike Krüger <mkrueger@novell.com> -// -// Copyright (C) 2007 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.IO; -using System.Xml; - -using MonoDevelop.Core; -using MonoDevelop.Projects; -using MonoDevelop.Core.Serialization; -using MonoDevelop.Deployment; -using MonoDevelop.Ide; -using MonoDevelop.Core.Execution; -using System.Linq; -using System.Threading.Tasks; - -namespace MonoDevelop.Gettext -{ - class TranslationProject : Project, IDeployable - { - [ItemProperty("packageName")] - string packageName = null; - - [ItemProperty("outputType")] - TranslationOutputType outputType; - - [ItemProperty(Name = "relPath", DefaultValue = "")] - string relPath = String.Empty; - - bool isDirty; - - public string PackageName { - get { return packageName; } - set { packageName = value; } - } - - public string RelPath { - get { return relPath; } - set { relPath = value; } - } - - public TranslationOutputType OutputType { - get { return outputType; } - set { outputType = value; } - } - - TranslationCollection translations; - - [ItemProperty] - List<TranslationProjectInformation> projectInformations = new List<TranslationProjectInformation> (); - - [ItemProperty ("translations")] - public TranslationCollection Translations { - get { return translations; } - } - - public ReadOnlyCollection<TranslationProjectInformation> TranslationProjectInformations { - get { return projectInformations.AsReadOnly (); } - } - - public TranslationProject () - { - Initialize (this); - translations = new TranslationCollection (this); - } - - protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles) +//
+// TranslationProject.cs
+//
+// Author:
+// Mike Krüger <mkrueger@novell.com>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.IO;
+using System.Xml;
+
+using MonoDevelop.Core;
+using MonoDevelop.Projects;
+using MonoDevelop.Core.Serialization;
+using MonoDevelop.Deployment;
+using MonoDevelop.Ide;
+using MonoDevelop.Core.Execution;
+using System.Linq;
+using System.Threading.Tasks;
+
+namespace MonoDevelop.Gettext
+{
+ class TranslationProject : Project, IDeployable
+ {
+ [ItemProperty("packageName")]
+ string packageName = null;
+
+ [ItemProperty("outputType")]
+ TranslationOutputType outputType;
+
+ [ItemProperty(Name = "relPath", DefaultValue = "")]
+ string relPath = String.Empty;
+
+ bool isDirty;
+
+ public string PackageName {
+ get { return packageName; }
+ set { packageName = value; }
+ }
+
+ public string RelPath {
+ get { return relPath; }
+ set { relPath = value; }
+ }
+
+ public TranslationOutputType OutputType {
+ get { return outputType; }
+ set { outputType = value; }
+ }
+
+ TranslationCollection translations;
+
+ [ItemProperty]
+ List<TranslationProjectInformation> projectInformations = new List<TranslationProjectInformation> ();
+
+ [ItemProperty ("translations")]
+ public TranslationCollection Translations {
+ get { return translations; }
+ }
+
+ public ReadOnlyCollection<TranslationProjectInformation> TranslationProjectInformations {
+ get { return projectInformations.AsReadOnly (); }
+ }
+
+ public TranslationProject ()
{
- List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles).ToList(); - if (includeReferencedFiles) { - foreach (Translation tr in translations) - col.Add (tr.PoFile); - } - return col; - } - - public TranslationProjectInformation GetProjectInformation (SolutionFolderItem entry, bool force) - { - foreach (TranslationProjectInformation info in this.projectInformations) { - if (info.ProjectName == entry.Name) - return info; - } - if (force) { - TranslationProjectInformation newInfo = new TranslationProjectInformation (entry.Name); - this.projectInformations.Add (newInfo); - return newInfo; - } - return null; - } - - public bool IsIncluded (SolutionFolderItem entry) - { - TranslationProjectInformation info = GetProjectInformation (entry, false); - if (info != null) - return info.IsIncluded; - return true; - } - - protected override void OnInitializeFromTemplate (ProjectCreateInformation projectCreateInfo, XmlElement template) - { - //NOTE: we don't really need multiple configurations for this project type, since nothing actually uses them - //but it makes the solution configuration mapping look more consistent - //Perhaps in future there will be some per-config settings - foreach (string config in new [] { "Debug", "Release"}) - Configurations.Add (new TranslationProjectConfiguration (config)); - - OutputType = (TranslationOutputType)Enum.Parse (typeof(TranslationOutputType), template.GetAttribute ("outputType")); - PackageName = template.GetAttribute ("packageName"); - RelPath = template.GetAttribute ("relPath"); - } - - string GetFileName (string isoCode) - { - return Path.Combine (base.BaseDirectory, isoCode + ".po"); - } - - public class MatchLocation - { - string originalString; - string originalPluralString; - int line; - - public string OriginalString { - get { return originalString; } - } - - public string OriginalPluralString { - get { return originalPluralString; } - } - - public int Line { - get { return line; } - } - - public MatchLocation (string originalString, string originalPluralString, int line) - { - this.originalString = originalString; - this.originalPluralString = originalPluralString; - this.line = line; - } - - public MatchLocation (string originalString, int line) : this (originalString, null, line) - { - } - } - - - public Translation AddNewTranslation (string isoCode, ProgressMonitor monitor) - { - try { - Translation tr = new Translation (this, isoCode); - translations.Add (tr); - string templateFile = Path.Combine (this.BaseDirectory, "messages.po"); - string translationFile = GetFileName (isoCode); - if (!File.Exists (templateFile)) - CreateDefaultCatalog (monitor); - File.Copy (templateFile, translationFile); - - monitor.ReportSuccess (String.Format (GettextCatalog.GetString ("Language '{0}' successfully added."), isoCode)); - monitor.Step (1); - SaveAsync (monitor); - return tr; - } catch (Exception e) { - monitor.ReportError (String.Format ( GettextCatalog.GetString ("Language '{0}' could not be added: "), isoCode), e); - return null; - } finally { - monitor.EndTask (); - } - } - - public Translation GetTranslation (string isoCode) - { - foreach (Translation translation in this.translations) { - if (translation.IsoCode == isoCode) - return translation; - } - return null; - } - - public void RemoveTranslation (string isoCode) - { - Translation translation = GetTranslation (isoCode); - if (translation != null) - this.translations.Remove (translation); - } - - internal void NotifyTranslationAdded (Translation tr) - { - if (!Loading) - isDirty = true; - OnTranslationAdded (EventArgs.Empty); - } - - internal void NotifyTranslationRemoved (Translation tr) - { - isDirty = true; - OnTranslationRemoved (EventArgs.Empty); - } - - protected override SolutionItemConfiguration OnCreateConfiguration (string name, ConfigurationKind kind) - { - return new TranslationProjectConfiguration (name); - } - - internal string GetOutputDirectory (ConfigurationSelector configuration) - { - if (this.ParentSolution.StartupItem == null) - return BaseDirectory; - if (this.ParentSolution.StartupItem is DotNetProject) { - return Path.Combine (Path.GetDirectoryName (((DotNetProject)ParentSolution.StartupItem).GetOutputFileName (configuration)), RelPath); - } - return Path.Combine (this.ParentSolution.StartupItem.BaseDirectory, RelPath); - } - - void CreateDefaultCatalog (ProgressMonitor monitor) - { - IFileScanner[] scanners = TranslationService.GetFileScanners (); - - Catalog catalog = new Catalog (this); - List<Project> projects = new List<Project> (); - foreach (Project p in ParentSolution.GetAllProjects ()) { - if (IsIncluded (p)) - projects.Add (p); - } - foreach (Project p in projects) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Scanning project {0}...", p.Name)); - foreach (ProjectFile file in p.Files) { - if (!File.Exists (file.FilePath)) - continue; - if (file.Subtype == Subtype.Code) { - string mimeType = DesktopService.GetMimeTypeForUri (file.FilePath); - foreach (IFileScanner fs in scanners) { - if (fs.CanScan (this, catalog, file.FilePath, mimeType)) - fs.UpdateCatalog (this, catalog, monitor, file.FilePath); - } - } - } - if (monitor.CancellationToken.IsCancellationRequested) - return; - monitor.Step (1); - } - catalog.Save (Path.Combine (this.BaseDirectory, "messages.po")); - } - - public void UpdateTranslations (ProgressMonitor monitor) - { - UpdateTranslations (monitor, translations.ToArray ()); - } - - public void UpdateTranslations (ProgressMonitor monitor, params Translation[] translations) - { - monitor.BeginTask (null, Translations.Count + 1); - - try { - List<Project> projects = new List<Project> (); - foreach (Project p in ParentSolution.GetAllProjects ()) { - if (IsIncluded (p)) - projects.Add (p); - } - monitor.BeginTask (GettextCatalog.GetString ("Updating message catalog"), projects.Count); - CreateDefaultCatalog (monitor); - monitor.Log.WriteLine (GettextCatalog.GetString ("Done")); - } finally { - monitor.EndTask (); - monitor.Step (1); - } - if (monitor.CancellationToken.IsCancellationRequested) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled.")); - return; - } - - Dictionary<string, bool> isIncluded = new Dictionary<string, bool> (); - foreach (Translation translation in translations) { - isIncluded[translation.IsoCode] = true; - } - foreach (Translation translation in this.Translations) { - if (!isIncluded.ContainsKey (translation.IsoCode)) - continue; - string poFileName = translation.PoFile; - monitor.BeginTask (GettextCatalog.GetString ("Updating {0}", translation.PoFile), 1); - try { - var pb = new ProcessArgumentBuilder (); - pb.Add ("-U"); - pb.AddQuoted (poFileName); - pb.Add ("-v"); - pb.AddQuoted (this.BaseDirectory.Combine ("messages.po")); - - var process = Runtime.ProcessService.StartProcess (Translation.GetTool ("msgmerge"), - pb.ToString (), this.BaseDirectory, monitor.Log, monitor.Log, null); - process.WaitForOutput (); - } - catch (System.ComponentModel.Win32Exception) { - var msg = GettextCatalog.GetString ("Did not find msgmerge. Please ensure that gettext tools are installed."); - monitor.ReportError (msg, null); - } - catch (Exception ex) { - monitor.ReportError (GettextCatalog.GetString ("Could not update file {0}", translation.PoFile), ex); - } - finally { - monitor.EndTask (); - monitor.Step (1); - } - if (monitor.CancellationToken.IsCancellationRequested) { - monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled.")); - return; - } - } - } - public void RemoveEntry (string msgstr) - { - foreach (Translation translation in this.Translations) { - string poFileName = translation.PoFile; - Catalog catalog = new Catalog (this); - catalog.Load (new MonoDevelop.Core.ProgressMonitor (), poFileName); - CatalogEntry entry = catalog.FindItem (msgstr); - if (entry != null) { - catalog.RemoveItem (entry); - catalog.Save (poFileName); - } - } - } - - protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration, OperationContext operationContext) - { - var toBuild = Translations.Where (t => t.NeedsBuilding(configuration)).ToArray (); - BuildResult results = new BuildResult ("", 1, 0); - string outputDirectory = GetOutputDirectory (configuration); - if (!string.IsNullOrEmpty (outputDirectory)) { - await Task.Run (delegate { - foreach (Translation translation in toBuild) { - if (translation.NeedsBuilding (configuration)) { - BuildResult res = translation.Build (monitor, configuration); - results.Append (res); - } - } - isDirty = false; - }); - } - return results; - } - - protected async override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration, OperationContext operationContext) - { - isDirty = true; - monitor.Log.WriteLine (GettextCatalog.GetString ("Removing all .mo files.")); - string outputDirectory = GetOutputDirectory (configuration); - if (string.IsNullOrEmpty (outputDirectory)) - return BuildResult.CreateSuccess (); - - var toClean = Translations.Select (t => t.GetOutFile (configuration)).ToArray (); - await Task.Run (delegate { - foreach (string moFileName in toClean) { - if (File.Exists (moFileName)) - File.Delete (moFileName); - } - }); - return BuildResult.CreateSuccess (); - } - -#region Deployment - public DeployFileCollection GetDeployFiles (ConfigurationSelector configuration) - { - DeployFileCollection result = new DeployFileCollection (); - foreach (Translation translation in this.Translations) { - if (OutputType == TranslationOutputType.SystemPath) { - string moDirectory = Path.Combine ("locale", translation.IsoCode); - moDirectory = Path.Combine (moDirectory, "LC_MESSAGES"); - string moFileName = Path.Combine (moDirectory, PackageName + ".mo"); - result.Add (new DeployFile (this, translation.GetOutFile (configuration), moFileName, TargetDirectory.CommonApplicationDataRoot)); - } else { - string moDirectory = Path.Combine (RelPath, translation.IsoCode); - moDirectory = Path.Combine (moDirectory, "LC_MESSAGES"); - string moFileName = Path.Combine (moDirectory, PackageName + ".mo"); - result.Add (new DeployFile (this, translation.GetOutFile (configuration), moFileName, TargetDirectory.ProgramFiles)); - } - } - return result; - } -#endregion - - protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration) - { - if (isDirty) - return true; - foreach (Translation translation in this.Translations) { - if (translation.NeedsBuilding (configuration)) - return true; - } - return false; - } - - protected virtual void OnTranslationAdded (EventArgs e) - { - if (TranslationAdded != null) - TranslationAdded (this, e); - } - - public event EventHandler TranslationAdded; - - protected virtual void OnTranslationRemoved (EventArgs e) - { - if (TranslationRemoved != null) - TranslationRemoved (this, e); - } - - public event EventHandler TranslationRemoved; - } - - enum TranslationOutputType { - RelativeToOutput, - SystemPath - } - - class TranslationProjectConfiguration : ProjectConfiguration - { - public TranslationProjectConfiguration (string id): base (id) - { - } - } - - class TranslationProjectInformation - { - [ItemProperty] - string projectName; - - [ItemProperty] - bool isIncluded; - - public string ProjectName { - get { return projectName; } - set { projectName = value; } - } - - public bool IsIncluded { - get { return isIncluded; } - set { isIncluded = value; } - } - - public TranslationProjectInformation () - { - } - - public TranslationProjectInformation (string projectName) - { - this.projectName = projectName; - } - } -} + Initialize (this);
+ translations = new TranslationCollection (this);
+ }
+
+ protected override IEnumerable<FilePath> OnGetItemFiles (bool includeReferencedFiles)
+ {
+ List<FilePath> col = base.OnGetItemFiles (includeReferencedFiles).ToList();
+ if (includeReferencedFiles) {
+ foreach (Translation tr in translations)
+ col.Add (tr.PoFile);
+ }
+ return col;
+ }
+
+ public TranslationProjectInformation GetProjectInformation (SolutionFolderItem entry, bool force)
+ {
+ foreach (TranslationProjectInformation info in this.projectInformations) {
+ if (info.ProjectName == entry.Name)
+ return info;
+ }
+ if (force) {
+ TranslationProjectInformation newInfo = new TranslationProjectInformation (entry.Name);
+ this.projectInformations.Add (newInfo);
+ return newInfo;
+ }
+ return null;
+ }
+
+ public bool IsIncluded (SolutionFolderItem entry)
+ {
+ TranslationProjectInformation info = GetProjectInformation (entry, false);
+ if (info != null)
+ return info.IsIncluded;
+ return true;
+ }
+
+ protected override void OnInitializeFromTemplate (ProjectCreateInformation projectCreateInfo, XmlElement template)
+ {
+ //NOTE: we don't really need multiple configurations for this project type, since nothing actually uses them
+ //but it makes the solution configuration mapping look more consistent
+ //Perhaps in future there will be some per-config settings
+ foreach (string config in new [] { "Debug", "Release"})
+ Configurations.Add (new TranslationProjectConfiguration (config));
+
+ OutputType = (TranslationOutputType)Enum.Parse (typeof(TranslationOutputType), template.GetAttribute ("outputType"));
+ PackageName = template.GetAttribute ("packageName");
+ RelPath = template.GetAttribute ("relPath");
+ }
+
+ string GetFileName (string isoCode)
+ {
+ return Path.Combine (base.BaseDirectory, isoCode + ".po");
+ }
+
+ public class MatchLocation
+ {
+ string originalString;
+ string originalPluralString;
+ int line;
+
+ public string OriginalString {
+ get { return originalString; }
+ }
+
+ public string OriginalPluralString {
+ get { return originalPluralString; }
+ }
+
+ public int Line {
+ get { return line; }
+ }
+
+ public MatchLocation (string originalString, string originalPluralString, int line)
+ {
+ this.originalString = originalString;
+ this.originalPluralString = originalPluralString;
+ this.line = line;
+ }
+
+ public MatchLocation (string originalString, int line) : this (originalString, null, line)
+ {
+ }
+ }
+
+
+ public Translation AddNewTranslation (string isoCode, ProgressMonitor monitor)
+ {
+ try {
+ Translation tr = new Translation (this, isoCode);
+ translations.Add (tr);
+ string templateFile = Path.Combine (this.BaseDirectory, "messages.po");
+ string translationFile = GetFileName (isoCode);
+ if (!File.Exists (templateFile))
+ CreateDefaultCatalog (monitor);
+ File.Copy (templateFile, translationFile);
+
+ monitor.ReportSuccess (String.Format (GettextCatalog.GetString ("Language '{0}' successfully added."), isoCode));
+ monitor.Step (1);
+ SaveAsync (monitor);
+ return tr;
+ } catch (Exception e) {
+ monitor.ReportError (String.Format ( GettextCatalog.GetString ("Language '{0}' could not be added: "), isoCode), e);
+ return null;
+ } finally {
+ monitor.EndTask ();
+ }
+ }
+
+ public Translation GetTranslation (string isoCode)
+ {
+ foreach (Translation translation in this.translations) {
+ if (translation.IsoCode == isoCode)
+ return translation;
+ }
+ return null;
+ }
+
+ public void RemoveTranslation (string isoCode)
+ {
+ Translation translation = GetTranslation (isoCode);
+ if (translation != null)
+ this.translations.Remove (translation);
+ }
+
+ internal void NotifyTranslationAdded (Translation tr)
+ {
+ if (!Loading)
+ isDirty = true;
+ OnTranslationAdded (EventArgs.Empty);
+ }
+
+ internal void NotifyTranslationRemoved (Translation tr)
+ {
+ isDirty = true;
+ OnTranslationRemoved (EventArgs.Empty);
+ }
+
+ protected override SolutionItemConfiguration OnCreateConfiguration (string name, ConfigurationKind kind)
+ {
+ return new TranslationProjectConfiguration (name);
+ }
+
+ internal string GetOutputDirectory (ConfigurationSelector configuration)
+ {
+ if (this.ParentSolution.StartupItem == null)
+ return BaseDirectory;
+ if (this.ParentSolution.StartupItem is DotNetProject) {
+ return Path.Combine (Path.GetDirectoryName (((DotNetProject)ParentSolution.StartupItem).GetOutputFileName (configuration)), RelPath);
+ }
+ return Path.Combine (this.ParentSolution.StartupItem.BaseDirectory, RelPath);
+ }
+
+ void CreateDefaultCatalog (ProgressMonitor monitor)
+ {
+ IFileScanner[] scanners = TranslationService.GetFileScanners ();
+
+ Catalog catalog = new Catalog (this);
+ List<Project> projects = new List<Project> ();
+ foreach (Project p in ParentSolution.GetAllProjects ()) {
+ if (IsIncluded (p))
+ projects.Add (p);
+ }
+ foreach (Project p in projects) {
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Scanning project {0}...", p.Name));
+ foreach (ProjectFile file in p.Files) {
+ if (!File.Exists (file.FilePath))
+ continue;
+ if (file.Subtype == Subtype.Code) {
+ string mimeType = DesktopService.GetMimeTypeForUri (file.FilePath);
+ foreach (IFileScanner fs in scanners) {
+ if (fs.CanScan (this, catalog, file.FilePath, mimeType))
+ fs.UpdateCatalog (this, catalog, monitor, file.FilePath);
+ }
+ }
+ }
+ if (monitor.CancellationToken.IsCancellationRequested)
+ return;
+ monitor.Step (1);
+ }
+ catalog.Save (Path.Combine (this.BaseDirectory, "messages.po"));
+ }
+
+ public void UpdateTranslations (ProgressMonitor monitor, bool sort)
+ {
+ UpdateTranslations (monitor, sort, translations.ToArray ());
+ }
+
+ public void UpdateTranslations (ProgressMonitor monitor, bool sort, params Translation[] translations)
+ {
+ monitor.BeginTask (null, Translations.Count + 1);
+
+ try {
+ List<Project> projects = new List<Project> ();
+ foreach (Project p in ParentSolution.GetAllProjects ()) {
+ if (IsIncluded (p))
+ projects.Add (p);
+ }
+ monitor.BeginTask (GettextCatalog.GetString ("Updating message catalog"), projects.Count);
+ CreateDefaultCatalog (monitor);
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Done"));
+ } finally {
+ monitor.EndTask ();
+ monitor.Step (1);
+ }
+ if (monitor.CancellationToken.IsCancellationRequested) {
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled."));
+ return;
+ }
+
+ Dictionary<string, bool> isIncluded = new Dictionary<string, bool> ();
+ foreach (Translation translation in translations) {
+ isIncluded[translation.IsoCode] = true;
+ }
+ foreach (Translation translation in this.Translations) {
+ if (!isIncluded.ContainsKey (translation.IsoCode))
+ continue;
+ string poFileName = translation.PoFile;
+ monitor.BeginTask (GettextCatalog.GetString ("Updating {0}", translation.PoFile), 1);
+ try {
+ var pb = new ProcessArgumentBuilder ();
+ pb.Add ("--update");
+ pb.AddQuoted (poFileName);
+ pb.Add ("--verbose");
+ if (sort)
+ pb.Add ("--sort-output");
+ pb.AddQuoted (this.BaseDirectory.Combine ("messages.po"));
+
+ var process = Runtime.ProcessService.StartProcess (Translation.GetTool ("msgmerge"),
+ pb.ToString (), this.BaseDirectory, monitor.Log, monitor.Log, null);
+ process.WaitForOutput ();
+ }
+ catch (System.ComponentModel.Win32Exception) {
+ var msg = GettextCatalog.GetString ("Did not find msgmerge. Please ensure that gettext tools are installed.");
+ monitor.ReportError (msg, null);
+ }
+ catch (Exception ex) {
+ monitor.ReportError (GettextCatalog.GetString ("Could not update file {0}", translation.PoFile), ex);
+ }
+ finally {
+ monitor.EndTask ();
+ monitor.Step (1);
+ }
+ if (monitor.CancellationToken.IsCancellationRequested) {
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Operation cancelled."));
+ return;
+ }
+ }
+ }
+ public void RemoveEntry (string msgstr)
+ {
+ foreach (Translation translation in this.Translations) {
+ string poFileName = translation.PoFile;
+ Catalog catalog = new Catalog (this);
+ catalog.Load (new MonoDevelop.Core.ProgressMonitor (), poFileName);
+ CatalogEntry entry = catalog.FindItem (msgstr);
+ if (entry != null) {
+ catalog.RemoveItem (entry);
+ catalog.Save (poFileName);
+ }
+ }
+ }
+
+ protected async override Task<BuildResult> OnBuild (ProgressMonitor monitor, ConfigurationSelector configuration, OperationContext operationContext)
+ {
+ var toBuild = Translations.Where (t => t.NeedsBuilding(configuration)).ToArray ();
+ BuildResult results = new BuildResult ("", 1, 0);
+ string outputDirectory = GetOutputDirectory (configuration);
+ if (!string.IsNullOrEmpty (outputDirectory)) {
+ await Task.Run (delegate {
+ foreach (Translation translation in toBuild) {
+ if (translation.NeedsBuilding (configuration)) {
+ BuildResult res = translation.Build (monitor, configuration);
+ results.Append (res);
+ }
+ }
+ isDirty = false;
+ });
+ }
+ return results;
+ }
+
+ protected async override Task<BuildResult> OnClean (ProgressMonitor monitor, ConfigurationSelector configuration, OperationContext operationContext)
+ {
+ isDirty = true;
+ monitor.Log.WriteLine (GettextCatalog.GetString ("Removing all .mo files."));
+ string outputDirectory = GetOutputDirectory (configuration);
+ if (string.IsNullOrEmpty (outputDirectory))
+ return BuildResult.CreateSuccess ();
+
+ var toClean = Translations.Select (t => t.GetOutFile (configuration)).ToArray ();
+ await Task.Run (delegate {
+ foreach (string moFileName in toClean) {
+ if (File.Exists (moFileName))
+ File.Delete (moFileName);
+ }
+ });
+ return BuildResult.CreateSuccess ();
+ }
+
+#region Deployment
+ public DeployFileCollection GetDeployFiles (ConfigurationSelector configuration)
+ {
+ DeployFileCollection result = new DeployFileCollection ();
+ foreach (Translation translation in this.Translations) {
+ if (OutputType == TranslationOutputType.SystemPath) {
+ string moDirectory = Path.Combine ("locale", translation.IsoCode);
+ moDirectory = Path.Combine (moDirectory, "LC_MESSAGES");
+ string moFileName = Path.Combine (moDirectory, PackageName + ".mo");
+ result.Add (new DeployFile (this, translation.GetOutFile (configuration), moFileName, TargetDirectory.CommonApplicationDataRoot));
+ } else {
+ string moDirectory = Path.Combine (RelPath, translation.IsoCode);
+ moDirectory = Path.Combine (moDirectory, "LC_MESSAGES");
+ string moFileName = Path.Combine (moDirectory, PackageName + ".mo");
+ result.Add (new DeployFile (this, translation.GetOutFile (configuration), moFileName, TargetDirectory.ProgramFiles));
+ }
+ }
+ return result;
+ }
+#endregion
+
+ protected override bool OnGetNeedsBuilding (ConfigurationSelector configuration)
+ {
+ if (isDirty)
+ return true;
+ foreach (Translation translation in this.Translations) {
+ if (translation.NeedsBuilding (configuration))
+ return true;
+ }
+ return false;
+ }
+
+ protected virtual void OnTranslationAdded (EventArgs e)
+ {
+ if (TranslationAdded != null)
+ TranslationAdded (this, e);
+ }
+
+ public event EventHandler TranslationAdded;
+
+ protected virtual void OnTranslationRemoved (EventArgs e)
+ {
+ if (TranslationRemoved != null)
+ TranslationRemoved (this, e);
+ }
+
+ public event EventHandler TranslationRemoved;
+ }
+
+ enum TranslationOutputType {
+ RelativeToOutput,
+ SystemPath
+ }
+
+ class TranslationProjectConfiguration : ProjectConfiguration
+ {
+ public TranslationProjectConfiguration (string id): base (id)
+ {
+ }
+ }
+
+ class TranslationProjectInformation
+ {
+ [ItemProperty]
+ string projectName;
+
+ [ItemProperty]
+ bool isIncluded;
+
+ public string ProjectName {
+ get { return projectName; }
+ set { projectName = value; }
+ }
+
+ public bool IsIncluded {
+ get { return isIncluded; }
+ set { isIncluded = value; }
+ }
+
+ public TranslationProjectInformation ()
+ {
+ }
+
+ public TranslationProjectInformation (string projectName)
+ {
+ this.projectName = projectName;
+ }
+ }
+}
|