Recently, I wrote about how you can create a macOS app bundle with CMake for a Qt6 application. I omitted the inclusion of translation files, which also required code changes. Well, I figured it out and will briefly explain what I had to do.
In my WorkTracker application, I store the language files in a folder called “l10n” at the project’s root. The first thing to do is instruct CMake to copy the *.qm
files to the app bundle’s “Resource” folder. I have done that before for the app icon, and the process is similar for this kind of file.
set(l10n_files
"${CMAKE_SOURCE_DIR}/l10n/qt_de_DE.qm"
"${CMAKE_SOURCE_DIR}/l10n/de_DE.qm"
"${CMAKE_SOURCE_DIR}/l10n/en_US.qm"
)
set_source_files_properties(${l10n_files} PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources/l10n")
qt_add_executable(WorkTracker MACOSX_BUNDLE
${worktracker_src}
${app_icon_macos}
${l10n_files})
- Define a variable
l10n_files
that contains all the files. - Tell CMake that these files shall end up in the app bundle, in the “Resources/l10n” folder, to be precise.
- Include the files in the call to the
qt_add_executable
function.

Now that the translations are part of the bundle, a minor modification to the code tells the application where to find them. The Qt documentation contains a section about using macOS APIs to determine the bundle location. That is not necessary, though. Qt also has a helpful method to achieve the same goal, QApplication::applicationDirPath()
.
#if defined(Q_OS_LINUX)
// On Linux the translations can be found in /usr/share/worktracker/l10n.
auto l10nPath = "/../share/worktracker/l10n/";
#elif defined (Q_OS_WIN)
// On Windows the translations are in the l10n folder in the exe dir.
auto l10nPath = "/l10n/";
#elif defined (Q_OS_MAC)
// On OS X the data is somewhere in the bundle.
auto l10nPath = "/../Resources/l10n/";
#endif
auto appDir = QApplication::applicationDirPath() + l10nPath;
This method returns the absolute path to the “MacOS” folder inside of the bundle, the folder where the application’s binary is located. Appending /../Resources/l10n/
first navigates up to the “Content” folder (via /..
), which is more or less the bundle’s “root” directory, and from there, goes to “Resources/l10n”. Finally, the language files are loaded like on Windows, and the translation works as expected.
I hope this was helpful because I could not find much information on this specific topic.
Thank you for reading.