I'm having a hard time wrapping my mind around how the resources work in an ASP.NET project. In my solution I have 2 projects:
A Website project that contains an App_GlobalResources folder where most of my resources reside (build action: "content").
A utility project, compiled as class library (that the website references), where I need another set of resources (called "ExceptionMessages" hereafter).
Nota: each project uses its own resources, there is no cross linking involved here.
I added a new resource directly in my second project (both as "content" or "embeded resource") and tried to access it via ExceptionMessages.Tag. Intellisense is happy about it and correctly suggests the Tag but I get the following error at runtime:
"Could not find any resources appropriate for the specified culture or
the neutral culture. Make sure
"Resources.ExceptionMessages.resources" was correctly embedded or
linked into assembly "App_GlobalResources.lqgd5zqy" at compile time,
or that all the satellite assemblies required are loadable and fully
signed."
Somehow, I don't understand why the webserver is looking for the resource in the App_GlobalResources instead of directly in the assembly where it is used... or how I could go around this in a clean way. Any hint or idea?
Thanks!
Related
I had a fairly big project and has lot of logic in form of classes in a folder.
Now i need to make a separate project that contains those classes.
All those classes are referring resource files for language..
Like
Localization.MyStringVariable
Copying the resource files too in a separate project make it build but throws error at runtime.
The error is resource files no loaded for neutral culture...
Any help is highly appreciated.
Exact Error:
{"Could not find any resources appropriate for the specified culture or the neutral culture. Make sure \"Project.Localization.resources\" was correctly embedded or linked into assembly \"ProjectDAL\" at compile time, or that all the satellite assemblies required are loadable and fully signed."}
I need to create resource files (.resx) programatically. Those ressource files are meant for
other projects, not for the one where I programatically create those resx files.
Is there a clean way to tell the other solutions/projects that it has to add the externally created ressource file.
In the resoure files strings are stored which shall be used in that project later.
Example:
I create a Resource.resx file with a project called ResourceCreator.
Now I have to tell a Project called MyProject to bind it into the solution/project WITHOUT to have to manually open the solution and add it then.
I believe you really want to create Satellite Assemblies.
A satellite assembly is a compiled library (DLL) that contains
(“localizable”) resources such as strings, bitmaps, etc. You are
likely to use them when creating a multilingual (UI) application.
Satellite assemblies provide you with the capability of designing and
deploying your solution to multiple cultures, rather than hard coding
strings, bitmaps, etc., into your main application. Satellite
assemblies are used to deploy applications in multiple cultures (not
languages), with 1 satellite assembly per culture - this is the
default behavior, but you can obviously have more granular control if
you handle the build process manually.
MSDN Ref - Introduction to Satellite Assemblies
Try looking into the Microsoft.Build namespace, it has all sorts of fancy ways of loading/modifying project and solution files.
Microsoft.Build namespaces
I know there are several questions about satellite Assembly's out there, but I still have some troubles when trying to implement them
My Goal is to separate each culture in a single assembly, giving me the flexibility to only re-compile one assembly at a time when required, I wouldn't like to compile all languages if I only want to make some minor changes to just one language
I want to fully understand how satellite Assembly's work. This is my current understanding:
Satellite Assembly's can be dropped in the bin directory without the need to recompile the whole application, which means the app does not require these assemblies in order to work correctly (as long as the fallback resource is specified)
S.A. has to be linked to a single culture
Now I can generate a S.A. using the al tool or Visual Studio can do it for me if I add the .resx files, the S.A. are created (in the bin folder I can see the folder structure for the specified cultures)
Question 1. Are these dll's equivalent, the one's generated by Visual Studio and the one's generated with the al tool?
Question 2. Do all these dll's must share a common name in order to work?? (I know for consistency they should, but if they do not share the name let's say creating them with the al tool specifying different names) can they still be recognized by the .Net framework to be loaded?
Question 3. If I want to use the ResourceManager class, do I have to instantiate one instance for each assembly-culture? (and since they contain the culture in their name, they have different assembly names, do I have to manually format the embedded resource file to load to match the current culture and load that assembly manually? Since they would probably not be loaded the first time, do I have to load it manually by specifying the file path inside the culture folder?)
Question 4. Are these S.A. loaded automatically by the .Net framework or do I have to explicitly load them?
Question 5. In case I have to load them, this means if I want to specify the resources declaratively in my control tags, do I have to create and register a custom resources factory in order to load them?
Question 6. If I add several resources for several cultures in a class project in visual studio with no code, they are automatically embedded, when I compile, the satellite assemblies for each culture are created, are these dll's related? I wonder if they are related by name, namespace or something
All these questions are based on this: I thought I would be able to just add the assemblies to the bin folder and specify something like a global assembly in the ResourceManager, and it would load automatically the resources even when they'd be in a different assembly (that's why my concern about the assembly names or how several satellite assemblies are related) just like when you define resources in a single assembly, you just call the Resources.MyResourceKey and that's it
I appreciate your hellp, this topic is driving me crazy =(
I know the resgen and al tools look a bit more complicated than they ought to be, but I am pretty sure that your goal is achievable, i.e. you can build your satellite assemblies outside of a Visual Studio solution (to save you having to maintain all your translated resources in your solution) but get exactly the same results.
Question 1: Yes
Question 2: Yes, the ResourceManager depends on the naming convention to load localized resources
Question 3: No. You can use the standard ResourceManager. In fact you don't have to use ResourceManager directly at all. Include your base resources in your solution and configure it with Build Action = Embedded Resource and Custom Tool = PublicResXFileCodeGenerator, then Visual Studio will automatically generate and maintain a class (with the same name as your resx file) that lets you access resources through static properties. Depending on Thread.CurrentThread.CurrentUICulture and on what satellite assemblies are deployed, these properties will either give you localized resources from a satellite assembly or from your base assembly.
Question 4: No. The ResourceManager does that automatically.
Question 5: See Q4. Nothing to do.
Question 6: See Q2. It's based on a naming convention (folder named as per the culture, satellite assembly named as per the base dll) and metadata (e.g. culture name used when compiling using al)
I've two Visual Basic 2008 projects - one is a class library project and another is a Windows Forms project. In the class library project, I've defined some strings in the project resources (project properties > Resources tab).
I build that class library project and get the DLL file from the debug folder and added up as a reference in my Windows Forms project.
How do I read those strings from the referenced DLL file?
While you can dynamically load the DLL as ho suggests, it's fine to use a reference as you have done. In fact I would recommend using a reference unless you had a particular requirement to dynamically load the resource assembly.
As to accessing the resources there are a few things you need to do.
In the resource assembly you will need to ensure the resources are public. By default resources are set to internal which means you will not see the resources in the winforms app. Double click on Properties\Resources.resx to open the resources view. In the top toolbar you will see a label "Access Modifier" next to a combo box drop down. Change the selection to public.
You will need to reference the assembly from the forms app. You have stated you have already done this. Just a note that a better way to do this is to create a solution that contains both projects. Then in the forms app choose add reference. Click on the Projects tab up the top. Double click on the resource DLL project name. This works better than referencing the debug DLL directly since it means if you change between a release build and debug build in your forms app, it will automatically build a matching release/debug version of your resource assembly.
Once you have added the reference you can simply reference the type out of the resources DLL, e.g.
ResourceDLLNamespace.Properties.Resource.ResourceName
Just a note, you need to be aware of type name clashes if you are using the same namespace for your forms app and resource DLL. In this situation both your forms app will have access to it's own Properties.Resources class as well as that of the resource DLL. You can do two things to avoid this:
Use a different namespace between the two assemblies
In the resource assembly don't include a default Properties\Resources.resx resource dictionary. Delete it and manually add a new resource, i.e. Add New Item and select "Resources File". You should find that you will not be able to add the new resource dictionary to the Properties folder - add it to the root or some other folder as you require. This will automatically give it a different type name by virtue of being in a different folder. You still may want to avoid using the resource file name of "Resources" however, as if you have all the relevant namespaces in scope via using statements you will get the same issue that the compiler won't know which version of Resources to use.
-Donovan
I think you just use System.Reflection.Assembly.Load to load the other assembly then use the constructor of System.Resources.ResourceManager that takes an assembly.
Note, I don't think it needs to a reference for this to work.
I am trying to modify an existing WPF application for localization. One of my restrictions is that all resources (including the default en-US fallback resource) have to be satellite resources. None of them can be embedded in the main assembly.
Through some reading on codeplex, I found that all I need to do is make the following change in my AssemblyInfo.cs file.
[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
When I do this, I get an exception on application startup saying:
Could not find any resources
appropriate for the specified culture
or the neutral culture. Make sure
"XXX.YYY.ZZZ.g.en-US.resources"
was correctly embedded or linked into
assembly "XXX.YYY.ZZZ"
at compile time, or that all the
satellite assemblies required are
loadable and fully signed.
If I switch back to putting the fallback resource (en-US) in the main assembly, everything works fine again. From what I've read, if you want to have the fallback resource as a satellite resource, you must have a specific resource for that locale (i.e. you must have a Resources.en-US.resx). Am I correct?
What seems fishy to me in the exception is the g (.g.en-US). Does that signify something? The g doesn't exist in any of my resource files?
Am I creating my resources correctly. I first create a generic Resources.resx file, put all my strings in it. Then, I simply copy/paste within Visual Studio and rename for each specific locale (ar, es-MX, etc.). Then, make the appropriate translations.
For now, I am just focusing on one projects resource files. Maybe it's getting hung up on a different project that doesn't have an en-US version of it's resource file?? If so, is there any way to get Visual Studio to tell me more about what it's really getting hung up on?
In short, your understanding of the resource files and what needs built seems correct.
The .g is for the compiled XAML files and built for you automatically. Nothing special or magical going on here.
Normally the fallback resource is embedded in the main assembly. If you are not doing that, you must create a satellite resource assembly for every culture you are going to do, plus an en-US one.