コード例 #1
0
        /// ------------------------------------------------------------------------------------
        /// <summary>
        /// Saves the cache to the files from which the cache was originally loaded, but only
        /// if the cache is dirty. If the cache is dirty and saved, then true is returned.
        /// Otherwise, false is returned.
        /// </summary>
        /// ------------------------------------------------------------------------------------
        internal void SaveIfDirty(ICollection <string> langIdsToForceCreate)
        {
            if (!IsDirty)
            {
                return;
            }

            StringBuilder errorMsg = null;

            foreach (var langId in XliffDocuments.Keys)
            {
                try
                {
                    if (XliffDocuments[langId].IsDirty)
                    {
                        SaveFileForLangId(langId, langIdsToForceCreate != null && langIdsToForceCreate.Contains(langId), XliffDocuments[langId]);
                    }
                }
                catch (Exception e)
                {
                    if (e is SecurityException || e is UnauthorizedAccessException || e is IOException)
                    {
                        if (errorMsg == null)
                        {
                            errorMsg = new StringBuilder();
                            errorMsg.AppendLine("Failed to save localization changes in the following files:");
                        }
                        errorMsg.AppendLine();
                        errorMsg.Append("File: ");
                        errorMsg.AppendLine(OwningManager.GetPathForLanguage(langId, true));
                        errorMsg.Append("Error Type: ");
                        errorMsg.AppendLine(e.GetType().ToString());
                        errorMsg.Append("Message: ");
                        errorMsg.AppendLine(e.Message);
                    }
                }
            }

            if (errorMsg != null)
            {
                throw new IOException(errorMsg.ToString());
            }

            IsDirty = false;
        }
コード例 #2
0
        /// ------------------------------------------------------------------------------------
        private void SaveFileForLangId(string langId, bool forceCreation, XLiffDocument xliffOriginal)
        {
            if (!forceCreation && !OwningManager.DoesCustomizedTranslationExistForLanguage(langId))
            {
                return;
            }

            var xliffOutput = CreateEmptyStringFile();

            if (langId != LocalizationManager.kDefaultLang)
            {
                xliffOutput.File.TargetLang = langId;
            }
            xliffOutput.File.ProductVersion           = OwningManager.AppVersion;
            xliffOutput.File.HardLineBreakReplacement = s_literalNewline;
            xliffOutput.File.AmpersandReplacement     = _ampersandReplacement;
            if (OwningManager != null && OwningManager.Name != null)
            {
                xliffOutput.File.Original = OwningManager.Name + ".dll";
            }

            foreach (var tu in DefaultXliffDocument.File.Body.TransUnits)
            {
                var tuTarget = xliffOriginal.File.Body.GetTransUnitForId(tu.Id);
                XLiffTransUnitVariant tuv = null;
                if (tuTarget != null)
                {
                    tuv = tuTarget.GetVariantForLang(langId);
                }
                // REVIEW: should we write units with no translation (target)?
                var newTu = new XLiffTransUnit {
                    Id = tu.Id, Dynamic = tu.Dynamic
                };
                newTu.AddOrReplaceVariant(tu.GetVariantForLang(LocalizationManager.kDefaultLang));
                if (tuv != null)
                {
                    newTu.AddOrReplaceVariant(tuv);
                }
                newTu.Notes = tu.CopyNotes();
                xliffOutput.AddTransUnit(newTu);
            }
            xliffOutput.File.Body.TransUnits.Sort(TuComparer);
            xliffOutput.Save(OwningManager.GetPathForLanguage(langId, true));
        }
コード例 #3
0
        /// ------------------------------------------------------------------------------------
        private void MergeXliffFilesIntoCache(IEnumerable <string> xliffFiles)
        {
            DefaultXliffDocument = XLiffDocument.Read(OwningManager.DefaultStringFilePath);             // read the generated file
            // It's possible (I think when there is no customizable Xliff, as on first install, but the version in the installed Xliff
            // is out of date with the app) that we don't have all the info from the installed Xliff in the customizable one.
            // We want to make sure that (a) any new dynamic strings in the installed one are considered valid by default
            // (b) any newly obsolete IDs are noted.
            if (File.Exists(OwningManager.DefaultInstalledStringFilePath))
            {
                if (!XLiffLocalizationManager.ScanningForCurrentStrings)
                {
                    var defaultInstalledXliffDoc = XLiffDocument.Read(OwningManager.DefaultInstalledStringFilePath);
                    foreach (var tu in defaultInstalledXliffDoc.File.Body.TransUnits)
                    {
                        DefaultXliffDocument.File.Body.AddTransUnitOrVariantFromExisting(tu, LocalizationManager.kDefaultLang);
                    }
                }
            }
            XliffDocuments.Add(LocalizationManager.kDefaultLang, DefaultXliffDocument);
            // Map the default language onto itself.
            LocalizationManagerInternal <XLiffDocument> .MapToExistingLanguage[LocalizationManager.kDefaultLang] = LocalizationManager.kDefaultLang;

            Exception error = null;

            foreach (var file in xliffFiles)
            {
                try
                {
                    var xliffDoc = XLiffDocument.Read(file);
                    var langId   = xliffDoc.File.TargetLang;
                    Debug.Assert(!string.IsNullOrEmpty(langId));
                    Debug.Assert(langId != LocalizationManager.kDefaultLang);
                    // Provide a mapping from a specific variant of a language to the base language.
                    // For example, "es-ES" can provide translations for "es" if we don't have "es" specifically.
                    var pieces = langId.Split('-');
                    if (pieces.Length > 1)
                    {
                        if (!LocalizationManagerInternal <XLiffDocument> .MapToExistingLanguage.ContainsKey(pieces[0]))
                        {
                            LocalizationManagerInternal <XLiffDocument> .MapToExistingLanguage.Add(pieces[0], langId);
                        }
                    }
                    // Identity mapping always wins.  Storing it simplifies code elsewhere.
                    LocalizationManagerInternal <XLiffDocument> .MapToExistingLanguage[langId] = langId;
                    XliffDocuments.Add(langId, xliffDoc);
                    var defunctUnits = new List <XLiffTransUnit>();
                    foreach (var tu in xliffDoc.File.Body.TransUnits)
                    {
                        // This block attempts to find 'orphans', that is, localizations that have been done using an obsolete ID.
                        // We assume the default language Xliff has only current IDs, and therefore don't look for orphans in that case.
                        // This guards against cases such as recently occurred in Bloom, where a dynamic ID EditTab.AddPageDialog.Title
                        // was regarded as an obsolete id for PublishTab.Upload.Title
                        if (langId != LocalizationManager.kDefaultLang && DefaultXliffDocument.GetTransUnitForId(tu.Id) == null &&
                            !tu.Id.EndsWith(kToolTipSuffix) && !tu.Id.EndsWith(kShortcutSuffix))
                        {
                            //if we couldn't find it, maybe the id just changed and then if so re-id it.
                            var movedUnit = DefaultXliffDocument.GetTransUnitForOrphan(tu);
                            if (movedUnit == null)
                            {
                                // with dynamic strings, by definition we won't find them during a static code scan
                                if (!tu.Dynamic)
                                {
                                    defunctUnits.Add(tu);
                                    xliffDoc.IsDirty = true;
                                    IsDirty          = true;
                                }
                            }
                            else
                            {
                                if (xliffDoc.File.Body.TranslationsById.ContainsKey(tu.Id))
                                {
                                    // adjust the document's internal cache
                                    xliffDoc.File.Body.TranslationsById[movedUnit.Id] = xliffDoc.File.Body.TranslationsById[tu.Id];
                                    xliffDoc.File.Body.TranslationsById.Remove(tu.Id);
                                }
                                tu.Id            = movedUnit.Id;
                                xliffDoc.IsDirty = true;
                                IsDirty          = true;
                            }
                        }
                    }
                    // Now we can delete any invalid XLiffTransUnit objects from this document.
                    foreach (var tuBad in defunctUnits)
                    {
                        xliffDoc.File.Body.RemoveTransUnit(tuBad);
                    }
                }
                catch (Exception e)
                {
                    var msg = $"Caught exception in MergeXliffFilesIntoCache [{file}] - {e.Message}";
#if DEBUG
                    throw new Exception(msg, e);
#else
                    // If an error happened reading some localization file other than one we care
                    // about right now, just ignore it.
                    if (file == OwningManager.GetPathForLanguage(LocalizationManager.UILanguageId, false))
                    {
                        error = new Exception(msg, e);
                    }
#endif
                }
            }
            if (error != null)
            {
                throw error;
            }
        }