We use resx files for globalization, along with database lookups for things that can be configured (such as tab names, which can be different by product) by our CS staff, and thus aren't known at design-time.
I created a custom tool that reads resx files and intelligently dumps the key/value pairs into a relational database (matching values so we don't have duplicates).
This has been a big help to our business - we don't have to send each resx for translation (and pay for duplicate translations of shared words) and we have a 'gold standard' with all our translations (in the database).
The tool I created also reads the database, picking up the key/value pairs and the translations of each value, and creates text files for each resx file (and each language's translation of the text file) and automates running resgen.exe, a command-line tool that ships with Visual Studio, to compile the resx files from the generated text files.
I don't have any source-control integration, so we have to manually check out the resx files and manually check-in the generated files when using the tool, but this hasn't been a big problem.
My problem is that this method is failing for our new MVC projects: the MVC projects require the resx files to be embedded resources with the Access Modifier of 'public'.
Thusfar, we have been fixing this by hand, which introduces the possibility of human error and adds a non-trivial amount of work.
Is there a way to get resgen.exe to create resource files that are embedded and public? If not, is there another way I can create resx files that will do so?
Update, additional question:
The resx files we generate with this method also raise a warning:
A custom tool 'PublicResXFileCodeGenerator' is associated with file '(resxname)',
but the output of the custom tool was not found in the project.
You may try re-running the custom tool by right-clicking on the file in the
Solution Explorer and choosing Run Custom Tool.
The tool mentioned is the tool we initially use to create the resx files. Is there a way I can prevent this warning?
First of, you can generated resources as public by using the /publicClass command line option. Also see: Resgen.exe - Resource File Generator # msdn
Second, I don't think you can let resgen make the resource files embedded resources by default, simply because its not a property of a resource, but a setting of the project.
For example: when you add a new resource "Resource1", using the wizard, a new item group will be added to the project file:
<ItemGroup>
<EmbeddedResource Include="Resource1.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resource1.Designer.cs</LastGenOutput>
</EmbeddedResource>
</ItemGroup>
Maybe there are libraries to programmatically modify project files, but not that I know of.
What I would do is just try to serialize and deserialize the project file yourself, and add that section to it, for each resource your generate.
EDIT:
It will also add in a different Item Group:
<ItemGroup>
<Compile Include="Resource1.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Resource1.resx</DependentUpon>
<DesignTime>True</DesignTime>
</Compile>
</ItemGroup>
So, unless you have a good 3rd Party program to serialize, edit, deserialize the project file. It it probably better to let the wizard do it.
I have struggled with this before but have resourcing working well. This may help although I am not sure. Its always worthwhikle to go over the basics as sometimes its something very simple and .NET resourcing can be infelxible.
I will explain my use of resourcing and hopefully you can apply it to your scenario (I cant really figure out what they exact problem is based on your question.)
Steps to setting up resourcing
1. Add a ASP.NET Folder to your web solution right click on solution select Add > Add ASP.NET Folder > App_GlobalResources
Add a resource file to the folder call it MyResourceFile.resx
Open Properties for file and select
Build Action : Embedded Resource
Custom Tool : PublicResXFileCodeGenerator
Then add your different resource files for different languages etc (specify the same properties for all resource file etc Build Action and Custom Tool)
MyResourceFile.en-GB.resx
MyResourceFile.fr-FR.resx
MyResourceFile.ja-JP.resx
This should auto generate your resource manager which can be accessed through calling
MyResourceFile.MyResourceText
It worth noting that if you havent got a culture installed or its incorrectly defined it wont work and you get all sorts of errors.
Etc MyResourceFile.en-JP.resx would not work (unless you create this custom culture) and cause all sorts of other issues. This culture will be mapped from the CultureInfo in the application to determine which resource file to use, therefore it must be a valid CultureInfo.
We did end up finding a solution to this problem.
For MVC projects, we changed the tool to use the ResXResourceWriter class to update the resx files, matching existing keys and adding new ones as needed.
This preserves the 'Embedded Resource' status as well as all of the other details that are needed.
We still have to set the file up correctly the first time it's created, but that is a much more manageable problem.
Related
I have a problem where I want to rename/move/copy a source XAML file before compiling it. I can see that there is a Move and a Copy task as a part of MSBuild that you can put into the .csproj file and it will do this. Unfortunately, I have only been able to get this to work with compiled files. Are either of these tasks supposed to work on the source files themselves?
If it is of any value, I'll elaborate a bit on what I'm trying to do, in case somebody has a completely different solution. Basically, our WPF application needs to be brandable. We've got the different brands in different XAML files (different icons and properties, etc.). These files are named something along the lines of BrandA.xaml, BrandB.xaml, etc. I'm currently trying to get exactly one of those brand files to be compiled into just simply Brand.xaml, which the rest of the application would then load. I've been able to get just a single file to copy over using MSBuild using conditions, but I haven't been able to get it named correctly.
Don't include the different brands as Page, but rather your custom item type, e.g. Brand (to ensure it's still part of the project and shows up in Visual Studio):
<Brand Include="BrandA.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Brand>
You can then use the BeforeBuild target to copy the relevant file to Brand.xaml and include it in the Page item group. You should be able to use both SourceFiles and DestinationFiles to rename the file as part of the copy.
I have my auto generated Resource.resx file set up with keys and strings. I also have three other resx files for German, French and Spanish given to me from translators. I'm not able to get the localization functioning and I suspect that the resx files aren't being called correctly. I added them to the project by dragging them into the solution explorer under "Properties". I have a nagging suspicion that just dragging them in isn't creating the proper connections behind the scene.
Now It's totally possible my issue lies somewhere else. If anyone can tell me whether it's ok to add resource files this way or if not, what the correct way is, it would save me tons of time spent chasing my tail. Thanks!
Resx files in Visual Studio include a special tool which is run at build time and translates them into embedded resources. Right-click your original VS-created resx file and click Properties. You should see Build Tool or something similar. Also note the resource type (Embedded, etc.). Make sure that you match these settings for your manually added files.
Once this is set up, you will need to use the CurrentUICulture property to tell .NET to pick up the appropriate resources. You can choose to change the culture/language at install-time or run-time. Here is a comprehensive tutorial which describes the various options available to you:
WPF Localization Using RESX Files
That said, as a best practice, translated Resx files are generally deployed as satellite assemblies. The main application DLL/EXE contains only the language neutral resources file. Other resource files are compiled into separate assemblies and deployed side-by-side with specific naming conventions. This allows you to dynamically add translations, localizations, etc. even after the application is deployed. Here's an introduction: Packaging and Deploying Resources in Desktop Apps
I have a console application that builds some default classes for me from a database. When the files are built, I want to be able to refresh my folders and see the new files in my class library.
However no matter what I do the files don't show up unless I go in and manually add existing files. Is there a way for VS2010 to look at the file folder and add in anything that is in that folder to the project? For example:
Folder > File1.cs, File2.cs, File3.cs, File4.cs
VS2010 sees
Folder > File1.cs
How can I make VS2010 show these new classes?
Your problem is that you will only see files that are included and referenced in your .csproj file. This is by and large a good thing because it gives you ultimate control over what is taken into account in the project or not. This is causing you a problem though, because the created files which are inserted into your project directory aren't being referenced. As you have mentioned you can include the files manually, but I understand that you wish this process to be automatic.
The best way to resovle this in my opinion is instead of having a project create the files, use design-time T4 templates. Design-time T4 templates are files which resemble pre-Razor ASP.NET views, which allow code generation within your project. You can access your database, format your classes and then output .cs files directly into your project without building it. This is extremely convenient becuase it lets you work on catching compile-time errors that may come up based on the output without having to do a complete build.
More information about using T4 can be found here.
And a good walkthrough can be found here.
Haven't tried this personally, but you should be able to do it using this..
First gain a reference to your project using your apps' solution, then with the Visual Studio automation framework (DTE):
ProjectItems p = Project.ProjectItems;
p.AddFromFile("File1.cs");
Taken from: http://msdn.microsoft.com/en-us/library/envdte.projectitems.addfromfile.aspx
I would read further into it.
Select the project where you can find your file
On top of your solution explorer you can select "show all files"
Select your files and include
Adding them automatically can be done from another app or script by modifying your projects .csproj/vbproj file
<Compile Include="My Project\MyClass.vb" />
This must be done in the correct itemgroup.
I think this is not directly possible. You may write a template file (t4) in order to create you cs files and they will be added to project when the transformation file is run.
In order to run the transformation file after / before build, you may write a pre/post build event.
That will require you to create a VS add-in.. you can find an example here...
Okay so I have a console application that is building some default classes for me from a database.
Can't you let this application write all classes in one file, say Proxy.cs or Entities.cs. Then every time you regenerate the file and rebuild the project, you can access the new classes.
Is it simple or even possible?
Why: Following my other question and using this approach, now I would like to simply embed the source file to the resources so I can copy it to the temp folder while the application is running - and keep the application as a single file.
I assume using a pre-build event is the best way to do this. If so, how would it be done?
EDIT: I'm asking about adding it before building because I also assume it won't be automatically updated if I add it manually once and then change the code after.
I recently went through this same issue when developing an examples suite for a .NET control which had to display its own example source code in the application.
The approach I ended up with was as follows.
I created a batch script (run in pre-build) to copy all the code files under /Examples/* to another folder in the solution Resources/ExamplesSrc/*
I then included all these files under Resources/ExamplesSrc/* in the csproj and saved it.
The next step was I set all the files under Resources/ExamplesSrc/* as embedded resource and committed the change to SVN. I did not commit the examples (generated) to SVN, just the modified csproj and batch file.
The effect when developers checked out was that they had (!) icons on all the resources (they were not on disk, but the csproj was looking for them), however as soon as they built the generated files appeared and all was well. This approach also worked with a build server (Team city) and the examples suite can now load and browse its own code via embedded resources.
One caveat you should be aware of. There is a quirk (by design apparently) in VS2010. If an embedded resource has ".cs" in it (i.e. any code file!) it cannot be loaded from the assembly using Assembly.GetManifestResourceStream(). To work around this all source files were renamed in the batch copy step from *.Xaml.cs to *.Xaml.c.txt, from *.cs to *.c.txt
Hope this helps!
Turns out I don't need to (re)add the source file each time I build the solution!
When I add it manually once it becomes a "Text" file on resources - and I can easily access it as a string using Properties.Resources.SourceCode (having the file named "SourceCode.cs"). And yes, it is updated automatically since the resource property "Persistence": the file is linked at compile time.
I am working on localization for a asp.net application that consists of several projects.
For this, there are some strings that are used in several of these projects. Naturally, I would prefer to have only one copy of the resource file in each project.
Since the resource files don't have an namespace (at least as far as I can tell), they can't be accessed like regular classes.
Is there any way to reference resx files in another project, within the same solution?
You can just create a class library project, add a resource file there, and then refer to that assembly for common resources.
I have used this solution before to share a assembley info.cs file across all projects in a solution I would presume the same would work fro a resource file.
Create a linked file to each individual project/class library. There will be only one copy and every project will have a reference to the code via a linked file at compile time. Its a very elegant solution to solve shared non public resources without duplicating code.
<Compile Include="path to shared file usually relative">
<Link>filename for Visual Studio To Dispaly.resx</Link>
</Compile>
add that code to the complile item group of a csproj file then replace the paths with your actual paths to the resx files and you sould be able to open them.
Once you have done this for one project file you should be able to employ the copy & paste the linked file to other projects without having to hack the csproj.
Some useful advice on how to manage a situation like this is available here:
http://www.codeproject.com/KB/dotnet/Localization.aspx