複数の言語をサポートするソリューションの作成
公開日: 2016年11月
対象: Dynamics CRM 2015
Microsoft Dynamics CRM 2015 および Microsoft Dynamics CRM Online 2015 更新プログラム は複数言語をサポートしています。 ソリューションを、異なる基本言語を含む組織や複数言語が準備されている組織にインストールする場合は、ソリューションの計画時に検討してください。 次の表は複数の言語がサポートされるソリューションに含めるソリューション コンポーネントで使用する戦略の一覧です。
戦略 |
ソリューション コンポーネントの種類 |
---|---|
開発者のオプション |
Web リソース |
埋め込みラベル |
アプリケーション ナビゲーション (サイト マップ) |
翻訳のエクスポートおよびインポート |
属性 |
基本言語の文字列のローカライズ |
契約テンプレート |
ローカライズが不要な場合 |
SDK メッセージ処理ステップ |
各言語の個別のコンポーネント |
記事テンプレート |
言語リソースとして XML Web リソースを使用する |
プラグイン アセンブリ |
以下のセクションで、各戦略の詳細情報を提供します。
開発者のオプション
Web リソースにはユーザー インターフェイスで設定できる LanguageCode 属性がありますが、この値は、アプリケーションで使用されません。 Web リソースは URL アドレス指定可能なため、通常は、条件として LanguageCode を使用して利用できる Web リソースをクエリすることによるのではなく、Web リソースの名前でアクセスします。 したがって、LanguageCode は上限値です。 より一般的なシナリオは、Web リソースが表示されるコンテキストに基づいて、適切な言語を検出する必要があるシナリオです。 Web リソースでは、コンテキスト オブジェクトで d7d0b052-abca-4f81-9b86-0b9dc5e62a66#BKMK_getOrgLcid および d7d0b052-abca-4f81-9b86-0b9dc5e62a66#BKMK_getUserLcid 機能にアクセスできます。 両方の機能とも、ロケール ID (LCID) 値に対応する整数値を返します。有効なロケール ID 値については、「Locale ID (LCID) Chart (ロケール ID (LCID) の一覧)」で確認することができます。
ユーザー インターフェイスのテキストを表示する Web リソースのため、テキストおよびレイアウトのユーザーの言語設定のサポート方法を管理する方法を使用できます。 具体的な実装は、Web リソースの種類によって異なります。
HTML Web リソース
1 つのオプションで、表示される名前によって異なる、ローカライズされた Web リソースを個別に作成します。 たとえば、英語のサポートのために new_/my_solution/1041/content.htm と呼ばれる Web リソースを用意し、日本語のサポートのために new_/my_solution/1033/content.htm と呼ばれる Web リソースを用意することができます。 右から左に記述する言語については、「方法 : グローバリゼーション用に 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 属性の対象コンテンツをユーザーの言語設定に対応し調整できるよう、ユーザーの言語設定を渡すことができます。詳細:サイト マップを使用して URL にパラメータを渡す
翻訳のエクスポートおよびインポート
次の表のソリューション コンポーネントのローカライズされたラベルは、ローカライズ用にエクスポートできます。
エンティティ |
属性 |
関連付け |
グローバル オプション セット |
エンティティ メッセージ |
エンティティ フォーム |
エンティティ ビュー (SavedQuery) |
グラフ |
ダッシュボード |
ラベルを翻訳して文字列を表示する
カスタマイズは、基本言語を使用したアプリケーションでしか実行できません。 そのため、カスタマイズ用のローカライズされたラベルを用意して文字列を表示する場合は、組織で使用できる他の言語にローカライズできるように、ラベルのテキストをエクスポートする必要があります。 次の手順を実行します。
作業する組織に、翻訳を入力する言語用のすべての MUI パックがインストールされており、言語が用意されていることを確認します。
ソリューションを作成し、コンポーネントを変更します。
ソリューションの開発を終了した後、"翻訳のエクスポート" 機能を使用します。 これにより、翻訳が必要なすべてのラベルを含む Microsoft Office Excel スプレッドシート (CrmTranslations.xml) が生成されます。
スプレッドシートに、対応する翻訳を入力します。
"翻訳のインポート" 機能を使用して翻訳を同じ Microsoft Dynamics 365 組織にインポートし、変更を公開します。
次にソリューションをエクスポートしたときに、設定したすべての翻訳がソリューションに含まれます。
ソリューションのインポート時、ターゲット システムで使用できない言語のラベルは破棄され、警告が記録されます。
ソリューション パッケージでターゲット システムの基本言語のラベルが提供されない場合は、代わりにソースの基本言語のラベルが使用されます。 たとえば、基本言語が英語であるソリューションで、英語とフランス語のラベルを含むソリューションをインポートしたが、ターゲット システムでは基本言語が日本語で、日本語とフランス語が設定されている場合、日本語のラベルの代わりに英語のラベルが使用されます。 基本言語のラベルは、null にすることも空にすることもできません。
翻訳をエクスポートする
翻訳をエクスポートする前に、言語パックをインストールし、ローカライズするすべての言語を準備する必要があります。 翻訳は Web アプリケーションにエクスポートするか、ExportTranslationRequest メッセージを使用してエクスポートできます。 詳細については、「ヘルプとトレーニング: カスタマイズされたエンティティとフィールド テキストの翻訳用のエクスポート」を参照してください。
テキストの翻訳
Excel で CrmTranslations.xml ファイルを開くと、次の表に示す 3 種類のワークシートが表示されます。
ワークシート |
説明 |
---|---|
情報 |
ラベルおよび文字列のエクスポート元の組織とソリューションに関する情報を表示します。 |
表示文字列 |
メタデータ コンポーネントに関連するメッセージのテキストを表す文字列を表示します。 この表に、システム リボン要素に使用するエラー メッセージと文字列を示します。 |
ローカライズされたラベル |
メタデータ コンポーネントのラベルのテキストをすべて表示します。 |
翻訳担当者、翻訳会社、およびローカリゼーション会社にはこのファイルを送信できます。 空のセルにローカライズされた文字列を指定する必要があります。
注意
ユーザー定義エンティティに対しては [作成日] または [作成者] などのシステム エンティティと共有する、共通のラベルがあります。 この言語は既にインストールおよび準備されているため、既定のソリューションの言語をエクスポートすると、一部の、ローカライズされたテキストのあるユーザー定義エンティティのラベルを他のエンティティで使用する同一のラベルと一致させることができます。 これにより、ローカライズにかかるコストを削減し、一貫性を向上できます。
ワークシートのテキストをローカライズ後、CrmTranslations.xml および [Content_Types].xml ファイルを 1 つの .zip 圧縮ファイルに追加します。 これで、このファイルをインポートできます。
XML ドキュメントとしてファイルをプログラムでエクスポートする場合は、これらのファイルが使用するスキーマについての情報を「Office 2003 XML リファレンス スキーマ」で参照してください。
翻訳済みテキストのインポート
重要
エクスポート元と同じ組織にのみ、翻訳済みテキストをインポートして戻すことができます。
カスタマイズされたエンティティまたは属性のテキストをエクスポートし、翻訳したら、ImportTranslationRequest メッセージを使用して、Web アプリケーションに翻訳済みのテキスト文字列をインポートできます。 インポートするファイルは、ルートの CrmTranslations.xml と [Content_Types].xml ファイルを格納する圧縮ファイルである必要があります。 詳細については、「ヘルプとトレーニング: エンティティおよびフィールドの翻訳済みテキストのインポート」を参照してください。
完了した翻訳をインポートした後、カスタマイズされたテキストは、そのテキストの翻訳後の言語を使用するユーザーに表示されます。
注意
Microsoft Dynamics 365 では、500 文字を超える長さの翻訳済みテキストをインポートすることはできません。 翻訳ファイル内の任意のアイテムが 500 文字を超える長さの場合、インポート プロセスは失敗します。 インポート プロセスが失敗した場合は、失敗の原因となったファイル中の行を確認し、文字数を減らしてから再度インポートを試みてください。
カスタマイズは基本言語でのみサポートされるので、言語選択で設定した基本言語で Microsoft Dynamics 365 を操作している可能性があります。 翻訳済みテキストが表示されることを確認するには、Microsoft Dynamics 365 のユーザー インターフェイスの言語選択を変更する必要があります。 カスタマイズに関する追加の作業を行うには、基本言語に戻す必要があります。
基本言語の文字列のローカライズ
一部のソリューション コンポーネントは、複数の言語をサポートしていません。 これらのコンポーネントには、特定の言語で意味のある名前またはテキストのみが含まれます。 特定の言語用のソリューションを作成した後、目的の組織の基本言語に対してこれらのソリューション コンポーネントを定義します。
複数の言語をサポートする必要がある場合は、1 つの方法として、1 つの基本言語にローカライズを含める方法があります。 たとえば "Friend" というつながりロールがあり、英語、スペイン語、ドイツ語をサポートする必要がある場合、“Friend (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));
}
}
関連項目
ソリューションを使用した拡張機能のパッケージ化および配布
ソリューションの概要
ソリューション開発の計画
ソリューション コンポーネントの依存関係の追跡
アンマネージド ソリューションの作成、エクスポート、またはインポート
管理ソリューションの作成、インストール、および更新
ソリューションのインストールまたは削除
ソリューション エンティティ
製品プロパティ値をローカライズする
© 2017 Microsoft. All rights reserved. 著作権