Offering localized experiences within Salesforce is essential for companies. One of the key components of this is translating Salesforce custom fields and labels to ensure that users across different regions have access to the system in their native languages. Salesforce provides translations for the core fields, but companies are left responsible for all custom translations.
Manually translating metadata files can be extremely time-consuming for resources. In this article, we’ll walk through how to leverage AI to automate Salesforce Translation Workbench metadata file translations, from exporting the necessary files from Salesforce to refining the translation process using OpenAI’s GPT technology.
The first step in our journey is to export the Salesforce metadata that needs translated. Salesforce’s Translation Workbench allows you to manage translations for various components like custom fields, labels, and picklist values. First, you must enable your languages, then export your translation file.
Exporting the Translation File:
- Navigate to Setup in Salesforce.
- In the Quick Find box, type “Translation Workbench” and select Export.
- We chose Bilingual as the Export Type option.
- Choose the language you want to translate and click on Export as STF.
- Salesforcde will generate a .stf (Salesforce Translation File), which contains the metadata that requires translation.
This file is what we’ll work with to automate translations. In our example, we are translating English to Spanish.
Step 2: Signing Up for OpenAI’s GPT
To automate the translation process, we use OpenAI’s GPT-3.5-turbo-16k model, which provides a robust language translation capability.
Signing Up
- Visit the OpenAI website.
- Sign up for an API key by creating an account.
- Once signed in, navigate to the API section and generate your API key.
- Store this key securely, as it will be used to authenticate your requests when using the OpenAI API.
- Make sure to fund your API account. An optimized process with approximately 5,000 items to translate may cost less than $10.00 to process one translation file.
Step 3: Initial Server Setup and Script Development
You will need to identify a server on which to run Python and call the OpenAI API. Options include Microsoft Azure and Amazon AWS. We used Amazon AWS Cloud 9 for this project, allowing us to quickly spin up a server running Linux. We uploaded our .stf file directly into the root of the newly created Cloud 9 environment. Make sure to go into bash and install the latest OpenAI package.
Bash install script:
pip install openai
With the server running openai, and your.stf file uploaded to your server along with your OpenAI API key ready, the next step is to create a Python script that can read the Salesforce file and process each line, translating the labels while preserving the key structure.
The Initial Script:
import openai
# Initialize your OpenAI API key
openai.api_key = 'your-api-key-here'
# Function to translate a batch of lines
def translate_batch(lines):
combined_text = "\n".join(lines)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-16k",
messages=[
{"role": "system", "content": "You are an expert translator specializing in Salesforce metadata files."},
{"role": "user", "content": f"Translate the following from English to Spanish:\n\n{combined_text}"}
],
temperature=0.2,
)
return response['choices'][0]['message']['content'].splitlines()
This initial setup allows us to send individual lines to the API for translation. However, we quickly encountered several challenges that required further refinement.
Step 4: Overcoming Key Challenges
As we refined the script, several challenges emerged:
- Handling Large Files Efficiently:
- Initial Issue: Processing each line individually was inefficient and costly.
- Solution: We optimized the script by batching lines together, significantly reducing the number of API calls and associated costs. ChatGPT 4o helped with refining the python scripts. We recommend a batch of 50-100 at a time.
- Dealing with Duplicate Keys and Character Limits:
- Initial Issue: Salesforce has strict rules on duplicate keys and character limits for certain fields.
- Solution: We added validation checks to identify and remove duplicate keys and enforced character limits by truncating labels when necessary.
- Handling Unsupported Salesforce Elements:
- Initial Issue: Salesforce’s Translation Workbench doesn’t support Text Templates in auto launched flows, leading to import errors.
- Solution: We implemented logic to skip these unsupported elements during translation, ensuring a clean and error-free import.
Step 5: Refining the Code
Through several iterations, the code was refined to handle all identified challenges.
The Final Script:
import openai
# Initialize your OpenAI API key
openai.api_key = 'your-api-key-here'
# Function to translate a batch of lines
def translate_batch(lines, source_lang='en', target_lang='es'):
combined_text = "\n".join(lines)
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-16k",
messages=[
{"role": "system", "content": "You are an expert translator specializing in Salesforce metadata files. Your task is to accurately translate only the label portion of each entry from English to Spanish, ensuring the integrity of the format and any HTML tags. The translations should be contextually accurate and appropriate for Salesforce usage."},
{"role": "user", "content": f"Please translate the following text from {source_lang} to {target_lang}. The text is in '#KEY LABEL' format. Only translate the LABEL portion of each line, leaving the KEY portion unchanged. Do not translate any HTML tags or special characters; only translate the content within the tags. Focus on starting below the section labelled '------------------OUTDATED AND UNTRANSLATED-----------------':\n\n{combined_text}"}
],
temperature=0.2,
)
translated_text = response['choices'][0]['message']['content']
return translated_text.splitlines()
# Function to process translations, enforce limits, and skip unsupported keys
def process_translations(translated_lines):
processed_lines = []
seen_keys = set()
for line in translated_lines:
# Skip empty or malformed lines
if '\t' not in line:
print(f"Skipped malformed line: {line}")
continue
key, label = line.split('\t', 1) # Split into key and label, allow label to contain tabs
# Skip unsupported elements in Autolaunched Flows
if "Text Template element in flows of type Autolaunched Flow" in key:
print(f"Skipped unsupported flow element: {key}")
continue
# Check for duplicates
if key in seen_keys:
print(f"Duplicate key found and skipped: {key}")
continue
seen_keys.add(key)
# Handle character limits for different types
if "FieldLabel" in key or "CrtColumn" in key or "WebTab" in key:
if len(label) > 40:
label = label[:40]
print(f"Label truncated to 40 characters: {key}")
elif "RelatedListLabel" in key and len(label) > 80:
label = label[:80]
print(f"Label truncated to 80 characters: {key}")
# Skip invalid keys with mismatched translation types
if "PicklistValue" in key and "LATVIANO" in label:
print(f"Skipped invalid key with mismatched translation type: {key}")
continue
processed_lines.append(f"{key}\t{label}\n")
return processed_lines
# Load the .stf file
with open('/home/ec2-user/environment/Bilingual_es_2024.stf', 'r', encoding='utf-8') as file:
lines = file.readlines()
# Process the lines and translate in batches
translated_lines = []
start_translation = False
batch_size = 50
batch = []
total_lines = len([line for line in lines if '\t' in line and not line.startswith('#')])
processed_lines_count = 0
for line in lines:
if '------------------OUTDATED AND UNTRANSLATED-----------------' in line:
start_translation = True
translated_lines.append(line)
continue
if not start_translation or line.startswith('#') or '\t' not in line:
translated_lines.append(line)
else:
batch.append(line.strip())
if len(batch) >= batch_size:
translated_batch = translate_batch(batch)
processed_lines = process_translations(translated_batch)
translated_lines.extend(processed_lines)
batch = []
processed_lines_count += batch_size
print(f"Processed {min(processed_lines_count, total_lines)} of {total_lines} lines")
# Translate and process any remaining lines in the last batch
if batch:
translated_batch = translate_batch(batch)
processed_lines = process_translations(translated_batch)
translated_lines.extend(processed_lines)
processed_lines_count += len(batch)
print(f"Processed {min(processed_lines_count, total_lines)} of {total_lines} lines")
# Save the translated content
with open('/home/ec2-user/environment/Bilingual_es_2024_TranslatedComplete.stf', 'w', encoding='utf-8') as file:
file.writelines(translated_lines)
print("Translation complete. The file has been saved as Bilingual_es_2024_TranslationComplete.stf.")
Step 6: Importing Back into Salesforce Translation Workbench and Handling Errors:
With the translation complete, import the .stf file back into Salesforce Translation Workbench. While only a few issues were encountered on our final import, we simply removed those few bad lines to get all the translations imported.
Importing the Translation File:
- Navigate to Setup in Salesforce.
- In the Quick Find box, type “Translation Workbench” and select Import.
- Upload the translated final file for import.
- Salesforce will email you if there are any errors.
- Salesforce requires an error-free .stf file for translations to be imported successfully. We had to remove a few lines from our file to get a successful import and navigate around a few errors that the python code couldn’t handle.
Summary
Automating the translation of Salesforce Translation Workbench metadata using AI can significantly streamline the process, saving time and money. By carefully handling the various challenges—such as character limits, duplicate keys, and unsupported elements—we were able to create an efficient and effective solution.
Have any questions how to use AI for Salesforce metadata translations? Please reach out to our Salesforce experts at any time!