Beispiel #1
0
        public static ErrorResource Parse(XElement errorXml)
        {
            Contracts.AssertValue(errorXml);

            var errorResource = new ErrorResource();

            // Parse each sub-element into the TagToValues dictionary.
            foreach (var tag in errorXml.Elements())
            {
                string tagName = tag.Name.LocalName;

                // Links are specialized because they are a two-part resource.
                if (tagName == LinkTag)
                {
                    errorResource.AddHelpLink(tag);
                }
                else
                {
                    if (!errorResource.TagToValues.ContainsKey(tagName))
                    {
                        errorResource.TagToValues[tagName] = new List <string>();
                    }

                    errorResource.TagToValues[tagName].Add(tag.Element("value").Value);
                }
            }

            return(errorResource);
        }
Beispiel #2
0
        public static bool TryGetErrorResource(ErrorResourceKey resourceKey, out ErrorResource resourceValue, string locale = null)
        {
            Contracts.CheckValue(resourceKey.Key, "action");
            Contracts.CheckValueOrNull(locale, "locale");

            if (locale == null)
            {
                locale = CurrentLocaleInfo.CurrentUILanguageName;
                Contracts.CheckNonEmpty(locale, "currentLocale");
            }

            Dictionary <string, ErrorResource> errorResources;

            if (!ErrorResources.TryGetValue(locale, out errorResources))
            {
                lock (dictionaryLock)
                {
                    Dictionary <string, string> strings;
                    LoadFromResource(locale, ResourceNamePrefix, typeof(TypeFromThisAssembly), ResourceFileName, ResourceFormat.Resw, out strings, out errorResources);
                    Strings[locale]        = strings;
                    ErrorResources[locale] = errorResources;
                }
            }

            return(errorResources.TryGetValue(resourceKey.Key, out resourceValue) || (ExternalStringResources?.TryGetErrorResource(resourceKey, out resourceValue, locale) ?? false));
        }
Beispiel #3
0
        private static Dictionary <string, ErrorResource> PostProcessErrorResources(Dictionary <string, string> separateResourceKeys)
        {
            // ErrorResource name -> ErrorResourceTag -> tag number -> value
            var errorResources = new Dictionary <string, Dictionary <string, Dictionary <int, string> > >(StringComparer.OrdinalIgnoreCase);

            foreach (var resource in separateResourceKeys)
            {
                if (!resource.Key.StartsWith(ErrorResource.ReswErrorResourcePrefix, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                // Skip URLs, we'll handle that paired with the link tag
                if (resource.Key.EndsWith(ErrorResource.LinkTagUrlTag, StringComparison.OrdinalIgnoreCase))
                {
                    continue;
                }

                foreach (var tag in ErrorResource.ErrorResourceTagToReswSuffix)
                {
                    if (!ErrorResource.IsTagMultivalue(tag.Key))
                    {
                        if (!resource.Key.EndsWith(tag.Value, StringComparison.OrdinalIgnoreCase))
                        {
                            continue;
                        }

                        // Single valued tag, we use index=0 here when inserting
                        var resourceName = resource.Key.Substring(ErrorResource.ReswErrorResourcePrefix.Length, resource.Key.Length - (ErrorResource.ReswErrorResourcePrefix.Length + tag.Value.Length));
                        UpdateErrorResource(resourceName, resource.Value, tag.Key, 0, errorResources);
                        break;
                    }
                    else
                    {
                        if (!TryGetMultiValueSuffix(resource.Key, tag.Value, out var suffix, out var index))
                        {
                            continue;
                        }

                        var resourceName = resource.Key.Substring(ErrorResource.ReswErrorResourcePrefix.Length, resource.Key.Length - (ErrorResource.ReswErrorResourcePrefix.Length + suffix.Length));
                        UpdateErrorResource(resourceName, resource.Value, tag.Key, index, errorResources);

                        // Also handle the URL for link resources
                        if (tag.Key == ErrorResource.LinkTag)
                        {
                            // This must exist, and the .verify call will fail CI builds if the resource is incorrectly defined.
                            separateResourceKeys.TryGetValue(resource.Key + "_url", out var urlValue).Verify();
                            UpdateErrorResource(resourceName, urlValue, ErrorResource.LinkTagUrlTag, index, errorResources);
                        }
                        break;
                    }
                }
            }

            return(errorResources.ToDictionary(kvp => kvp.Key, kvp => ErrorResource.Reassemble(kvp.Value)));
        }
Beispiel #4
0
        public static ErrorResource Reassemble(Dictionary <string, Dictionary <int, string> > members)
        {
            Contracts.AssertAllNonEmpty(members.Keys);
            Contracts.AssertAllValues(members.Values);

            var errorResource = new ErrorResource();

            // Reassemble link 2-part resources first
            // They need to match up. Because these resources are loaded for almost all tests,
            // The asserts here will fail during unit tests if they're incorrectly defined
            if (members.TryGetValue(LinkTag, out var linkValues))
            {
                members.TryGetValue(LinkTagUrlTag, out var urls).Verify();
                Contracts.Assert(linkValues.Count == urls.Count);

                foreach (var kvp in linkValues)
                {
                    urls.TryGetValue(kvp.Key, out var correspondingUrl).Verify();
                    errorResource.HelpLinks.Add(new ErrorHelpLink(kvp.Value, correspondingUrl));
                }
                members.Remove(LinkTag);
                members.Remove(LinkTagUrlTag);
            }


            foreach (var tag in members)
            {
                if (!errorResource.TagToValues.ContainsKey(tag.Key))
                {
                    errorResource.TagToValues[tag.Key] = new List <string>();
                }

                foreach (var value in tag.Value.OrderBy(kvp => kvp.Key).Select(kvp => kvp.Value))
                {
                    errorResource.TagToValues[tag.Key].Add(value);
                }
            }

            return(errorResource);
        }
Beispiel #5
0
        internal static void LoadFromResource(string locale, string assemblyPrefix, Type typeFromAssembly, string resourceFileName, ResourceFormat resourceFormat, out Dictionary <string, string> strings, out Dictionary <string, ErrorResource> errorResources)
        {
            var assembly = typeFromAssembly.Assembly;

            // This is being done because the filename of the manifest is case sensitive e.g. given zh-CN it was returning English
            if (locale.Equals("zh-CN"))
            {
                locale = "zh-cn";
            }
            else if (locale.Equals("zh-TW"))
            {
                locale = "zh-tw";
            }
            else if (locale.Equals("ko-KR"))
            {
                locale = "ko-kr";
            }

            using (var res = assembly.GetManifestResourceStream(assemblyPrefix + locale.Replace("-", "_") + "." + resourceFileName))
            {
                if (res == null)
                {
                    if (locale == FallbackLocale)
                    {
                        throw new InvalidProgramException(string.Format("[StringResources] Resources not found for locale '{0}' and failed to find fallback", locale));
                    }

                    // Load the default ones (recursive, but not infinite due to check above)
                    LoadFromResource(FallbackLocale, assemblyPrefix, typeFromAssembly, resourceFileName, resourceFormat, out strings, out errorResources);
                }
                else
                {
                    var loadedStrings = XDocument.Load(res).Descendants(XName.Get("data"));
                    strings        = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                    errorResources = new Dictionary <string, ErrorResource>(StringComparer.OrdinalIgnoreCase);

                    if (resourceFormat == ResourceFormat.Pares)
                    {
                        foreach (var item in loadedStrings)
                        {
                            string type;
                            if (item.TryGetNonEmptyAttributeValue("type", out type) && type == ErrorResource.XmlType)
                            {
                                errorResources[item.Attribute("name").Value] = ErrorResource.Parse(item);
                            }
                            else
                            {
                                strings[item.Attribute("name").Value] = item.Element("value").Value;
                            }
                        }
                    }
                    else if (resourceFormat == ResourceFormat.Resw)
                    {
                        var separatedResourceKeys = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                        foreach (var item in loadedStrings)
                        {
                            var itemName = item.Attribute("name").Value;
                            if (itemName.StartsWith(ErrorResource.ReswErrorResourcePrefix, StringComparison.OrdinalIgnoreCase))
                            {
                                separatedResourceKeys[itemName] = item.Element("value").Value;
                            }
                            else
                            {
                                strings[itemName] = item.Element("value").Value;
                            }
                        }
                        errorResources = PostProcessErrorResources(separatedResourceKeys);
                    }
                    else
                    {
                        Contracts.Assert(false, "Unknown Resource Format");
                    }
                }
            }
        }