Office add-in localization: ribbon and commandbar controls, task panes etc.
To localize your COM add-in, you need to know the language settings of the Office application (host application) that the add-in is currently loaded in. This is possible through the Application.LanguageSettings property provided by every Office application. This property returns a COM class (of the LanguageSettings type) which provides the LanguageID property (function in C#). LanguageID returns an integer value which is the language id of the Office application. Every language id (also known as Locale ID or LCID) is listed at https://www.microsoft.com/globaldev/reference/lcid-all.mspx. In a minute I will show you what events to use and how to get access to the host application object. You will also find some VB.NET and Delphi code samples of localizing your Add-in Express based COM add-ins.
Localizing command bar controls
Pay attention to the AddinInitialize event of the add-in module (OnAddInInitialize in the VCL edition). Its event handler is the best place to check the localization of the Office application and modify all user-visible properties of your command bar controls. Note that this event fires before any custom command bar is added to the command bar system of the host application.
When localizing command bar controls in Add-in Express, make a clear distinction between temporary and non-temporary (permanent) controls. Temporary command bar controls are created every time the add-in starts and are removed when the host application closes or the add-in is checked off in the COM Add-ins dialog. In the following code, it is assumed that AdxCommandBarButton1 is a temporary command bar button. That is, its Temporary property is set to true.
Private Sub AddinModule_AddinInitialize(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.AddinInitialize
Dim LCID As Integer
LCID = Me.HostApplication.LanguageSettings. _
LanguageID(Office.MsoAppLanguageID.msoLanguageIDUI)
Select Case LCID
Case 1033 'English
AdxCommandBarButton1.Caption = "English Caption"
AdxCommandBarButton1.TooltipText = "English Hint"
AdxCommandBarButton1.DescriptionText = "English Description"
Case 1036 'French
...
Case 1031 'German
...
Case 1040 'Italian
...
Case Else ' isn't supported - use English
...
End Select
End Sub
See how to implement the same approach in VCL (Delphi):
procedure TAddInModule.adxCOMAddInModuleAddInInitialize (Sender: TObject);
begin
case HostApp.LanguageSettings.LanguageID[msoLanguageIDUI] of
1033: begin // English
CommandBar1.Controls[0].AsButton.Caption :=
'English Caption';
CommandBar1.Controls[0].AsButton.TooltipText :=
'English Hint';
CommandBar1.Controls[0].AsButton.DescriptionText :=
'English Description';
end;
1036: begin // French
...
end;
1031: begin // German
...
end;
1040: begin // Italian
...
end;
else begin // not supported - use English
...
end;
end;
Non-temporary controls are created at the first start of the add-in. They are removed when you uninstall the add-in or uncheck it in the COM Add-ins dialog in the Office application. So, if AdxCommandBarButton2 has the Temporary property set to false, the following code should be used:
Private Sub AddinModule_AddinInitialize(ByVal sender As Object, ByVal e As System.EventArgs) _
Handles Me.AddinInitialize
If Me.StartMode = AddinExpress.MSO.ADXStartMode.smFirstStart Then
Dim LCID As Integer
LCID = Me.HostApplication.LanguageSettings. _
LanguageID(Office.MsoAppLanguageID.msoLanguageIDUI)
Select Case LCID
Case 1033 'English
AdxCommandBarButton2.Caption = "English Caption2"
AdxCommandBarButton2.TooltipText = "English Hint2"
AdxCommandBarButton2.DescriptionText = "English Description2"
Case 1036 'French
...
Case 1031 'German
...
Case 1040 'Italian
...
Case Else ' isn't supported - use English
...
End Select
End If
End Sub
Delphi developers write the conditional statement in their own way:
if Self.StartMode = smFirstStart then
When localizing custom .NET controls to be embedded onto Office toolbars, you use one of the approaches above depending on the value of the Temporary property of the corresponding AdvancedCommandBarControl. Note, that you need to localize the control specified in the AdvancedCommandBarControl.Control property.
Localizing Ribbon controls
Office 2007 Ribbon controls are created when the add-in starts. They are removed whenever the add-in unloads. You can localize the controls in the OnRibbonBeforeCreate event of the add-in module.
The only exception to this rule is the dynamicMenu Ribbon control. It provides the OnCreate event that allows populating the component with controls. Naturally, this event is suitable for localizing the controls.
Localizing Office 2007 Task Panes
In .NET, a task pane is a UserControl an instance of which is created whenever the task pane is shown. The instance is removed when the task pane is destroyed (see the OnTaskPaneBeforeDestroy event of the add-in module). To localize the task pane, use the Load event of the UserControl.
In Delphi, a custom Office task pane is a descendant of TActiveForm and you use its OnCreate event. For instance:
procedure TmyPane.ActiveFormCreate(Sender: TObject);
begin
case ADDIN_MODULE_GLOBAL_VARIABLE.HostApp.LanguageSettings.LanguageID[2] of
1033: begin
...
end;
end;
Localizing Outlook property pages
Property pages for the Tools | Options and Folder Properties dialogs are created every time when the dialogs are shown. To localize them, use the Load event of the property page class.
In Delphi, you use the OnCreate event exactly in the same way as shown above.
Localizing Excel task panes and Outlook forms
Add-in Express Excel task panes as well as Outlook forms are created whenever the application-specific task pane or form manager decides that the current context fits the form or pane settings. At this very moment, the constructor of the pane or form is called. That is, the localization code can be safely placed in their constructors. For instance,
Public Sub New()
MyBase.New()
'This call is required by the Windows Form Designer.
InitializeComponent()
'Add any initialization after the InitializeComponent() call
Dim LCID As Integer
LCID = MyOutlookTodayAddin.AddinModule.CurrentInstance. _
HostApplication.LanguageSettings. _
LanguageID(Office.MsoAppLanguageID.msoLanguageIDUI)
Select Case LCID
Case 1033 'English
Me.Text = "English Text"
Case 1036 'French
...
Case 1031 'German
...
Case 1040 'Italian
...
Case Else ' isn't supported - use English
Me.Text = "English Text"
End Select
End Sub
In Add-in Express for Office and CodeGear VCL, you localize your Add-in Express Outlook forms and Excel task panes in the OnCreate event. To retrieve the current LCID, you use an appropriate manager. For instance, in an Add-in Express Outlook form, you do it as follows:
procedure TadxOlForm1.adxOlFormCreate(Sender: TObject);
var
LCID: Integer;
begin
if (self.FormsManager <> nil) then begin
LCID := self.FormsManager.OutlookAppObj.LanguageSettings.LanguageID[2];
end;
end;
When using Add-in Express Excel task pane in Delphi, the same code may look like the following one:
procedure TadxExcelTaskPane1.adxExcelTaskPaneCreate(Sender: TObject);
var
LCID: Integer;
begin
if (self.ExcelTaskPaneManager <> nil) then begin
LCID :=
self.ExcelTaskPaneManager.ExcelAppObj.LanguageSettings.LanguageID[2];
end;
end;
Localizing Outlook Bar shortcuts and shortcut groups
Outlook Bar shortcuts and shortcut groups are created when the add-in starts for the first time. They are removed when the add-in is unchecked in the COM Add-ins dialog or the add-in is uninstalled. To localize them, you can use the same event and the same approach as shown above for the non-temporary command bar controls.
Andrei Smolin
Add-in Express Team Leader
3 Comments
Hello there.. i think its not really good to “hardcode” resource strings in your sourcecode.. better use the Resources derived from your Properties of the Project.
Hello Exceler,
I agree. That post was published when there was no localization support in the .NET edition of Add-in Express. The current version does provide such support and you can localize your add-ins in exactly the same way as your WinForms applications. As to the VCL edition, Delphi doesn’t provide such support and developers have to use the approach described above.
Been looking for a solution like this – thanks for the post (though I know it’s a bit old now)