Thank you for your response and excellent quality video of your .resx management. Your methods will be useful on some other apps I plan to create.
I was finally successful at getting my C# Winforms to show in any UICulture languages! I want to share this information with others:
RIBBON PANEL LOCALIZATION:
I added a language switcher file based on Andrey Bushman' sample file. This has been modified to 'RVTLanguages.cs'. The file was placed in my root folder below my C# project name.
In the same location, I also created three .resx files:
RibbonResources.resx (empty and set to 'Internal')
RibbonResources.en-US.resx (all of my panel data - see image below)
RibbonResources.fr-FR.resx (my french translations)
To keep my panel button narrow and allow for wrapping of text, I created two lines in the .resx file
In my App.cs :
public Result OnStartup(UIControlledApplication application)
{
#region READ AND SET THE LANGUAGE ENVIRONMENT USING THE RVTLanguages.cs file
RVTLanguages.Cultures(application.ControlledApplication.Language);
ResourceManager res_mng = new ResourceManager(typeof(RibbonResources));
#endregion
RibbonPanel p = application.CreateRibbonPanel(RibbonResources.ResourceManager.GetString("PanelName"));
string thisAssemblyPath = Assembly.GetExecutingAssembly().Location;
string buttonText1 = RibbonResources.ResourceManager.GetString("CommandName1");
string buttonText2 = RibbonResources.ResourceManager.GetString("CommandName2");
PushButtonData btnMyApp = new PushButtonData("btnMyApp", buttonText1 + "\n" + buttonText2, thisAssemblyPath, typeof(Command).FullName)
{
LargeImage = imgSrc,
Image = imgSrcTB,
LongDescription = RibbonResources.ResourceManager.GetString("CommandDescription"),
ToolTip = RibbonResources.ResourceManager.GetString("CommandToolTip")
};
// set help file to reference .bundle file help.html
string helpFolder = Path.Combine(parentFolder, "help.html");
ContextualHelp contextHelp = new ContextualHelp(
ContextualHelpType.ChmFile, helpFolder);
btnMyApp.SetContextualHelp(contextHelp);
p.AddItem(btnMyApp);
This was all that was required for setting up a localized ribbon button.
CREATING THE LOCALIZED WINFORMS:
I created a folder called "Forms" and then placed all of my WinForms under this folder.
After my forms were created, I then manually created two new .resx files.
for example: "MyForm.en-US.resx" and "MyForm.fr-FR.resx"
These files were placed in the Forms folder along with my main WinForm.
In my Winform code I did the following:
MyForm.cs
public sealed class UICultureSwitcher : IDisposable
{
CultureInfo previous;
public UICultureSwitcher()
{
CultureInfo culture = new CultureInfo(Thread
.CurrentThread.CurrentCulture.Name);
previous = Thread.CurrentThread.CurrentUICulture;
Thread.CurrentThread.CurrentUICulture = culture;
}
void IDisposable.Dispose()
{
Thread.CurrentThread.CurrentUICulture = previous;
}
}
public MyForm(Autodesk.Revit.DB.Document doc)
{
ResourceManager res_mng = new ResourceManager(typeof(MyForm));
ResourceSet resourceSet = res_mng.GetResourceSet(Thread.CurrentThread.CurrentUICulture, true, true);
InitializeComponent();
familyDocument = doc;
label1.Text = GetLocalizedTextFromResource("label1Text");
label2.Text = GetLocalizedTextFromResource("label2.Text");
label3.Text = GetLocalizedTextFromResource("label3.Text");
label4.Text = GetLocalizedTextFromResource("label4.Text");
............
<rest of code>
}
Below I have a function that will collect the necessary language information in the .resx file.
private string GetLocalizedTextFromResource(string key)
{
try
{
// Load the appropriate resource file based on the user's selected language
ResourceManager resourceManager = new ResourceManager("MyApp.Forms.MyForm", typeof(MyForm).Assembly);
CultureInfo currentCulture = Thread.CurrentThread.CurrentUICulture;
// Fetch the localized text for the given key from the resource
string localizedText = resourceManager.GetString(key, currentCulture);
// If the resource for the given key is not found in the culture,
// explicitly load the default resource (English) using CultureInfo.InvariantCulture
if (localizedText == null)
{
localizedText = resourceManager.GetString(key, CultureInfo.InvariantCulture);
}
// If the resource is still not found, return the key itself as a fallback
return localizedText ?? key;
}
catch (MissingManifestResourceException ex)
{
// Handle the exception if the resource file is not found
// Log the exception
Console.WriteLine($"Resource file not found. Exception: {ex.Message}");
return key; // Return the key itself as a fallback
}
}
I then repeat the same methods for my other forms. I have included screenshots of the end results. Now, I am updating the datagrid based upon a similar workflow.
I truly hope this helps others. This has been a very confusing journey. Everything mentioned was done in Visual Studio 2022 and for Revit 2022-2024.
Kind regards,
Geoff Jennings