Salesforce Apex获取自定义标签翻译的内容

437 阅读3分钟

有个业务需求:Salesfroce前端需要下载某个对象当前的页面,需要选择指定语言然后下载内容,比如联系人,下载当前联系人的姓名、电话等字段,需要将字段姓名、电话的标签转为指定的语言(注:不包含值)

1.在Salesfroce的设置搜索“翻译”,找到用户界面-翻译工作台-翻译语言设置,可以设置系统支持的语言。

image.png

2.进入自定义标签创建标签,在标签上新增翻译。

image.png

3.通过调用CustomLabelTranslation类的getCustomLabelsByLanguage的方法,返回自定义标签指定的翻译文本。

public without sharing class CustomLabelTranslation {
   private static final String INSTANCE_URL = Url.getSalesforceBaseUrl().toExternalForm();
   private static final String TOOLING_ENDPOINT = '/services/data/v52.0/tooling/query/?q=';
   private static final String TOOLING_LABEL_QUERY = 'Select+id,Name,Value,Language+from+ExternalString';
   private static final String TOOLING_LABEL_TRANSLATION_QUERY = 'Select+Value,Language,ExternalString.Name+from+ExternalStringLocalization';
   private static final String LABEL_WHERE_STRING = '+where+Name+IN+';
   private static final String LABEL_TRANSLATION_WHERE_STRING = '+where+ExternalString.Name+IN+';

   private static List<Records> externalStringRecords = new List<Records>();

   /**
    * @Description: label:标签Name,lan:zh_CN中文简体、en_US英语、de德语、ft法语、ja日语、ko韩语、ru俄语、it意大利语、zh_TW中文繁体
    * @Author: Zaki
    * @CreateDate: 2022-06-08 17:32
    * @UpdateDate: 2022-06-08 17:32
    */
   public static String getCustomLabelsByLanguage(String label, String lan) {
      try {
         Map<String, Map<String, String>> customLabelsByLanguage = CustomLabelTranslation.getCustomLabels(new List<String>{label});
         Map<String, String> labelMap = customLabelsByLanguage.get(lan);
         String re = labelMap.get(label);
         return re;
      } catch (Exception e) {
         return null;
      }
   }

   public static Map<String, Map<String, String>> getCustomLabels(List<String> customLabelNames) {
      String externalStringQuery = getExternalStringQuery(customLabelNames);
      String externalStringLocalizationQuery = getExternalStringLocalizationQuery(customLabelNames);

      makeCustomLabelCallout(externalStringQuery, null);
      makeCustomLabelCallout(externalStringLocalizationQuery, null);
      Map<String, Map<String, String>> languageToLabels = mapCustomLabelsByLanguage(externalStringRecords);
      return languageToLabels;
   }

   public static void makeCustomLabelCallout(String query, String nextQueryUrl) {
      HttpRequest req = new HttpRequest();
      req.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
      req.setHeader('Content-Type', 'application/json');

      if(String.isBlank(nextQueryUrl)) {
         req.setEndpoint(query);
      }
      else{
         req.setEndpoint(INSTANCE_URL + nextQueryUrl);
      }
      req.setMethod('GET');

      Http h = new Http();
      HttpResponse res = h.send(req);

      Response response = (Response) JSON.deserialize(res.getBody(), Response.class);
      externalStringRecords.addAll(response.records);
      if(!response.done){
         makeCustomLabelCallout(null, response.nextRecordsUrl);
      }
   }

   private static String getExternalStringQuery(List<String> customLabelNames){
      if (customLabelNames != null) {
         return INSTANCE_URL + TOOLING_ENDPOINT + TOOLING_LABEL_QUERY + LABEL_WHERE_STRING + formatLabelNamesForQuery(customLabelNames);
      }
      //Retrieve all labels
      return INSTANCE_URL + TOOLING_ENDPOINT + TOOLING_LABEL_QUERY;
   }

   private static String getExternalStringLocalizationQuery(List<String> customLabelNames){
      if (customLabelNames != null) {
         return INSTANCE_URL + TOOLING_ENDPOINT + TOOLING_LABEL_TRANSLATION_QUERY + LABEL_TRANSLATION_WHERE_STRING + formatLabelNamesForQuery(customLabelNames);
      }
      //Retrieve all labels
      return INSTANCE_URL + TOOLING_ENDPOINT + TOOLING_LABEL_TRANSLATION_QUERY;
   }

   private static String formatLabelNamesForQuery(List<String> customLabelNames) {
      String value = '(';
      for (String s : customLabelNames) {
         value += ''' + s + ''' + ',';
      }
      if (String.isNotBlank(value)) {
         value = value.removeEnd(',');
         value += ')';
      }
      return value;
   }

   public static Map<String, Map<String, String>> mapCustomLabelsByLanguage(List<Records> customLabelRecords) {
      Map<String, Map<String, String>> languageToLabelsMap = new Map <String, Map<String, String>>();
      for (Records record : customLabelRecords) {
         if (String.isNotBlank(record.Language)) {
            Map<String, String> customLabels = languageToLabelsMap.get(record.Language);
            if (customLabels == null) customLabels = new Map<String, String>();

            //Handle scenario where custom label name is coming from lookup to ExternalString
            if (record?.ExternalString?.Name != null) {
               customLabels.put(record.ExternalString.Name, record.Value);
            } else {
               customLabels.put(record.Name, record.Value);
            }
            languageToLabelsMap.put(record.Language, customLabels);
         }
      }
      return languageToLabelsMap;
   }

   public class Response {
      public Integer size;
      public Integer totalSize;
      public Boolean done;
      public String queryLocator;
      public String nextRecordsUrl;
      public String entityTypeName;
      public List<Records> records;
   }

   public class Attributes {
      public String type;
      public String url;
   }

   public class ExternalString {
      public Attributes attributes;
      public String Name;
   }

   public class Records {
      public Attributes attributes;
      public String Id;
      public String Name;
      public String Language;
      public String Value;
      public ExternalString ExternalString;
   }
}

调用示例:

CustomLabelTranslation.getCustomLabelsByLanguage('Test', 'en_US');

输出结果:

image.png

其他思路:

1.在翻译工作台-翻译也可以实现对象的字段翻译,同时还可以指定值的翻译,最终的翻译结果,可以在objectTranslations/Contact-en_US.objectTranslation里查看翻译信息,它的内容是存在CustomObjectTranslation对象中的,所以,我们应该也是可以通过调用Salesforce标准接口去获取翻译文本的,但是,我经历一番波折并没有找到相关的接口,所以也就放弃了这种方法。 image.png 2.当我们在翻译工作台对指定标签翻译成指定语言的时候,我们到打开个人设置-我的个人信息-语言与时区-语言,修改成指定语言的时候,我们通过Apex直接输出该对象的字段Label就已经是翻译后的结果了,所以,我们可以通过修改用户的语言,获取到指定的翻译文本后,在将用户的语言修改回来,但是,有个问题就是:用Apex给用户修改语言之后,获取到的文本不一定是翻译后的,因为修改用户语言后,系统将语言翻译过来有延迟,所以需要休眠片刻在获取文本,得到想要的文本后再将用户语言修改回来。这个方法实现如下,但也被我弃用了。

User u = [SELECT LanguageLocaleKey from User where Username='xxx'];
u.LanguageLocaleKey = 'en_US';
update u;
System.debug(YoursObject.getSObjectType().getDescribe().fields.getMap().get('YoursObjectName').getDescribe().getLabel());
u.LanguageLocaleKey = 'zh_CN'; 
update u;