Programming

Querying Salesforce profiles in non-English environments

Short guide how to query standard user profiles in multilanguage Salesforce environments

When writing Salesforce tests for testing permissions developers need to create users. Quick search over StackExchange will give you a recipe to select a Standard User profile and then insert a new user with this profile as follows:

Profile stdUserProfile = [SELECT Id FROM Profile WHERE Name='Standard User'];

insert new User(
  ProfileId = stdUserProfile.Id,
  UserName='joe@example.com',
	Alias = 'joe',
	Email='joe@example.com',
	EmailEncodingKey='UTF-8',
	LastName='Test',
	LanguageLocaleKey='en_US',
  LocaleSidKey='en_US',
  TimeZoneSidKey='Asia/Tokyo',
);

If this code ends up in a managed package and gets installed to a customer org by a user who uses Salesforce in a different language then it will fail with System.QueryException: List has no rows for assignment to SObject.

The reason behind this — Salesforce renames some of the profiles to a local language. Standard User becomes 標準ユーザ in Japanese or Utilisateur standard in French.

One way to fix the SOQL query above is to write:

SELECT Id FROM Profile WHERE Name IN ('Standard User', '標準ユーザ', 'Utilisateur standard'and another 32 languages that Salesforce supports )

Then pray that Salesforce does not change the names!

Another method is to look at the Permissions* fields of the profiles and deduct which profile is our demanded Standard User.

I have gone through the list of all standard profiles and derived the least possible combination of the permissions that give you the Standard User profile:

SELECT Id FROM Profile 
	WHERE
		UserType = 'Standard'
		AND PermissionsPrivacyDataAccess = false
		AND PermissionsSubmitMacrosAllowed = true
		AND PermissionsMassInlineEdit = true
	LIMIT 1

For the System Administrator it is even simpler:

SELECT Id FROM Profile
	WHERE
		UserType = 'Standard'
		AND PermissionsPrivacyDataAccess = true
	LIMIT 1

The code above is confirmed to be working for the API version 49.0 (Summer'20).

Now you can query the profiles in any language setting while praying that Salesforce won’t change the permissions on the standard profiles. If only Salesforce could add a DeveloperName for this SObject!

For those wondering how to dump all available permissions for the Profile SObject using anonymous Apex:

Schema.SObjectField[] fields = Schema.describeSObjects(new List<String>{'Profile'})[0].fields.getMap().values();
for(Schema.SObjectField field : fields) System.debug(field);

Then run sfdx force:data:soql:query -q "SELECT <fields from code above> FROM Profile" with a --resultformat=csv to get a CSV file with all profiles and their permissions.