public void TryToFixBrokenSubstitutionMarkers(string badFormat, string goodFormat) { var result = XLiffLocalizedStringCache.FixBrokenFormattingString(badFormat); Assert.That(result, Is.EqualTo(goodFormat)); // Check for the maximum number of possible substitution markers: unused arguments don't matter for validity. Assert.That(XLiffLocalizedStringCache.CheckForValidSubstitutionMarkers(3, result, "a.b"), Is.EqualTo(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); }
/// <summary> /// Check that all the format substitution markers are present and okay. /// </summary> /// <returns> /// true if the translation substitution markers are all valid and match the source markers, false otherwise /// </returns> private static ErrorState CheckFormatStringMarkers(string filename) { var retval = ErrorState.Okay; var doc = XLiffDocument.Read(filename); var dictSourceMarkers = new Dictionary <string, int>(); var dictTargetMarkers = new Dictionary <string, int>(); foreach (var tu in doc.File.Body.TransUnitsUnordered) { if (tu.Source == null || tu.Target == null) { continue; } if (String.IsNullOrWhiteSpace(tu.Source.Value) || String.IsNullOrWhiteSpace(tu.Target.Value)) { continue; } var matchesSource = Regex.Matches(tu.Source.Value, "{[0-9]+}"); var matchesTarget = Regex.Matches(tu.Target.Value, "{[0-9]+}"); if (matchesSource.Count == 0 && matchesTarget.Count == 0) { continue; } TabulateMarkers(matchesSource, dictSourceMarkers); TabulateMarkers(matchesTarget, dictTargetMarkers); var okay = CheckForExactlyMatchingSubstitutionMarkers(tu.Id, dictSourceMarkers, dictTargetMarkers); if (!okay && retval == ErrorState.Okay) { retval = ErrorState.Warning; } if (!XLiffLocalizedStringCache.CheckForValidSubstitutionMarkers(dictSourceMarkers.Count, tu.Target.Value, tu.Id, _quiet)) { _mangledTargets.Add(tu.Id); retval = ErrorState.Error; okay = false; } if (!okay && !_quiet) { Console.WriteLine(); // separate the messages for different trans-units } } return(retval); }
private static void FixBrokenTransUnit(XElement tu, XmlNamespaceManager namespaceManager) { var tuid = tu.Attribute("id").Value; var source = tu.XPathSelectElement("x:source", namespaceManager); var target = tu.XPathSelectElement("x:target", namespaceManager); if (source.HasElements || target.HasElements) { Console.WriteLine("Cannot fix {0} because the translated material contains XML elements", tuid); return; } var targetValue = target.Value; if (!string.IsNullOrWhiteSpace(targetValue)) { var targetFixed = XLiffLocalizedStringCache.FixBrokenFormattingString(targetValue); if (targetFixed != target.Value) { target.SetValue(targetFixed); } } }
public void FixBrokenSubstitutionMarkersOnly(string badFormat, string goodFormat) { var result = XLiffLocalizedStringCache.FixBrokenFormattingString(badFormat); Assert.That(result, Is.EqualTo(goodFormat)); }
public void CheckStringsForValidSubstitionMarkers(int markerCount, string formatting, bool isValid) { Assert.That(XLiffLocalizedStringCache.CheckForValidSubstitutionMarkers(markerCount, formatting, "a.b"), Is.EqualTo(isValid)); }
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); }