Localization with C# Windows Forms, cannot access my .resx File - c#

Hi I created this WinForm Program. It has several Forms.
I looked for a tutorial or someting to help and found this on StackoverFlow.
How to use Localization in C#
It was really helpful but..
I created a ResourceString.de-DE.resx File and added it to the Properties Folder.
Added some Strings so i can test it. And changed the Access Modifier to Public.
Then i wanted to access the Properties Folder to Use the ResourceString.de-De.resx File.
But it doesn't get suggested.
The Code has to look like this in the end :
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.ResourceString.de-DE.btnSwitchLanguage;
}
Am I missing something ?
Any Help is appreciated. :)
Thanks

You don't need to add the Strings.resx file, Your project already has the resource file Resources.resx. Therefore, you should add a new resource file with Resources.de.resx name, if required localization for the "de-DE". So, you can put into this resource file not only strings, but images, icons etc.
There is no need to change the Access Modifier to Public unless you are not going to access this resources from another assembly.
NOTE: When you are working in the Visual Studio the Visual Assist
suggestion will be the same for all languages, starting from
Properties.Resources.

You need to create a default 'ResourceString.resx' file along with al your language specific resx files. Make sure to add the same resources in all resx files. (btnSwitchLanguage, ...).

Well i found my mistake, after reading the Thread again, that i linked in my Post.
There should be a File called Strings.resx (or whatever Name you Choose), which contains the original strings.
And the File which contains another language. (German in my Example).
Should have the same name, except the language comes at the end.
Like this :
Strings.de-DE.resx
After that i just had to change my Code to :
private void btnSwitchLanguage_Click(object sender, EventArgs e)
{
if (Thread.CurrentThread.CurrentUICulture.ToString().Equals("de-DE"))
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en-GB");
}
else
{
Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("de-DE");
setLanguage();
}
}
private void setLanguage()
{
btnSwitchLanguage.Text = Properties.Strings.btnSwitchLanguage;
}

Related

Read Settings from Dependent Project in C#

I just want to start by saying that I've done a lot of research but couldn't find an answer, hence the post.
I'm adding user settings functionality to my app which works as a plugin inside a common off the shelf program for architecture (called Autodesk Revit). The main project (let's call it MainProj) has several dependencies including a project that handles logging and usage (let's call it Loggers). I created a Settings file inside the Loggers project with the goal to have users change the logging level from Error to Debug when there are issues so I can ask them to make the change and send me the log.
The issue I'm facing is that when I change the log level directly inside the config file and re-run the command from within Revit, the change doesn't get translated into the log, as if the log level is somehow compiled during design and is never changed.
I actually tried to reproduce the problem in a simpler way and created a little console program and I'm facing the same issue. Below is the code from the Loggers project.
namespace Loggers
{
public static class Logger
{
public static string RunMe()
{
if (Properties.Settings.Default.LogMode == "Debug") { return "DEBUG"; }
else return "NOTHING";
}
}
}
I then changed the LogMode property from Debug to anything else in the config file but the console kept on returning DEBUG.
static void Main(string[] args)
{
Console.WriteLine(Logger.RunMe());
Console.Read();
}
I also tried changing the setting from user to application and editing its value in the config file and re-running the command but the outcome was the same.
Any help would be very much appreciated. I've been stuck on this for a while. Thank you.
Thanks to #BurnsBA, the link you shared had comments saying that the user.config lives in a different folder and it's not created until the user changes a setting. This made me understand that there wasn't a point in manually editing the app.config and expect the settings to work.
I then did some testing by creating a simple form with a checkbox linked to the Property I wanted to change and the user.config file gets created straight after I call the Save() method on the Properties.
private void btnOK_Click(object sender, EventArgs e)
{
if (chkDebugMode.Checked == true)
Loggers.Properties.Settings.Default.LogMode = "Debug";
else Loggers.Properties.Settings.Default.LogMode = "Error";
Loggers.Properties.Settings.Default.Save();
Close();
}

C# WPF Localization - Ignoring other cultures and loading default Resources

I'm trying to localize my app, I've created several Resources.[culture].resx but program ignores them all and always loads default Resources.resx.
I have this code in App construtor (and in OnStartup event)
System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
My resources are called Resources.en-US.resx, Resources.cs-CZ.resx and Resources.resx
Code in WPF is
xmlns:p="clr-namespace:WpfThermalLabelEditorApp.Properties"
Title="{x:Static p:Resources.Title}"
This should load en-US localization but it doesn't. Loads default. I tried to delete AssemblyInfo and even putting <UICulture> tags into csproj
Not sure if this is the answer, but FWIW: I always set both CurrentCulture and CurrentUICulture like so;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(languageAbbreviation);
Thread.CurrentThread.CurrentUICulture = new CultureInfo(languageAbbreviation);
And be sure to double check the abbreviation you use is the same for all references. That should fix your problem.
EDIT1: Make sure your resource files are set to public, the access modifier should be somewhere near the top when you're viewing the resource file. Double check this says public and rebuild. Also, to call your resource file key do so like this:
<TextBlock xmlns:local="clr-namespace:WpfApplication2" Text="{x:Static local:Resource1.myname}"/>
Where...
"WpfApplication2" is replaced with your project name
"Resource1" is replace with the name of your resource file (without culture id, e.g. for your case it would just be Resources)
"myname" is replaced with the key you want
I came across the same problem, the solution was to clean and rebuild the project. No need to create new project.
Well, after 2 days I've solved my problem. My solution was correct. I have no idea what was wrong but I've created a new project, moved all my data to a new one and suddenly everything worked as a charm.
Here is a few usefull links:
WPF localization and globalization
Localization tutorial
Localization tutorial 2

How to output a file from a roslyn code analyzer?

I'm using the roslyn API to write a DiagnosticAnalyzer and CodeFix.
After I have collected all strings and string-interpolations, I want to write all of them to a file but I am not sure how to do this the best way.
Of course I can always simply do a File.WriteAllText(...) but I'd like to expose more control to the user.
I'm also not sure about how to best trigger the generation of this file, so my questions are:
I do not want to hard-code the filename, what would be the best way to expose this setting to the user of the code-analyzer? A config file? If so, how would I access that? ie: How do I know the directory?
If one string is missing from the file, I'd like to to suggest a code fix like "Project contains changed or new strings, regenerate string file". Is this the best way to do this? Or is it possible to add a button or something to visual studio?
I'm calling the devenv.com executable from the commandline to trigger builds, is there a way to force my code-fix to run either while building, or before/after? Or would I have to "manually" load the solution with roslyn and execute my codefix?
I've just completed a project on this. There are a few things that you will need to do / know.
You will probably need to switch you're portable class library to a class library. otherwise you will have trouble calling the File.WriteAllText()
You can see how to Convert a portable class library to a regular here
This will potentially not appropriately work for when trying to apply all changes to document/project/solution. When Calling from a document/project/solution, the changes are precalcuated and applied in a preview window. If you cancel, an undo action is triggered to undo all changes, if you write to a file during this time, and do not register an undo action you will not undo the changes to the file.
I've opened a bug with roslyn but you can handle instances by override the preview you can see how to do so here
And one more final thing you may need to know is how to access the Solution from the analyzer which, Currently there is a hack I've written to do so here
As Tamas said you can use additional files you can see how to do so here
You can use additional files, but I know on the version I'm using resource files, are not marked as additional files by default they are embeddedResources.
So, for my users to not have to manually mark the resource as additonalFiles I wrote a function to get out the Designer.cs files associated with resource files from the csproj file using xDoc you can use it as an example if you choose to parse the csproj file:
protected List<string> GetEmbeddedResourceResxDocumentPaths(Project project)
{
XDocument xmldoc = XDocument.Load(project.FilePath);
XNamespace msbuild = "http://schemas.microsoft.com/developer/msbuild/2003";
var resxFiles = new List<string>();
foreach (var resource in xmldoc.Descendants(msbuild + "EmbeddedResource"))
{
string includePath = resource.Attribute("Include").Value;
var includeExtension = Path.GetExtension(includePath);
if (0 == string.Compare(includeExtension, RESX_FILE_EXTENSION, StringComparison.OrdinalIgnoreCase))
{
var outputTag = resource.Elements(msbuild + LAST_GENERATED_TAG).FirstOrDefault();
if (null != outputTag)
{
resxFiles.Add(outputTag.Value);
}
}
}
return resxFiles;
}
For config files you can use the AdditionalFiles msbuild property, which is passed to the analyzers through the context. See here.

How to use .resx and .resource files in custom server control asp?

I am writing my own server side control and I am using images that are being stored in a .resx file. In the console application this code works fine:
ResXResourceReader rsxr = new ResXResourceReader("Resource1.resx");
foreach (DictionaryEntry d in rsxr)
{
Console.WriteLine(d.Key.ToString() + ":\t" + d.Value.ToString());
}
rsxr.Close();
but here
protected override void RenderContents(HtmlTextWriter output)
{
ResXResourceReader rsxr = new ResXResourceReader("Resource1.resx");
base.RenderContents(output);
foreach (DictionaryEntry d in rsxr)
{
output.Write(d.Key.ToString());
}
}
I get this error:
Could not find file 'C:\Program Files\Common Files\Microsoft Shared\DevServer\10.0\Resource1.resx'
I tried to use the ResourceManager, but it requires a .resource file. I can't access the resgen tool (command prompt does not understand the resgen command) and install it (during the attempt some errors ocured).
My questions are:
Why can't I read .resx?
How to install the resgen tool properly?
thanks.
It is considered good practice to store your resource file under App_GlobalResources folder in application root or in App_LocalResources with the same name as your user control file. So for example user user control is uc.ascx file in local resource folder should be uc.ascx.resx. That way it is easier to maintain and asp.net will automatically detect it.
Now your answers:
First Question:
Use Server.MapPath("~/") points to physical directly where your web.config is. If you want to use a resource file in Controls folder you have to write Server.MapPath("~/Controls/Resource1.resx") to get the path.
Not sure what you want to do with resgen tool? When you compile your application, resource file will also be compiled. select your resource file and click F4, it will show you build action, choose resource in build action and your resource file will be included in assembly.
You can review this post for more information: How to use image resource in asp.net website?
From your description, I understand you need to locate and access the user control's resource file. I found that it works nicely the following way:
Create a App_GlobalResources on project level (via context menu Add -> Add ASP.NET Folder -> App_GlobalResources)
Create the ressource file with the same name as the control, but inside the App_GlobalResources. For example, if the control is named myControl.ascx, then the ressource file's name for the default language has to be myControl.ascx.resx
Create additional ressource files for each language you require. For instance, if you need German ("de-DE"), then add myControl.ascx.de.resx
Add the class MultiLanguageUserControl as follows:
public class MultiLanguageUserControl : System.Web.UI.UserControl
{
public string getResValue(string id)
{
var ctrlPath = TemplateControl.AppRelativeVirtualPath;
var ctrlFile = System.IO.Path.GetFileName(ctrlPath);
var resObj = GetGlobalResourceObject(ctrlFile, id);
if (resObj!=null)
return resObj.ToString();
else
return string.Format("UNRESOLVED[{0}]", id);
}
}
Open the code behind of myControl and make it inherit from MultiLanguageUserControl instead from System.Web.UI.UserControl:
public partial class myControl : MultiLanguageUserControl { //... }
In the HTML code, use the new function, e.g.: <%=getResValue("resid")%>, where "resid" is the name of the ressource string you want to look up. You can also use the HTML-encoding tag <%: instead of <%=, depending on your requirements. Alternatively, you can use getResValue anywhere in your server-sided C# code in your user control to retrieve the value from the ressource file.
Ensure that you support the language detection in the Page_Load event of the page, which uses the user control. How you can do this is described here (look for the function InitializeCulture).
NOTE: If you want to read the page's local resource strings from inside the user control then take a look here.

Could not find any resources appropriate for the specified culture or the neutral culture

I have created an assembly and later renamed it.
Then I started getting runtime errors when calling:
toolsMenuName = resourceManager.GetString(resourceName);
The resourceName variable is "enTools" at runtime.
Could not find any resources
appropriate for the specified culture
or the neutral culture. Make sure
"Jfc.TFSAddIn.CommandBar.resources"
was correctly embedded or linked into
assembly "Jfc.TFSAddIn" at compile
time, or that all the satellite
assemblies required are loadable and
fully signed.
The code:
string resourceName;
ResourceManager resourceManager = new ResourceManager("Jfc.TFSAddIn.CommandBar", Assembly.GetExecutingAssembly());
CultureInfo cultureInfo = new CultureInfo(_applicationObject.LocaleID);
if(cultureInfo.TwoLetterISOLanguageName == "zh")
{
CultureInfo parentCultureInfo = cultureInfo.Parent;
resourceName = String.Concat(parentCultureInfo.Name, "Tools");
}
else
{
resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools");
}
toolsMenuName = resourceManager.GetString(resourceName); // EXCEPTION IS HERE
I can see the file CommandBar.resx included in the project, I can open it and can see the "enTools" string there. It seems that either resources are not included into assembly or resource are included but .NET cannot resolve the name.
I think simpler solution would be to create separate resources file for each language.
As far as this case is concerned check if the assembly containing resources has the default namespace set to the same text (Project->Properties->Default namespace; in VS)
Check as well if the resx file has a property BuildAction set to "Embedded resource"
Sounds similar to an issue we had. The namespace was incorrect in the resource file's designer. I fixed it by manually re-running the custom-tool on the resx file.
Right click your.resx, and click Run Custom Tool.
I'm sure you've already got the answer, but just in case:
You can view your ManifestResourceName by calling
System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceNames()
Check that Manifest name and your name in GetString() calling are identical.
Also, be sure you have correct namespace in designer.resx file:
namespace Jfc.TFSAddIn {
...
global::System.Resources.ResourceManager temp =
new global::System.Resources.ResourceManager(
"Jfc.TFSAddIn.CommandBar", typeof(CommandBar).Assembly);
...
}
Open resx file properties: "Build Action" should be "Embedded Resource"
For me, the source of the problem was naming the rex files starting with a number:
20160216_tranlation.resx
I had to add an underscore _ before the resx file name when calling GetGlobalResourceObject:
public static string getResource(string key)
{
return HttpContext.GetGlobalResourceObject("_20160216_tranlation", key).ToString();
}
I corrected the namespace in designer file (Resources.Designer.cs) in ResourceManager static property & it worked for me.
See the code below:
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("XYZAssembly.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
I added a temporary class within my Form.cs while (testing || debugging) that caused this exception to be thrown. The Form.resx file (Name || Resource ID) was modified to the temporary class name instead of the Form class name. This caused the issue for me. I (corrected || alleviated) this by creating a separate file for my temporary class in the project.
One Solution is to change the property of resx file from content to Embedded Resource and Build it.Sure this time u vil get
I have encountered this issue in Xamarin.Forms, when I tried to the rename the project, the resources could not be loaded anymore with the same stated error text.
To fix the problem I had to modify the .csproj by a text editor, and change the logical name of the embedded resource.
<EmbeddedResource Include="Localization\TextResources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>TextResources.Designer.cs</LastGenOutput>
<LogicalName>YourNewNamespaceName.TextResources.resources</LogicalName>
<SubType>Designer</SubType>
</EmbeddedResource>
Also watch out for the autogenerated class when you rebuild it, the namespace stated in there might change.
Hope it helps someone that went into the same situation.
Got this error when I added a class ABOVE the partial form class in my Windows forms app.
It went away when I moved the class BELOW the partial form class.
This answer solved the problem for me! GetGlobalResourceObject

Categories