"key: " in designer

Sep 15, 2013 at 2:27 PM
After configuring my window every localized text is displayed in designer like this: "key: MyKeyName". Why is that?

In window header I have:
lex:LocalizeDictionary.DesignCulture="pl-PL"
lex:ResxLocalizationProvider.DefaultAssembly="AssemblyName"
lex:ResxLocalizationProvider.DefaultDictionary="Strings"
control:
<MenuItem Header="{lex:Loc Menu_Tools}" />
Everything is ok when control is localized like this:
<MenuItem Header="{lex:Loc AssemblyName:Strings:Menu_Tools}" />
Is there any solution for this issue?
Sep 19, 2013 at 9:19 AM
Same problem here. Thanks for posting a workaround!
Sep 25, 2013 at 12:03 PM
I confirm it, too. With one exception, it doesn't metter how control is localized - localized text, for me, is always: "Key: xxx". This problem occuring at VS2012. Designer works normal at VS2010. I can't check now, what about Blend.

Cheers
Christopher
Sep 25, 2013 at 12:42 PM
Update. I reloaded project and strings displayed normal. But, if I edited string, it doesn't bring any change - untill reload project. If I inserted new string into resources and used it as localize value, it is displayed like "Key: xxx".
I skimmed source code, and, if I uderstand, phrase "Key: xxx" mean that extension doesn't find key and can't get value from resources. I don't know why extension doesn't see changes at resources. Any suggest?

Cheers
Chris
Coordinator
Sep 25, 2013 at 9:23 PM
Hi,

the problem is, that the VS2012 designer is creating a shadow copy of your binaries, including the resource files. These files cannot be overwritten (which also means updated after inserting or changing localized texts), because they are loaded and therefore locked by the XDesProc process. Unfortunately, the designer itself does not update these files after rebuild. One proposed workaround is to shut down this process, rebuild and then reload the designer.

In my opinion, this is a bug, but I had no success in the MS forums.

Best regards,
Uwe
Coordinator
Sep 26, 2013 at 5:59 AM

Could vs2013 fix the problem?

Sep 26, 2013 at 6:35 AM
And everything is clear. Thank you for info.
Coordinator
Sep 29, 2013 at 1:33 PM
SeriousM wrote:
Could vs2013 fix the problem?
We'll see - but I will wait until the final version is available before testing it.
Nov 10, 2013 at 9:27 PM
Hy @all

Are there any news?
I have the same issue on VS2012 Pro

Is there any Workaround?
Maybe a Batchfile?

Thanks in advance
Sascha
Coordinator
Nov 17, 2013 at 8:10 PM
No news so far on that topic :-(.
Jan 12 at 2:27 PM
How are the chances, that this issue gets fixed soon?

I am afraid, that it was not a that good decision to rely on WPF Localizatin Extension.
My main reason to do so was the benefit to see localization at design time, which now is gone :-(
Also the workaround described above does not work with my project....
How it looks in my project
Coordinator
Jan 15 at 8:26 PM
Hi,

I'm now a fresh new owner of VS2013, but I have to find some time to evaluate the problem there. I'll keep you updated.

Best regards,
Uwe
Jan 24 at 6:55 PM
Same issue with VS2013 here.
Jan 26 at 3:21 PM
Hi All,

I have good news ;-)
I just installed the VS2013 Update1 and I looks like the issue is gone!

Regards
Rainer
Jan 26 at 3:31 PM
Sorry, I looks like I was too enthusiastic.
First my Views did not show the "key:" any more. Then I played around with them a little and now the "key:" is back ;-(

Regards
Rainer
Feb 3 at 1:14 PM
I too have this problem in VS2012, but the 'workaround' doesn't work here as I always had it like that. Just an FYI, the old versions of this project always worked fine but the new versions have this problem here.
Feb 3 at 3:51 PM
Edited Feb 3 at 5:12 PM
Since it made this new version completely useless, I did some checking myself and found the problem of this issue. It isn't that hard to fix actually.

In the ResxLocalizationProviderBase there is a function GetResourceManager that is not working correctly.

There is this line (line 248):
var dir = Path.GetDirectoryName(process.Modules[0].FileName);
This doesn't work for x64 processes when the host process is x86 (and the other way around).
This is easily solved through WMI (the only way that works afaik):

Create a function in the same file:
        /// <summary>
        /// Get the executable path for both x86 and x64 processes.
        /// </summary>
        /// <param name="processId">The process id.</param>
        /// <returns>The path if found; otherwise, null.</returns>
        private static string GetExecutablePath(int processId)
        {
            const string wmiQueryString = "SELECT ProcessId, ExecutablePath, CommandLine FROM Win32_Process";
            using (var searcher = new ManagementObjectSearcher(wmiQueryString))
            using (var results = searcher.Get())
            {
                var query = from p in Process.GetProcesses()
                            join mo in results.Cast<ManagementObject>()
                            on p.Id equals (int)(uint)mo["ProcessId"]
                            where p.Id == processId
                            select new
                            {
                                Process = p,
                                Path = (string)mo["ExecutablePath"],
                                CommandLine = (string)mo["CommandLine"],
                            };
                foreach (var item in query)
                {
                    return item.Path;
                }
            }
            return null;
        }
Then, change line 248 from above to:
   var dir = Path.GetDirectoryName(GetExecutablePath(process.Id));
   if (String.IsNullOrWhiteSpace(dir))
       continue;
However, there is other major issue in this same function.

Let's start with the first. There are foreach loops over the files:
    foreach (var f in files)
There are a couple of issues I'm having with both these lines. The first being that it copies everything from every subdirectory. I have a subdirectory that stores temp files (a total of 12GB of small files). It takes 35 minutes to fully copy the folder that is of zero interest to this library. After all, it only needs two different file types, and the exe's and dll's of the assembly. So, the first change I made for both foreach loops is this:
 foreach (var f in files.Where(x => !String.IsNullOrWhiteSpace(x)))
                        {
                            if (!(f.EndsWith(".resx", StringComparison.OrdinalIgnoreCase) ||
                                  f.EndsWith(".resources", StringComparison.OrdinalIgnoreCase)) &&
                                  !dir.Equals(Path.GetDirectoryName(f), StringComparison.OrdinalIgnoreCase)) // We aren't bothered with other files
                                continue;

 // The other code
Then, there is this bit of code (283-288):
  var dst = Path.Combine(assemblyDir, f.Replace(dir + "\\", ""));

                                    var dstDir = Path.GetDirectoryName(dst);
                                    if (!Directory.Exists(dstDir))
                                        Directory.CreateDirectory(dstDir);
                                    File.Copy(f, dst, true);
Since the generated cache folder is already quite long (C:\Users\UserName\AppData\Local\Microsoft\VisualStudio\11.0\Designer\ShadowCache\gx43qkl1.wag\fdty5ini.grk\tmp), it easily goes over the max file path length (250). This caused the function to crash. Honestly, I don't care about one or two files that aren't able to be copied and thus disabling the whole preview so I made some changes too for this bit:
                                try
                                {
                                    var dst = Path.Combine(assemblyDir, f.Replace(dir + "\\", ""));

                                    var dstDir = Path.GetDirectoryName(dst);
                                    if (String.IsNullOrWhiteSpace(dstDir))
                                        continue;

                                    if (!Directory.Exists(dstDir))
                                        Directory.CreateDirectory(dstDir);
                                    File.Copy(f, dst, true);
                                }
                                // ReSharper disable once EmptyGeneralCatchClause
                                catch { } // Ignore exceptions so the designer can continue to work.
So, here is the request to the author to fix this in the version on NuGet so I can continue to use that one. I don't mind editing code but it would be nice if it worked out of the box.

Thanks for all your hard work on this, we've been using it for a while now, but in my opinion it's current state is worse than what it is a year ago.
I also don't understand the reason why you want to put LocTextUpper etc on obsolete. Using converters isn't always an option when you need multiple converters (and I don't like chaining converters).

There are also some data errors now:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.FrameworkElement', AncestorLevel='1''. BindingExpression:Path=Parent; DataItem=null; target element is 'ContextMenu' (Name='MainContextMenu'); target property is 'Parent' (type 'DependencyObject')
Coordinator
Feb 3 at 9:11 PM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Coordinator
Feb 3 at 9:15 PM
Just one additional question: Did one of the older versions you mentioned go well (which means complete design-time preview) under VS2012 or higher? If yes, please give me a hint on that combination of versions.

Regarding your request on the LocTextUpper - the old specialized extensions will be reverted to normal in the next release (this was already covered in another thread).
Feb 4 at 8:19 AM
MrCircuit wrote:
Just one additional question: Did one of the older versions you mentioned go well (which means complete design-time preview) under VS2012 or higher? If yes, please give me a hint on that combination of versions.

Regarding your request on the LocTextUpper - the old specialized extensions will be reverted to normal in the next release (this was already covered in another thread).
Yes, the older versions always worked fine in the design time preview. The version we previously used had this data in AssemblyInfo.cs:
[assembly: AssemblyVersion("2.1.2.0")]
[assembly: AssemblyFileVersion("2.1.2.0")]

We modified it a bit (mainly 'Dictionary<string, ResourceManager> ResourceManagerList' to 'public Dictionary<string, ResourceManager> ResourceManagerList { get; set; }' in ResxLocalizationProviderBase.cs because the .resources files are locked and the only way to delete or update these resources files is to call .ReleaseAllResources on the ResourceManager.) but this never affected the designer. A while ago we also tried to update to another version (I think it was 2.1.4) and it had the same designer issues.

I also saw a post that you mentioned that you would ship signed packages on NuGet. Since all our packages are signed we cannot include your package without signing them first. We currently use an additional app that can sign the assemblies but it would be nice if the next version could also ship signed. Thank you for all your hard work, it's been a great time saver, if you have more questions, please ask ;)