Win32 · MFC · Delphi Reference
Resource-only DLLs: one EXE, one language DLL per language.
A resource-only DLL holds the dialogs, menus, and strings of one language and no code. The application keeps a single EXE and takes its user interface from the DLL that matches the user's language. This page shows how the DLLs are named, how MFC, Delphi, and plain Win32 code load them, and how to build them from a compiled application.
- MFC
MyAppDEU.dll, loaded by MFC- Delphi, C++Builder
MyApp.DEU, loaded by the runtime- Plain Win32
- Any name, loaded by your code
- No DLL for the language
- The EXE's own resources
On this page
Language DLLs or a localized EXE per language?
Both keep the code untouched. A localized EXE is a full copy of the application in each language folder. Resource-only DLLs ship one EXE and add a small DLL for each language next to it.
Resource-only DLLs fit when
- One installer and one EXE should serve every language.
- Languages are added or corrected after release: ship one more DLL, the EXE stays the same.
- The EXE is signed, and you do not want a signed copy for each language.
A localized EXE fits when
- The application has no loading code and is not MFC or Delphi.
- Each language ships as its own package anyway.
- You want each language tested and shipped as one complete file.
Names: the framework decides.
MFC and Delphi look for a fixed name built from the Windows language abbreviation (LOCALE_SABBREVLANGNAME): DEU for German (Germany), FRA for French (France), JPN for Japanese. Plain Win32 code can use any convention, as long as the code and the files agree.
| Framework | German (Germany) | Also tried | Where |
|---|---|---|---|
| MFC | MyAppDEU.dll | MyAppLOC.dll | Folder of MyApp.exe |
| Delphi, C++Builder (VCL) | MyApp.DEU | MyApp.DE | Folder of MyApp.exe |
| Plain Win32 | Your choice, for example lang\de-DE.dll | What your code tries | Where your code looks |
The resource IDs in every language DLL must match the EXE: IDD_ABOUT in MyAppDEU.dll is the same number as in MyApp.exe. Windows' own MUI system uses .mui files in language folders instead; that is a separate mechanism.
Reference
How the DLL gets loaded.
MFC: by CWinApp::InitInstance
At startup, CWinApp::InitInstance goes through the user's UI languages and loads MyAppDEU.dll from the folder of MyApp.exe, then MyAppLOC.dll. Without a matching DLL, the application uses the resources in its own EXE. Your InitInstance must call the base class; to pick a language other than the Windows one, call SetThreadPreferredUILanguages before it.
Delphi and C++Builder: by the runtime
Before your code runs, the runtime looks next to MyApp.exe for MyApp.DEU on a German (Germany) system, then MyApp.DE. A value in the Locales key under HKEY_CURRENT_USER, named after the full path of MyApp.exe, selects another language; the key name depends on the Delphi version (example).
Plain Win32: in your code
Load the DLL as a data file and pass its handle wherever the code passes the module's own handle today: LoadString, DialogBoxParam, LoadMenu, LoadIcon. Fall back to the EXE when the file is missing.
// Pick the file from the user's language or a saved setting
HMODULE ui = LoadLibraryExW(L"MyAppDEU.dll", nullptr,
LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE);
if (!ui) ui = hInstance; // the EXE's own resources
LoadStringW(ui, IDS_SAVED, text, _countof(text));
DialogBoxParamW(ui, MAKEINTRESOURCEW(IDD_ABOUT), hwnd, AboutProc, 0);
Build
Two ways to build resource-only DLLs.
Pick by what you have: translated .rc files, or only the compiled application.
1. From a translated .rc file, by hand
Compile the translated resource script and link it into a DLL without an entry point. Build it for the same platform as the EXE, and repeat for every language and every release:
rc /fo MyAppDEU.res MyAppDEU.rc
link /DLL /NOENTRY /MACHINE:X64 /OUT:MyAppDEU.dll MyAppDEU.res
The work here is keeping each translated .rc in step with the original: every new dialog, control, and string has to reach every language.
2. From the compiled application, with Lingobit Localizer
Add MyApp.exe to a project and set the output type to Resource-Only DLLs (MFC Output for Win32, VCL Binary Output for Delphi). Translate the dialogs, menus, and strings in the visual editor, then run Create Localized Files. Lingobit writes MyAppDEU.dll or MyApp.DEU next to your files; the EXE is not changed and nothing is rebuilt.
- Next release: Scan for Changes shows the new and changed resources; only those need translation.
- Check the layout: Validation reports text cut off in dialogs and duplicate hotkeys.
- See it run: Run Localized Application starts the EXE with the chosen language.
- Existing DLLs: Import Translations from Localized Files reads language DLLs you already have, including ones made by other tools.
The application stays in English.
| Check | Why it matters |
|---|---|
The file is next to MyApp.exe | MFC and Delphi look only in the folder of the EXE, not in a de subfolder. |
| The name has the right abbreviation | MyAppDEU.dll, not MyAppDE.dll or MyApp_de.dll: MFC ignores other names. |
| The language is the user's UI language | A German DLL on an English Windows is not loaded unless the application selects German itself. |
MFC: the base InitInstance is called | The DLL is loaded there; an override that skips it never loads one. |
| The DLL matches the EXE | Built from an older release, it lacks new dialogs and strings, or has different IDs. |
Questions.
Can I add a language without rebuilding the application?
Yes. That is the main reason to use language DLLs: copy MyAppFRA.dll or MyApp.FRA next to the EXE and French users get French.
Can users switch the language while the application runs?
Not with the built-in loading: MFC and Delphi pick the DLL at startup, so a new choice takes effect after a restart. Plain Win32 code that keeps the DLL handle in one place can reload it. For MFC, Multilingual Library adds a language menu.
Do I need the source code?
Not with Lingobit: it reads the resources from the compiled EXE or DLL. The application only needs a way to load the language DLL, which MFC and Delphi have built in.
What about .NET applications?
.NET uses satellite assemblies instead: de\MyApp.resources.dll in a culture folder. See .NET satellite assemblies.
Related paths
- Win32 / MFC — Translate dialogs, menus, and strings in the compiled build.
- Delphi / C++Builder — VCL forms with preview, resource strings, resource modules.
- .NET satellite assemblies — The .NET counterpart of language DLLs.
- Migration — Bring translations from existing language DLLs.