建立支援多種語言的解決方案
發行︰ 2017年1月
適用於: Dynamics 365 (online)、Dynamics 365 (on-premises)、Dynamics CRM 2016、Dynamics CRM Online
Microsoft Dynamics 365 (線上和內部部署) 支援多種語言。 如果您需希望您的解決方案為組織安裝,且包含不同的基礎語言或多種語言,請在配置解決方案時考慮此做法。 下表列出使用方案元件的策略,包含支援多種語言的解決方案。
策略 |
解決方案元件類型 |
---|---|
開發人員選項 |
Web 資源 |
內嵌索引標籤 |
應用程式導覽選項 (SiteMap) |
匯出和匯入翻譯 |
屬性 |
在基礎語言字串的本地化 |
合約範本 |
不需要翻譯 |
SDK 訊息處理步驟 |
每種語言的不同元件 |
文章範本 |
使用 XML Web 資源做為語言資源 |
外掛程式組件 |
下列段落提供各種策略的其他詳細資料。
開發人員選項
Web 資源具備一種 LanguageCode 屬性,可以在使用者介面中設定,但是應用程式不會使用此值。 因為 web 資源是 URL 可定址的,通常會使用名稱而非可用於查詢的 web 資源,搭配 LanguageCode 做為準則。 因此,LanguageCode 的值有限制。 在較常見的情況是,必須基於 web 資源顯示的背景下來偵測適當的語言。 若是 Web 資源,內容物件讓您存取 getOrgLcid 和 getUserLcid 函數。 這兩個函數會回傳一個整數值,對應地區設定識別碼 (LCID) 值。您可以在地區設定識別碼 (LCID) 表找到有效的地區設定識別碼值。
針對文字顯示在使用者介面中的 Web 資源,您可以使用您要的方式來管理文字和配置支援使用者的語言喜好設定。 這個特定實作依靠的是 Web 資源類型。
HTML Web 資源
其中一個選項是根據已套用名稱變更個別當地語系化 Web 資源。 例如,您可以有名為 new_/my_solution/1033/content.htm 的 Web 資源支援為另一個名為 new_/my_solution/1041/content.htm 支援日文。 對於需要從右到左邊的顯示的語言,請參閱 如何針對全球化來使用 HTML 標籤,讓文字從右到左顯示。
如果您希望根據使用者的語言動態設定 UI 文字,您可以儲存所有在物件中以指令碼定義的 web 資源檔案中的在地化的字串值。 根據使用者的語言喜好設定,您可以設定在頁面載入時,使用儲存在物件中的字串來設定 UI 文字元素。 下列 JavaScript 程式碼範例顯示設定為在地語系化字串的方法。
var userLcid = 1033;
var localizedStrings = {
ErrorMessage: {
_1033: "There was an error completing this action. Please try again.",
_1041: "このアクションを完了、エラーが発生しました。もう一度実行してください。",
_1031: "Es ist ein Fehler aufgetreten, der Abschluss dieser Aktion. Bitte versuchen Sie es erneut.",
_1036: "Il y avait une erreur complétant cette action. Veuillez essayer à nouveau.",
_1034: "Hubo un error al completar esta acción. Vuelva a intentarlo.",
_1049: "Произошла ошибка, выполнение этого действия. Пожалуйста, попробуйте снова."
},
Welcome: {
_1033: "Welcome",
_1041: "ようこそ",
_1031: "Willkommen",
_1036: "Bienvenue",
_1034: "Bienvenido",
_1049: "Добро пожаловать"
}
};
var LocalizedErrorMessage = localizedStrings.ErrorMessage["_" + userLcid];
var LocalizedWelcomeMessage = localizedStrings.Welcome["_" + userLcid];
Silverlight Web 資源
Silverlight 應用程式可支援當地語系化語言資源。其他資訊:翻譯 Silverlight 型的應用程式。
下列類別讓您根據 Silverlight Web 資源顯示的內容,存取使用者語言喜好設定。 此類別支援英文 (美國)、阿拉伯文、德文、希伯來語和日文。 它需要針對為 Silverlight Web 資源支援的特定語言來修改。
public static class Localization
{
// The locale ID.
public static int LCID { get; set; }
// Create a dictionary of right-to-left language codes (Hebrew and Arabic).
private static Dictionary<int, bool> _rightToLeftLanguages =
new Dictionary<int, bool>
{
{ 1025, true },
{ 1037, true },
};
private static Dictionary<int, String> _lcidToCultureNameMap =
new Dictionary<int, String>
{
{ 1025, "ar-SA" },
{ 1031, "de-DE" },
{ 1033, "en-US" },
{ 1037, "he-IL" },
{ 1041, "ja-JP" }
};
public static void InitializeCulture()
{
// Get the user's LCID from the page's context to determine what language to
// display.
dynamic window = HtmlPage.Window;
//Get the user's language code from the context.
try
{
//If the containing window is a CRM form
LCID = Convert.ToInt32(window.Xrm.Page.context.getUserLcid());
// For testing, comment the line above and uncomment one of the lines below
//representing a user language.
//LCID = 1033; //English
//LCID = 1041; //Japanese
//LCID = 1031; //German
//LCID = 1037; //Hebrew - a right-to-left language.
//LCID = 1025; //Arabic - a right-to-left language.
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
try
{
//If the containing window is a CRM web resource with
//the WebResources/ClientGlobalContext.js.aspx page linked
LCID = Convert.ToInt32(window.GetGlobalContext().getUserLcid());
}
catch (Microsoft.CSharp.RuntimeBinder.RuntimeBinderException)
{
LCID = 1033; //Setting a default for design time when the context
//object is not present and one of the sample languages are not set.
}
}
// Sets the culture of the thread to the appropriate culture, based on what
// LCID was retrieved.
if (_lcidToCultureNameMap.ContainsKey(LCID))
{
var culture = new CultureInfo(_lcidToCultureNameMap[LCID]);
Thread.CurrentThread.CurrentCulture = culture;
Thread.CurrentThread.CurrentUICulture = culture;
}
}
public static FlowDirection GetFlowDirection()
{
if (_rightToLeftLanguages.ContainsKey(LCID))
{
return FlowDirection.RightToLeft;
}
return FlowDirection.LeftToRight;
}
}
如語言需要從右到左邊顯示語言,請參閱 FrameworkElement.FlowDirection 屬性。
XML Web 資源
因為 XML web 資源通常不會為使用者顯示,所以為其他解決方案元件 (如同 使用 XML Web 資源做為語言資源 的描述) 儲存翻譯的字串當成資源可能會很實用。
內嵌索引標籤
使用此銷售技術的每個解決方案元件需要所有包含在解決方案元件中的當地語系化文字。
功能區
安裝語言套件後,應用程式功能區自動顯示所功能區預設文字的當地語系化文字。 系統標籤定義在 ResourceId 屬性值中,僅供內部使用。 當您自己新增文字時,應使用 <LocLabels> (RibbonDiffXml) 元素為您提供支援語言翻譯的文字。其他資訊:在功能區中使用當地語系化的標籤
SiteMap
安裝語言套件後,預設文字會顯示在應用程式導覽列中,自動顯示翻譯文字。 如果要覆寫預設文字或提供您設定的文字,請使用 <Titles> (SiteMap)元素。Titles 元素應包含一個 <Title> (SiteMap) 元素,其中含有解決方案支援的各種語言的翻譯的文字。 如果 Title 元素無法提供使用者慣用語言使用,則與組織基礎語言相應的標題就會顯示。
<SubArea> (SiteMap) 元素允許透過使用者的語言偏好,使用的是 userlcid 參數,如此一來 SubArea.Url 屬性目標的內容就可以由使用者的語言偏好感知,並依此做調整。其他資訊:使用 SiteMap 傳遞參數至 URL
匯出和匯入翻譯
下表中的解決方案元件的當地語系化的標籤可用於本地化匯出。
實體 |
屬性 |
關聯 |
全域選項組 |
實體訊息 |
實體表單 |
實體檢視表 (SavedQuery) |
圖表 |
儀表板 |
翻譯標籤並顯示字串
您只能透過使用基礎語言在應用程式中執行自訂項目。 因此,當您要提供翻譯的索引標籤,並為這些字定項目顯示字串,您必須匯出索引標籤的文字,如此才能針對其他組織使用的語言進行翻譯。 使用下列步驟:
確定您的組織已安裝所有 MUI 套件以及要提供轉換為語言佈建語言。
您建立的解決方案元件與修改。
完成開發您自己的解決方案後,使用「匯出轉換」功能。 這會產生一個包含所有需要翻譯的索引標籤的 Microsoft Office Excel 試算表 (CrmTranslations.xml)。
在試算表中提供了可對應的翻譯。
將翻譯匯回相同的 Microsoft Dynamics 365 組織,使用「匯入翻譯」功能並發行變更。
下次解決方案匯出,會帶有您提供的任何翻譯。
在匯入解決方案時,目標系統中無法使用語言標籤,在登入時會警告您此標籤已捨棄。
如果目標系統的解決方案套件未提供基礎語言索引標籤,則會使用來源的基礎語言的標籤。 例如,如果匯入包含以英文做為基礎語言的英文及法文標籤的解決方案,但是目標系統使用日文為基礎語言,包含日文與法文,則會使用英文而非日文。 基礎語言索引標籤無法為 null 或空白。
正在匯出翻譯
在您輸出翻譯之前,您必須先安裝語言套件與佈建要翻譯的所有語言。 您可以匯出要翻譯在 Web 應用程式或透過使用 ExportTranslationRequest 訊息。 如需詳細資訊,請參閱說明及訓練:匯出自訂實體和欄位文字以供翻譯。
翻譯文字
如果您已在 Excel 開啟 CrmTranslations.xml 檔案,您會看到下表列出的三份工作表。
工作表 |
描述 |
---|---|
資訊 |
顯示有關組織與解決方案的資訊,標籤與字串從解決方案中匯出。 |
顯示字串 |
顯示代表與中繼資料元件關聯的任何訊息文字的字串。 下表包含用於系統功能區元素的錯誤訊息和字串。 |
當地語系化標籤 |
顯示所有中繼資料元件標籤的文字。 |
您可以傳送此檔案給語言專家、翻譯社或在地化公司。 將需要為任何空白儲存格提供翻譯的字串。
注意
對於自訂實體,有些一般與系統實體共用的索引標籤,例如 [建立時間] 或 [建立者]。 因為您已經安裝與佈建語言,但是,如果您匯出預設解決方案的語言,您可以在自訂實體中用翻譯的文字比對部分索引標籤,針對其他實體使用的識別標籤。 這可減少本地化成本並提升一致性。
在工作表文字的翻譯之後,新增 CrmTranslations.xml 和 [Content_Types].xml 檔案至單一壓縮的 .zip 檔案中。 您現在可以匯入這個檔案了。
如果您偏好用程式的方法匯出檔案做為 XML 文件,請參閱 Office 2003 XML 結構描述參照 檔案使用結構的詳細資訊。
匯入翻譯的文字
重要
您可以只把翻譯的文字匯入組織 (先前匯出的組織)。
匯出自訂實體或屬性文字並進行翻譯之後,就可以匯入翻譯的文字字串,使用的是 ImportTranslationRequest 訊息。 匯入檔案必須包含 CrmTranslations.xml 和壓縮檔 [Content_Types].xml 檔案頁面。 如需詳細資訊,請參閱說明及訓練:匯入翻譯實體和欄位文字。
匯入完成的翻譯之後,會將自訂的語文顯示給使用譯文語言的使用者。
注意
Microsoft Dynamics 365 無法匯入長度超過 500 個字元的翻譯文字。 如果翻譯檔案中任何項目的長度超過 500 個字元,則匯入程序失敗。 如果匯入程序失敗,請檢閱檔案中造成失敗的那一行,並減少字元數目,然後試著重新匯入。
因為只有基礎語言才能支援自訂,所以使用 Microsoft Dynamics 365 時可以將基礎語言設定為您的慣用語言。 若要確認翻譯的文字會顯示,您必須變更 Microsoft Dynamics 365 使用者介面的語言喜好設定。 若要執行其他自訂工作,您必須變更回基礎語言。
在基礎語言字串的本地化
某些解決方案元件不支援多種語言。 包括名稱或文字的元件只在特定語言中有意義。 如果您建立特定語言的解決方案,請定義所用組織基礎語言的解決方案元件。
如需支援多種語言,有一種使用基礎語言字串包含在地化的策略。 例如,如果您有名為「朋友」的關聯角色,而您需要備份英文、西班牙文與德文,您可以使用文字「朋友 (Amigo/Freund)」為關聯角色的名稱。 因為文字長度問題,所以有一些關於最多可以支援幾種語言的策略。
某些在此群組中的解決方案元件,僅系統管理員可看到。 因為系統的自訂只能在組織基礎語言中完成,並不需要提供多種語言版本。資訊安全角色和欄位安全性設定檔屬於此群組。
合約範本提供服務合約類型的描述。 以下 [名稱] 以及 [縮寫] 欄位的文字。 您應考慮使用供組織中的所有使用者使用的唯一且適當的名稱和縮寫。
關聯角色依靠選取描述關聯角色的人員類別與名稱。 因為這些可以是相對的簡短,建議您在基礎語言字串包括本地化。
程序 (工作流程) 為事件啟用可正常運作,但他們不需要用翻譯的文字更新記錄。 使用工作流程組件是可能的,因此可套用至翻譯文字的邏輯也可以用與外掛程式組件 (使用 XML Web 資源做為語言資源) 相同的策略。
指定工作流程需要名稱,讓人員可以選取它們。 除了將本地化併入指定工作流程外,另一種策略為建立多個工作流程搭配翻譯的名稱,每個名稱都會呼叫子程序。 不過,所有使用者將看見指定工作流程的完整清單,而不只是使用者偏好的使用者介面語言。
不需要翻譯
SDK 訊息處理步驟和服務端點解決方案元件無法顯示當地化文字給使用者。 如果很重要的,這些元件的名稱和描述對應組織的基礎語言,您可以使用該語言的名稱和描述建立並輸出受管理的解決方案。
每種語言的不同元件
下列解決方案元件都包含相當量要翻譯的文字:
文章範本
電子郵件範本
合併列印範本
報表
對話方塊
針對解決方案元件的類型,建議的策略是建立每種語言的不同元件。 這表示您通常會建立含有您的核心解決方案元件,然後不同受管理的解決方案包含每種語言,這些解決方案元件的基本受管理的解決方案。 在客戶安裝基本解決方案之後,即可安裝他們為組織提供的語言的受管理的解決方案。
不像是程序 (工作流程),您可以建立對話方塊,反映使用者目前的語言喜好設定,而且只顯示對話方塊給該語言的使用者。
建立當地語系化對話方塊
安裝適當的語言套件並佈建語言。
如需詳細資訊,請參閱 TechNet:語言套件安裝指示。
變更您的個人選項來指定您需要對話方塊顯示的使用者介面語言。
前往 [設定] 然後在 [程序中心] 群組,選擇 [程序]。
按一下 [新增] 並在您指定的語言中建立對話方塊。
在建立對話方塊後,請變更您的個人選項,以指定組織的基礎語言。
在使用組織基礎語言時,您可以前往 [設定] 中的 [解決方案] 區域並新增翻譯對話方塊做為一部分的解決方案。
此建立於其他語言中的對話方塊只會顯示 Microsoft Dynamics 365 給該使用該語言的使用者。
使用 XML Web 資源做為語言資源
外掛程式組件解決方案元件可以透過送出 InvalidPluginExecutionException 以及建立和更新記錄傳送訊息給最後使用者。 不同於 Silverlight Web 資源,外掛程式無法使用資源檔案。
當外掛程式要求翻譯文字後,您可以使用 XML Web 資源儲存當地語系化字串,這樣外掛程式就可以在需要時存取它們。 XML 的結構是您的選項,但是您可能想要追蹤由 ASP.NET 資源 (.resx) 檔案使用的結構,來為每個語言建立分別的 XML web 資源。 例如,以下是名為 localizedString.en_US 的 XML Web 資源,會依照由 .resx 檔案使用的模式。
<root>
<data name="ErrorMessage">
<value>There was an error completing this action. Please try again.</value>
</data>
<data name="Welcome">
<value>Welcome</value>
</data>
</root>
下列程式碼顯示當,翻譯的訊息可以如何傳回外掛程式來顯示訊息給使用者。 這是 Account 實體 Delete 事件之前確認階段:
protected void ExecutePreValidateAccountDelete(LocalPluginContext localContext)
{
if (localContext == null)
{
throw new ArgumentNullException("localContext");
}
int OrgLanguage = RetrieveOrganizationBaseLanguageCode(localContext.OrganizationService);
int UserLanguage = RetrieveUserUILanguageCode(localContext.OrganizationService,
localContext.PluginExecutionContext.InitiatingUserId);
String fallBackResourceFile = "";
switch (OrgLanguage)
{
case 1033:
fallBackResourceFile = "new_localizedStrings.en_US";
break;
case 1041:
fallBackResourceFile = "new_localizedStrings.ja_JP";
break;
case 1031:
fallBackResourceFile = "new_localizedStrings.de_DE";
break;
case 1036:
fallBackResourceFile = "new_localizedStrings.fr_FR";
break;
case 1034:
fallBackResourceFile = "new_localizedStrings.es_ES";
break;
case 1049:
fallBackResourceFile = "new_localizedStrings.ru_RU";
break;
default:
fallBackResourceFile = "new_localizedStrings.en_US";
break;
}
String ResourceFile = "";
switch (UserLanguage)
{
case 1033:
ResourceFile = "new_localizedStrings.en_US";
break;
case 1041:
ResourceFile = "new_localizedStrings.ja_JP";
break;
case 1031:
ResourceFile = "new_localizedStrings.de_DE";
break;
case 1036:
ResourceFile = "new_localizedStrings.fr_FR";
break;
case 1034:
ResourceFile = "new_localizedStrings.es_ES";
break;
case 1049:
ResourceFile = "new_localizedStrings.ru_RU";
break;
default:
ResourceFile = fallBackResourceFile;
break;
}
XmlDocument messages = RetrieveXmlWebResourceByName(localContext, ResourceFile);
String message = RetrieveLocalizedStringFromWebResource(localContext, messages, "ErrorMessage");
throw new InvalidPluginExecutionException(message);
}
protected static int RetrieveOrganizationBaseLanguageCode(IOrganizationService service)
{
QueryExpression organizationEntityQuery = new QueryExpression("organization");
organizationEntityQuery.ColumnSet.AddColumn("languagecode");
EntityCollection organizationEntities = service.RetrieveMultiple(organizationEntityQuery);
return (int)organizationEntities[0].Attributes["languagecode"];
}
protected static int RetrieveUserUILanguageCode(IOrganizationService service, Guid userId)
{
QueryExpression userSettingsQuery = new QueryExpression("usersettings");
userSettingsQuery.ColumnSet.AddColumns("uilanguageid", "systemuserid");
userSettingsQuery.Criteria.AddCondition("systemuserid", ConditionOperator.Equal, userId);
EntityCollection userSettings = service.RetrieveMultiple(userSettingsQuery);
if (userSettings.Entities.Count > 0)
{
return (int)userSettings.Entities[0]["uilanguageid"];
}
return 0;
}
protected static XmlDocument RetrieveXmlWebResourceByName(LocalPluginContext context, string webresourceSchemaName)
{
context.TracingService.Trace("Begin:RetrieveXmlWebResourceByName, webresourceSchemaName={0}", webresourceSchemaName);
QueryExpression webresourceQuery = new QueryExpression("webresource");
webresourceQuery.ColumnSet.AddColumn("content");
webresourceQuery.Criteria.AddCondition("name", ConditionOperator.Equal, webresourceSchemaName);
EntityCollection webresources = context.OrganizationService.RetrieveMultiple(webresourceQuery);
context.TracingService.Trace("Webresources Returned from server. Count={0}", webresources.Entities.Count);
if (webresources.Entities.Count > 0)
{
byte[] bytes = Convert.FromBase64String((string)webresources.Entities[0]["content"]);
// The bytes would contain the ByteOrderMask. Encoding.UTF8.GetString() does not remove the BOM.
// Stream Reader auto detects the BOM and removes it on the text
XmlDocument document = new XmlDocument();
document.XmlResolver = null;
using (MemoryStream ms = new MemoryStream(bytes))
{
using (StreamReader sr = new StreamReader(ms))
{
document.Load(sr);
}
}
context.TracingService.Trace("End:RetrieveXmlWebResourceByName , webresourceSchemaName={0}", webresourceSchemaName);
return document;
}
else
{
context.TracingService.Trace("{0} Webresource missing. Reinstall the solution", webresourceSchemaName);
throw new InvalidPluginExecutionException(String.Format("Unable to locate the web resource {0}.", webresourceSchemaName));
return null;
// This line never reached
}
}
protected static string RetrieveLocalizedStringFromWebResource(LocalPluginContext context, XmlDocument resource, string resourceId)
{
XmlNode valueNode = resource.SelectSingleNode(string.Format(CultureInfo.InvariantCulture, "./root/data[@name='{0}']/value", resourceId));
if (valueNode != null)
{
return valueNode.InnerText;
}
else
{
context.TracingService.Trace("No Node Found for {0} ", resourceId);
throw new InvalidPluginExecutionException(String.Format("ResourceID {0} was not found.", resourceId));
}
}
另請參閱
使用解決方案,封裝與發佈擴充功能
解決方案簡介
解決方案開發計劃
解決方案元件相依性追蹤
建立、匯出或匯入未受管理的解決方案
建立、安裝和更新受管理的解決方案
解除安裝或刪除解決方案
解決方案實體
當地語系化產品屬性值
Microsoft Dynamics 365
© 2017 Microsoft. 著作權所有,並保留一切權利。 著作權