/// <summary> /// Read ResxData from .resx files /// </summary> /// <param name="path">root path of resx files</param> /// <param name="deepSearch">search subdirs</param> /// <param name="cultureList">list of cultures to translate</param> /// <param name="excludeKeyList">list of keys to exclude (regular expressions)</param> /// <param name="excludeCommentList">list of comments to exclude (regular expressions)</param> /// <param name="useFolderNamespacePrefix">use folder namespace prefix</param> /// <returns>a ResxData with all data</returns> public static ResxData FromResx(string path, bool deepSearch, bool purge, List<CultureInfo> cultureList, List<string> excludeKeyList, List<string> excludeCommentList) { ResxData rd = new ResxData(); rd.exportCultures = cultureList; rd.excludeKeyList = excludeKeyList; rd.excludeCommentList = excludeCommentList; List<string> regexes = AppSettings.Default.ExcludeFilenames.Cast<string>() .ToList(); var searchoptions = deepSearch ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly; var files = Directory.GetFiles(path, "*.resx", searchoptions) .Where(filename => !regexes.Any(pattern => Regex.IsMatch(filename, pattern))) .ToList(); foreach (string f in files) { var resx = new Resx(f); if (!resx.IsCultureSpecific) { rd.ReadResx(resx, path, purge); } } if (!string.IsNullOrEmpty(rd.ReadResxReport)) { Console.WriteLine(rd.ReadResxReport); } return rd; }
/// <summary> /// Read a specific .resx file /// </summary> /// <param name="primaryResx">resource file to import</param> /// <param name="projectRoot">root of project used to calculate relative path</param> /// <param name="useFolderNamespacePrefix">use folder namespace prefix</param> private void ReadResx(Resx primaryResx, string projectRoot, bool purge) { // Create resx reader for primary language var primaryEntries = primaryResx.Read() .Where(k => this.ValidateKey(k.Key)) .Where(k => this.ValidateComment(k.Comment)) .Where(k => !string.IsNullOrEmpty(k.Value)); if (primaryEntries.Count() > 0) { // Create translation source entry for resx file TranslationSourceRow resxrow = this.TranslationSource.NewTranslationSourceRow(); resxrow.FileSource = primaryResx.GetRelativePath(projectRoot); this.TranslationSource.AddTranslationSourceRow(resxrow); // Iterate over all entries in resource file fileName foreach (ResxItem resxitem in primaryEntries) { var resxkey = this.AddResxKey(resxrow, resxitem.Key, resxitem.Value, resxitem.Comment); } // Create resx readers for all requested cultures var secondaryResxs = new Dictionary<string, IEnumerable<ResxItem>>(); foreach (CultureInfo culture in exportCultures) { var path = string.Format("{0}.{1}.resx", primaryResx.PathWithoutExtension, culture.Name); if (File.Exists(path)) { var resx = new Resx(path); var entries = resx.Read() .Where(k => this.ValidateKey(k.Key)) .Where(k => !string.IsNullOrEmpty(k.Value)); foreach (ResxItem resxitem in entries) { var row = this.PrimaryTranslation.Where(p => p.TranslationSource == resxrow.Id) .FirstOrDefault(r => r.Key == resxitem.Key); if (row == null && !purge) { row = this.AddResxKey(resxrow, resxitem.Key, "", "does not exist in primary language"); row.Implicit = true; } if (row != null) { this.AddSecondaryKey(row, culture.Name, resxitem.Value); } } } } // Check for missing keys when base language has keys var untranslated = this.PrimaryTranslation.Where(p => p.ResxRow == resxrow) .Where(p => p.GetResxLocalizedRows().Count() == 0); if (untranslated.Count() > 0) { string missingReport = string.Format( "Missing translations from {0}:{1}{2}", primaryResx.GetRelativePath(projectRoot), Environment.NewLine, string.Join(", ", untranslated.Select(u => u.Key).ToArray())); this.ReadResxReport += missingReport + Environment.NewLine + Environment.NewLine; } } }