From 08a2ec6883df9dd969d60ade4768b5a7ce171f1c Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 20 Mar 2015 18:15:31 +1100 Subject: [PATCH] Fixes: U4-6436 Localization in the back office doesn't work immediately after app restart --- .../LocalizedTextServiceFileSources.cs | 138 ++++++++++-------- 1 file changed, 75 insertions(+), 63 deletions(-) diff --git a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs index be53d8d16b..934b015079 100644 --- a/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs +++ b/src/Umbraco.Core/Services/LocalizedTextServiceFileSources.cs @@ -20,12 +20,83 @@ namespace Umbraco.Core.Services //TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :( private readonly Dictionary _twoLetterCultureConverter = new Dictionary(); + private readonly Lazy>> _xmlSources; + public LocalizedTextServiceFileSources(IRuntimeCacheProvider cache, DirectoryInfo fileSourceFolder) { if (cache == null) throw new ArgumentNullException("cache"); if (fileSourceFolder == null) throw new ArgumentNullException("fileSourceFolder"); + _cache = cache; + //Create the lazy source for the _xmlSources + _xmlSources = new Lazy>>(() => + { + var result = new Dictionary>(); + + if (_fileSourceFolder == null) return result; + + foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml")) + { + var localCopy = fileInfo; + var filename = Path.GetFileNameWithoutExtension(localCopy.FullName).Replace("_", "-"); + + //TODO: Fix this nonsense... would have to wait until v8 to store the language files with their correct + // names instead of storing them as 2 letters but actually having a 4 letter culture. wtf. So now, we + // need to check if the file is 2 letters, then open it to try to find it's 4 letter culture, then use that + // if it's successful. We're going to assume (though it seems assuming in the legacy logic is never a great idea) + // that any 4 letter file is named with the actual culture that it is! + CultureInfo culture = null; + if (filename.Length == 2) + { + //we need to open the file to see if we can read it's 'real' culture, we'll use XmlReader since we don't + //want to load in the entire doc into mem just to read a single value + using (var fs = fileInfo.OpenRead()) + using (var reader = XmlReader.Create(fs)) + { + if (reader.IsStartElement()) + { + if (reader.Name == "language") + { + if (reader.MoveToAttribute("culture")) + { + var cultureVal = reader.Value; + try + { + culture = CultureInfo.GetCultureInfo(cultureVal); + //add to the tracked dictionary + _twoLetterCultureConverter[filename] = culture; + } + catch (CultureNotFoundException) + { + LogHelper.Warn( + string.Format("The culture {0} found in the file {1} is not a valid culture", cultureVal, fileInfo.FullName)); + //If the culture in the file is invalid, we'll just hope the file name is a valid culture below, otherwise + // an exception will be thrown. + } + } + } + } + } + } + if (culture == null) + { + culture = CultureInfo.GetCultureInfo(filename); + } + + //get the lazy value from cache + result.Add(culture, new Lazy(() => _cache.GetCacheItem( + string.Format("{0}-{1}", typeof(LocalizedTextServiceFileSources).Name, culture.Name), () => + { + using (var fs = localCopy.OpenRead()) + { + return XDocument.Load(fs); + } + }, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] { localCopy.FullName }))); + } + return result; + }); + if (fileSourceFolder.Exists == false) { LogHelper.Warn("The folder does not exist: {0}, therefore no sources will be discovered", () => fileSourceFolder.FullName); @@ -42,69 +113,7 @@ namespace Umbraco.Core.Services /// public IDictionary> GetXmlSources() { - var result = new Dictionary>(); - - if (_fileSourceFolder == null) return result; - - foreach (var fileInfo in _fileSourceFolder.GetFiles("*.xml")) - { - var localCopy = fileInfo; - var filename = Path.GetFileNameWithoutExtension(localCopy.FullName).Replace("_", "-"); - - //TODO: Fix this nonsense... would have to wait until v8 to store the language files with their correct - // names instead of storing them as 2 letters but actually having a 4 letter culture. wtf. So now, we - // need to check if the file is 2 letters, then open it to try to find it's 4 letter culture, then use that - // if it's successful. We're going to assume (though it seems assuming in the legacy logic is never a great idea) - // that any 4 letter file is named with the actual culture that it is! - CultureInfo culture = null; - if (filename.Length == 2) - { - //we need to open the file to see if we can read it's 'real' culture, we'll use XmlReader since we don't - //want to load in the entire doc into mem just to read a single value - using (var fs = fileInfo.OpenRead()) - using (var reader = XmlReader.Create(fs)) - { - if (reader.IsStartElement()) - { - if (reader.Name == "language") - { - if (reader.MoveToAttribute("culture")) - { - var cultureVal = reader.Value; - try - { - culture = CultureInfo.GetCultureInfo(cultureVal); - //add to the tracked dictionary - _twoLetterCultureConverter[filename] = culture; - } - catch (CultureNotFoundException) - { - LogHelper.Warn( - string.Format("The culture {0} found in the file {1} is not a valid culture", cultureVal, fileInfo.FullName)); - //If the culture in the file is invalid, we'll just hope the file name is a valid culture below, otherwise - // an exception will be thrown. - } - } - } - } - } - } - if (culture == null) - { - culture = CultureInfo.GetCultureInfo(filename); - } - - //get the lazy value from cache - result.Add(culture, new Lazy(() => _cache.GetCacheItem( - string.Format("{0}-{1}", typeof (LocalizedTextServiceFileSources).Name, culture.Name), () => - { - using (var fs = localCopy.OpenRead()) - { - return XDocument.Load(fs); - } - }, isSliding: true, timeout: TimeSpan.FromMinutes(10), dependentFiles: new[] {localCopy.FullName}))); - } - return result; + return _xmlSources.Value; } //TODO: See other notes in this class, this is purely a hack because we store 2 letter culture file names that contain 4 letter cultures :( @@ -112,6 +121,9 @@ namespace Umbraco.Core.Services { if (twoLetterCulture.Length != 2) Attempt.Fail(); + //This needs to be resolved before continuing so that the _twoLetterCultureConverter cache is initialized + var resolved = _xmlSources.Value; + return _twoLetterCultureConverter.ContainsKey(twoLetterCulture) ? Attempt.Succeed(_twoLetterCultureConverter[twoLetterCulture]) : Attempt.Fail();