public void MergeXliffDocuments_WorksAsExpected() { var oldDoc = CreateTestDocument(); var newDoc = CreateTestDocument(); AdjustDocumentForTestingMerge(newDoc); var mergedDoc = XLiffLocalizationManager.MergeXliffDocuments(newDoc, oldDoc, true); Assert.IsNotNull(mergedDoc); Assert.That(5, Is.EqualTo(oldDoc.File.Body.TransUnits.Count)); Assert.That(6, Is.EqualTo(newDoc.File.Body.TransUnits.Count)); Assert.That(8, Is.EqualTo(mergedDoc.File.Body.TransUnits.Count)); var tu = mergedDoc.GetTransUnitForId("This.test"); CheckMergedTransUnit(tu, "This is a test.", new[] { "ID: This.test", "This is only a test" }, false); tu = mergedDoc.GetTransUnitForId("That.test"); CheckMergedTransUnit(tu, "That was a test.", new[] { "ID: That.test", "That is hard to explain, but a literal rendition is okay.", "Not found in static scan of compiled code (version 3.1.4)" }, false); tu = mergedDoc.GetTransUnitForId("What.test"); CheckMergedTransUnit(tu, "What is a good test?", new[] { "ID: What.test", "[OLD NOTE] Whatever you say...", "[OLD NOTE] This should be a question.", "OLD TEXT (before 1.0): What are good test.", "OLD TEXT (before 3.1.4): What is good test." }, true); tu = mergedDoc.GetTransUnitForId("What.this"); CheckMergedTransUnit(tu, "What is this nonsense?", new[] { "ID: What.this", "Not dynamic: found in static scan of compiled code (version 3.1.4)" }, false); Assert.IsNotNull(tu); tu = mergedDoc.GetTransUnitForId("This.new1"); CheckMergedTransUnit(tu, "This is a new test.", new[] { "ID: This.new1", "This is still only a test" }, false); tu = mergedDoc.GetTransUnitForId("That.new2"); CheckMergedTransUnit(tu, "That was an old test.", new[] { "ID: That.new2", "That should be easy to translate." }, false); tu = mergedDoc.GetTransUnitForId("What.new3"); CheckMergedTransUnit(tu, "What's up, doc?", new[] { "ID: What.new3" }, true); tu = mergedDoc.GetTransUnitForId("How.now"); CheckMergedTransUnit(tu, "How now brown cow", new[] { "ID: How.now", "Not found when running compiled program (version 3.1.4)" }, true); }
static void Main(string[] args) { // Parse and check the command line arguments. if (!ParseOptions(args)) { Usage(); return; } LocalizationManager.TranslationMemoryKind = TranslationMemory.XLiff; // Load the input assemblies so that they can be scanned. List <Assembly> assemblies = new List <Assembly>(); foreach (var file in _assemblyFiles) { var asm = Assembly.LoadFile(file); if (asm != null) { assemblies.Add(asm); } } // Scan the input assemblies for localizable strings. var extractor = new StringExtractor <XLiffDocument> { ExternalAssembliesToScan = assemblies.ToArray() }; var localizedStrings = extractor.DoExtractingWork(_namespaces.ToArray(), null); // The arguments to this constructor don't really matter much as they're used internally by // L10NSharp for reasons that may not percolate out to xliff. We just need a LocalizationManagerInternal // to feed into the constructor the LocalizedStringCache that does some heavy lifting for us in // creating the XliffDocument from the newly extracted localized strings. var lm = new XLiffLocalizationManager(_fileOriginal, _fileOriginal, _fileProductVersion); var stringCache = new XLiffLocalizedStringCache(lm, false); foreach (var locInfo in localizedStrings) { stringCache.UpdateLocalizedInfo(locInfo); } // Get the newly loaded static strings (in newDoc) and the baseline XLIFF (in baseDoc). var newDoc = stringCache.XliffDocuments[kDefaultLangId]; var baseDoc = LoadBaselineAndCompare(newDoc); // Save the results to the output file, merging in data from the baseline XLIFF if one was specified. var xliffOutput = XLiffLocalizationManager.MergeXliffDocuments(newDoc, baseDoc, _verbose); xliffOutput.File.SourceLang = kDefaultLangId; xliffOutput.File.ProductVersion = !string.IsNullOrEmpty(_fileProductVersion) ? _fileProductVersion : newDoc.File.ProductVersion; xliffOutput.File.HardLineBreakReplacement = kDefaultNewlineReplacement; xliffOutput.File.AmpersandReplacement = kDefaultAmpersandReplacement; xliffOutput.File.Original = _fileOriginal; xliffOutput.File.DataType = !string.IsNullOrEmpty(_fileDatatype) ? _fileDatatype : newDoc.File.DataType; xliffOutput.Save(_xliffOutputFilename); }
static void Main(string[] args) { // Parse and check the command line arguments. if (!ParseOptions(args)) { Usage(); return; } LocalizationManager.TranslationMemoryKind = TranslationMemory.XLiff; // Load the input assemblies so that they can be scanned. List <Assembly> assemblies = new List <Assembly>(); List <string> assemblyPaths = new List <string>(); if (_glob) { foreach (var glob in _assemblyFiles) { assemblyPaths.AddRange(Directory.GetFiles(Path.GetDirectoryName(glob), Path.GetFileName(glob))); } } else { assemblyPaths = _assemblyFiles; } foreach (var file in assemblyPaths) { // Using LoadFrom to make sure we pick up other assemblies in the same directory so we don't fail // to load because of 'missing' dependencies var asm = Assembly.LoadFrom(file); assemblies.Add(asm); for (var index = 0; index < _additionalLocalizationMethodNames.Count; index++) { var methodNameSpec = _additionalLocalizationMethodNames[index]; try { var type = asm.GetType(methodNameSpec.Item1 + "." + methodNameSpec.Item2); if (type == null) { continue; } _additionalLocalizationMethods.AddRange(type .GetMethods(BindingFlags.Static | BindingFlags.Public) .Where(m => m.Name == methodNameSpec.Item3)); if (_verbose) { Console.WriteLine($"Method {methodNameSpec.Item2}.{methodNameSpec.Item3} in {asm.GetName().FullName} will be treated as a localization method."); } _additionalLocalizationMethodNames.RemoveAt(index--); } catch (Exception e) { if (_verbose) { Console.WriteLine("Error using reflection on {asm.GetName().FullName} to get type {methodNameSpec.Item2} or method {methodNameSpec.Item3}:" + e.Message); } } } } if (_verbose && _additionalLocalizationMethodNames.Any()) { Console.WriteLine("Failed to find the following additional localization methods:"); foreach (var methodNameSpec in _additionalLocalizationMethodNames) { Console.WriteLine($"{methodNameSpec.Item1}.{methodNameSpec.Item2}.{methodNameSpec.Item3}"); } } // Scan the input assemblies for localizable strings. var extractor = new StringExtractor <XLiffDocument> { ExternalAssembliesToScan = assemblies.ToArray() }; extractor.OutputErrorsToConsole = _verbose; var localizedStrings = extractor.DoExtractingWork(_additionalLocalizationMethods, _namespaces.ToArray(), null); // The arguments to this constructor don't really matter much as they're used internally by // L10NSharp for reasons that may not percolate out to xliff. We just need a LocalizationManagerInternal // to feed into the constructor the LocalizedStringCache that does some heavy lifting for us in // creating the XliffDocument from the newly extracted localized strings. var lm = new XLiffLocalizationManager(_fileOriginal, _fileOriginal, _fileProductVersion); var stringCache = new XLiffLocalizedStringCache(lm, false); foreach (var locInfo in localizedStrings) { stringCache.UpdateLocalizedInfo(locInfo); } // Get the newly loaded static strings (in newDoc) and the baseline XLIFF (in baseDoc). var newDoc = stringCache.GetDocument(kDefaultLangId); var baseDoc = LoadBaselineAndCompare(newDoc); // Save the results to the output file, merging in data from the baseline XLIFF if one was specified. var xliffOutput = XLiffLocalizationManager.MergeXliffDocuments(newDoc, baseDoc, _verbose); xliffOutput.File.SourceLang = kDefaultLangId; xliffOutput.File.ProductVersion = !string.IsNullOrEmpty(_fileProductVersion) ? _fileProductVersion : newDoc.File.ProductVersion; xliffOutput.File.HardLineBreakReplacement = kDefaultNewlineReplacement; xliffOutput.File.AmpersandReplacement = kDefaultAmpersandReplacement; xliffOutput.File.Original = _fileOriginal; xliffOutput.File.DataType = !string.IsNullOrEmpty(_fileDatatype) ? _fileDatatype : newDoc.File.DataType; xliffOutput.Save(_xliffOutputFilename); }