Repository: godotengine/godot
File: editor/export/editor_export_platform_apple_embedded.cpp (C++)

Code before:
	Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");

	const String project_name = get_project_setting(p_preset, "application/config/name");
	const Dictionary appnames = get_project_setting(p_preset, "application/config/name_localized");
	const StringName domain_name = "godot.project_name_localization";
	Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(domain_name);
	TranslationServer::get_singleton()->load_project_translations(domain);
	const HashSet<Ref<Translation>> &translations = domain->get_translations();

	if (!translations.is_empty()) {
		{
			String fname = binary_dir + "/en.lproj";
			tmp_app_path->make_dir_recursive(fname);
			Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
			f->store_line("/* Localized versions of Info.plist keys */");
			f->store_line("");
			f->store_line("CFBundleDisplayName = \"" + project_name + "\";");
			f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
			f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
			f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
		}

		HashSet<String> locales = { "en" };
		for (const Ref<Translation> &translation : translations) {
			const String lang = translation->get_locale();
			if (locales.has(lang)) {
				continue;
			}
			locales.insert(lang);

			String fname = binary_dir + "/" + lang + ".lproj";
			tmp_app_path->make_dir_recursive(fname);
			Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
			f->store_line("/* Localized versions of Info.plist keys */");
			f->store_line("");

			if (appnames.is_empty()) {
				domain->set_locale_override(lang);
				const String &name = domain->translate(project_name, String());
				if (name != project_name) {
					f->store_line("CFBundleDisplayName = \"" + name + "\";");
				}
			} else if (appnames.has(lang)) {
				f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
			}

			if (camera_usage_descriptions.has(lang)) {
				f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
			}
			if (microphone_usage_descriptions.has(lang)) {
				f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");

Review comment (suggestion):
Looks like `get_loaded_locales()` from TranslationDomain could also be kept 🤔

Code after:
	Dictionary photolibrary_usage_descriptions = p_preset->get("privacy/photolibrary_usage_description_localized");

	const String project_name = get_project_setting(p_preset, "application/config/name");
	const Dictionary appnames = get_project_setting(p_preset, "application/config/name_localized");
	const StringName domain_name = "godot.project_name_localization";
	Ref<TranslationDomain> domain = TranslationServer::get_singleton()->get_or_add_domain(domain_name);
	TranslationServer::get_singleton()->load_project_translations(domain);
	const Vector<String> locales = domain->get_loaded_locales();

	if (!locales.is_empty()) {
		{
			String fname = binary_dir + "/en.lproj";
			tmp_app_path->make_dir_recursive(fname);
			Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
			f->store_line("/* Localized versions of Info.plist keys */");
			f->store_line("");
			f->store_line("CFBundleDisplayName = \"" + project_name + "\";");
			f->store_line("NSCameraUsageDescription = \"" + p_preset->get("privacy/camera_usage_description").operator String() + "\";");
			f->store_line("NSMicrophoneUsageDescription = \"" + p_preset->get("privacy/microphone_usage_description").operator String() + "\";");
			f->store_line("NSPhotoLibraryUsageDescription = \"" + p_preset->get("privacy/photolibrary_usage_description").operator String() + "\";");
		}

		for (const String &lang : locales) {
			if (lang == "en") {
				continue;
			}

			String fname = binary_dir + "/" + lang + ".lproj";
			tmp_app_path->make_dir_recursive(fname);
			Ref<FileAccess> f = FileAccess::open(fname + "/InfoPlist.strings", FileAccess::WRITE);
			f->store_line("/* Localized versions of Info.plist keys */");
			f->store_line("");

			if (appnames.is_empty()) {
				domain->set_locale_override(lang);
				const String &name = domain->translate(project_name, String());
				if (name != project_name) {
					f->store_line("CFBundleDisplayName = \"" + name + "\";");
				}
			} else if (appnames.has(lang)) {
				f->store_line("CFBundleDisplayName = \"" + appnames[lang].operator String() + "\";");
			}

			if (camera_usage_descriptions.has(lang)) {
				f->store_line("NSCameraUsageDescription = \"" + camera_usage_descriptions[lang].operator String() + "\";");
			}
			if (microphone_usage_descriptions.has(lang)) {
				f->store_line("NSMicrophoneUsageDescription = \"" + microphone_usage_descriptions[lang].operator String() + "\";");
			}
			if (photolibrary_usage_descriptions.has(lang)) {
				f->store_line("NSPhotoLibraryUsageDescription = \"" + photolibrary_usage_descriptions[lang].operator String() + "\";");