Code Samples for Businesses, Schools & Developers

First Published 23 Sept 2026



Language settings are normally changed from the Options menu:

Language Options
However, many developers need to test applications in different languages before deployment. The ability to change language within the application can be a useful time saver.

This can be done by editing the language settings stored in the registry at: HKEY_CURRENT_USER\SOFTWARE\Microsoft\Office\16.0\Common\LanguageResources

Registry Language Resources
As with changes made in the Options menu, Access needs to be restarted for the changes to take effect.



Change the Office language using VBA

The example app contains a form and all code needed to change the Office language to any of the languages already installed.

The form shows the current Office language together with a combo box with all the installed Office languages:

Change Language Form
In fact, the combo box is used to change the Office locale which consists of both a language and country/region.
The locale names use the format en-GB, fr-FR etc., where the language is in lower case and the country/region is in upper case.


For display purposes, these are written as e.g. English (United Kingdom), French (France) etc.
In certain cases, the sort order is also specified. For example, es-ES is displayed as Spanish (Spain, International Sort).

Most of the code used by the form is in the standard module, modOfficeLang.
The GetLocaleInfoEx API is used together with a locale type constant to obtain the locale display names with a helper function, LocaleNameToDisplayName.

' Windows API declaration for GetLocaleInfoEx
' Retrieves information about a locale using its name (e.g., "en-US")
Private Declare PtrSafe Function GetLocaleInfoEx Lib "kernel32" _
(ByVal lpLocaleName As LongPtr, _
ByVal lcType As Long, _
ByVal lpLCData As LongPtr, _
ByVal cchData As Long) As Long

' Constant for LCType
Private Const LOCALE_SLOCALIZEDDISPLAYNAME As Long = &H2

' Helper function to convert locale name to display name
Public Function LocaleNameToDisplayName(ByVal localename As String) As String
Dim buffer As String
Dim length As Long

' Allocate buffer for result
buffer = String$(256, vbNullChar)

' Call API
length = GetLocaleInfoEx(StrPtr(localename), _
LOCALE_SLOCALIZEDDISPLAYNAME, _
StrPtr(buffer), _
Len(buffer))

If length > 0 Then
' Trim null characters
LocaleNameToDisplayName = Left$(buffer, length - 1)
Else
LocaleNameToDisplayName = vbNullString
End If
End Function


The current Office language is obtained by reading the UILanguageTag key value from the registry then converting to the display name:

Public Function GetCurrentOfficeDisplayName() As String

On Error GoTo Err_Handler

Dim wsh As Object
Dim regPath As String
Dim langTag As String

regPath = "HKCU\Software\Microsoft\Office\16.0\Common\LanguageResources\"
Set wsh = CreateObject("WScript.Shell")

' Get the UI Display locale name (e.g. "en-US", "es-ES", "fr-FR")
langTag = wsh.RegRead(regPath & "UILanguageTag")

'convert to display name
GetCurrentOfficeDisplayName = LocaleNameToDisplayName(langTag)

Exit_Handler:
Set wsh = Nothing
Exit Function

Err_Handler:
Set wsh = Nothing
MsgBox "Error getting Office display name: " & Err.Description, vbCritical, "Language Error"
Resume Exit_Handler

End Function


The list of installed languages shown in the combo box is obtained by first reading the UISnapshotLanguages key from the registry e.g. de-de;en-gb;en-us;es-es;fr-fr.
Where this key is not yet populated, the
UIFallbackLanguages key is used instead.

Public Function GetInstalledOfficeLanguages() As String
On Error GoTo ErrHandler

Dim wsh As Object
Dim regPath As String
Dim snapshot As String
Dim arrLangs() As String
Dim i As Long
Dim langTag As String, displayName As String
Dim rowSourceStr As String

regPath = "HKCU\Software\Microsoft\Office\16.0\Common\LanguageResources\"
Set wsh = CreateObject("WScript.Shell")

' 1. Read the snapshot of UI languages actually installed on this PC
On Error Resume Next
snapshot = wsh.RegRead(regPath & "UISnapshotLanguages")
On Error GoTo ErrHandler

' Fallback to UIFallbackLanguages if UISnapshotLanguages is not yet written
If Len(Trim(snapshot)) = 0 Then
On Error Resume Next
snapshot = wsh.RegRead(regPath & "UIFallbackLanguages")
On Error GoTo ErrHandler
End If

' Debug.Print snapshot

Set wsh = Nothing

If Len(Trim(snapshot)) = 0 Then
GetInstalledOfficeLanguages = ""
Exit Function
End If

' 2. Split the list (e.g. "ca-es;en-gb;en-us;es-es")
arrLangs = Split(snapshot, ";")

' 3. Build the Value List: "Tag";"Friendly Name";
For i = LBound(arrLangs) To UBound(arrLangs)
langTag = Trim(arrLangs(i))
displayName = LocaleNameToDisplayName(langTag)

' Ignore empty entries and the internal "x-none" entry
If Len(langTag) > 0 And LCase(langTag) <> "x-none" Then
langTag = FormatLangTag(langTag)
rowSourceStr = rowSourceStr & langTag & ";" & displayName & ";"
End If
Next i

' Replace any commas as this messes up the display
rowSourceStr = Replace(rowSourceStr, ",", ":")

' Remove the trailing semicolon
If Right(rowSourceStr, 1) = ";" Then
rowSourceStr = Left(rowSourceStr, Len(rowSourceStr) - 1)
End If

' Debug.Print rowSourceStr

GetInstalledOfficeLanguages = rowSourceStr
Exit Function

ErrHandler:
'Handle error if langTag is empty or langTag=x-none
If Err = -2147221502 Then Resume Next

Set wsh = Nothing
GetInstalledOfficeLanguages = ""

End Function

' Standardizes tags to standard casing (e.g., "ca-es" -> "ca-ES")
Private Function FormatLangTag(ByVal tag As String) As String
Dim parts() As String
parts = Split(tag, "-")
If UBound(parts) = 1 Then
FormatLangTag = LCase(parts(0)) & "-" & UCase(parts(1))
Else
FormatLangTag = tag
End If
End Function


The list is then split into language tags (LangTag) which are used to build a value list for the combo box, ignoring any empty values.
The LangTag values are used as the hidden bound column. The display name for each locale is also obtained using the same function as before and used for the visible column in the combo box.
For some unknown reason, the registry array doesn't use the standard format so the
FormatLangTag function also handles this.

The combo box AfterUpdate event handles the following steps:
•   checks whether the selected language is different to the current language
•   asks the user to confirm they wish to proceed
•   runs code to switch the language values in the registry and restarts the database

Private Sub cboLanguage_AfterUpdate()

If Replace(Me.cboLanguage.Column(1), ":", ",") = Me.txtCurrentLang Then
FormattedMsgBox "The Office language has not been changed", vbInformation, "Language not changed", "", 0
Me.cboLanguage = ""
Exit Sub
End If

If Not IsNull(Me.cboLanguage) Then
If FormattedMsgBox("Are you SURE you want to change the Office language to " & Me.cboLanguage.Column(1) & "?" & _
"@Click OK to confirm." & vbCrLf & "Access will restart automatically. @", _
vbExclamation + vbOKCancel + vbDefaultButton2, "Change Office Language?", "", 0) = vbOK Then

Call SwitchLanguage(Me.cboLanguage)
RestartCurrentDatabase
Else
Me.cboLanguage = ""
End If
End If

End Sub


The SwitchLanguage code updates a number of registry keys:

Sub SwitchLanguage(newLanguage As String)
SetOffice365Language (newLanguage)
End Sub

Public Function SetOffice365Language(ByVal langTag As String, Optional ByVal setHelp As Boolean = True) As Boolean

On Error GoTo Err_Handler

Dim wsh As Object
Dim regPath As String
Dim currentFallback As String
Dim newFallback As String

regPath = "HKCU\Software\Microsoft\Office\16.0\Common\LanguageResources\"
Set wsh = CreateObject("WScript.Shell")

' 1. Set the UI Display Language Tag (e.g. "en-US", "es-ES", "ca-ES")
wsh.RegWrite regPath & "UILanguageTag", langTag, "REG_SZ"

' 2. Ensure Office does NOT follow the Windows system display language
wsh.RegWrite regPath & "FollowSystemUILanguage", 0, "REG_DWORD"

' 3. Update UIFallbackLanguages so the new language is at the top of the priority list
On Error Resume Next
currentFallback = wsh.RegRead(regPath & "UIFallbackLanguages")

On Error GoTo Err_Handler

If Len(currentFallback) > 0 Then
' Remove the target tag if already present in the list, then prepend it
currentFallback = Replace(currentFallback, langTag & ";", "")
currentFallback = Replace(currentFallback, ";" & langTag, "")
newFallback = langTag & ";" & currentFallback
Else
newFallback = langTag & ";x-none"
End If
wsh.RegWrite regPath & "UIFallbackLanguages", newFallback, "REG_SZ"

' 4. Optionally set Help and Editing language tags
If setHelp Then
wsh.RegWrite regPath & "HelpLanguageTag", langTag, "REG_SZ"
End If

wsh.RegWrite regPath & "PreferredEditingLanguage", langTag, "REG_SZ"

Exit_Handler:
Set wsh = Nothing
SetOffice365Language = True
Exit Function

Err_Handler:
Set wsh = Nothing
SetOffice365Language = False
MsgBox "Error setting Microsoft 365 language: " & Err.Description, vbCritical, "Language Error"
Resume Exit_Handler
End Function


The RestartCurrentDatabase code is as follows:

Public Sub RestartCurrentDatabase()
Dim strPath As String
Dim strAccessExe As String
Dim strCommand As String

' 1. If you want to ensure the current active record is saved before restarting:
' On Error Resume Next
' If Screen.ActiveForm.Dirty Then Screen.ActiveForm.Dirty = False
' On Error GoTo 0

' 2. Get current database full path
strPath = Application.CurrentProject.FullName

' 3. Dynamically retrieve the Access installation path using SysCmd
strAccessExe = SysCmd(acSysCmdAccessDir) & "MSACCESS.EXE"

' 4. Build shell execution string with a 1-second delay to release locks
strCommand = "cmd.exe /c timeout /t 1 /nobreak >nul & """ & strAccessExe & """ """ & strPath & """"

' 5. Spawn background shell process
Shell strCommand, vbHide

' 6. Quit current instance safely
Application.Quit acQuitSaveAll
End Sub


As far as the end user is concerned, the whole process is both seamless and almost instantaneous.


Acknowledgements

Once again, I am very grateful to my colleague, Xevi Batlle, whose idea this was. The core code was significantly based on Google Gemini API with further changes made by me.

Download

Click to download: Change Office Language v1.21      (ACCDB file - approx 0.5 MB (zipped)

As is the case for all files downloaded from the internet, first unblock the downloaded file, unzip then save to a trusted location.
For more details, see my article: Unblock downloaded files by removing the Mark of the Web



Feedback

Please use the Email button in the contact form below to let me know whether you found this article useful or if you have any questions.

Please also consider making a donation towards the costs of maintaining this website. Thank you


Colin Riddington Mendip Data Systems Last Updated 23 Sept 2026




Return to Code Samples Page




Return to Top