.NETでのローカリゼーションの効果的な戦略[終了]


121

近い将来、すべてのコンテンツの国際的なローカライズを必要とする.NET MVCアプリケーション用のUIを開発しています。私は一般的に.NETに非常に精通していますが、国際的なアクセシビリティにそのような重要な焦点を当てる必要のあるプロジェクトは一度もありませんでした。

投影は最初は英語で行われています。将来ローカライズを実装しやすくするために、この時点でどのような対策を講じる必要がありますか?


2
いい質問です!私は同様の状況に直面しているので、専門家がこれについて議論するのを楽しみにしています。

誰もがリソース管理の良い基準を持っていますか?ローカライズされた値には、文字列だけでなく画像も含まれる場合があります。

1
これはWPF / silverlight UIですか、それともWinformsですか?私の(限られた)経験から、ローカライズのためのWinFormsの経験はWPF / Silverlightよりもはるかに簡単です。
ピート・ステンスネ

1
あなたが代わりにリソースファイルを、データベース中のあなたのローカライズされた文字列を格納してしまう場合は、この議論を見てみたいことがあります。stackoverflow.com/questions/2458615/...

1
@ Pete、@ smartcavemanは、「。NET MVCアプリケーションのUIを開発している」と言っていたので
...-BrunoSalvino

回答:


74

ASP.Net MVCアプリケーションを開発していますか?その他の答えは、デスクトップアプリケーションに固有のようです。一般的なものをキャプチャしてみましょう。

ロケール検出

アプリケーションがユーザーのロケールを正しく検出することは非常に重要です。デスクトップアプリケーションでは、CultureInfo.CurrentCultureは優先フォーマットロケール(数値、日付、通貨などのフォーマットに使用されるべき)を保持しますが、CultureInfo.CurrentUICultureは優先ユーザーインターフェイスロケール(ローカライズされたメッセージの表示に使用されるべき)を保持します。Webアプリケーションの場合、派手なロケール検出ワークフローを実装する(つまり、オンデマンドで言語の変更をサポートする)場合を除き、両方のカルチャをauto(AcceptLanguageヘッダーからロケールを自動的に検出する)に設定する必要があります。

文字列を外部化する

すべての文字列はリソース、つまりResxファイルから取得する必要があります。Winformsアプリでは、フォームのLocalizableプロパティをtrueに設定することで簡単に実現できます。また、モデルから取得した文字列を手動で(残念ながら)外部化する必要があります。また、比較的簡単です。Asp.Netでは、すべてを手動で外部化する必要があります...

レイアウト

文字列の展開を許可する必要があります。Winformsの世界では、より長いテキストに対応するためにレイアウトが自動的に調整されるようにするために使用する必要があるTableLayoutPanelを介して実現できます。ウェブの世界では、あなたは少し運が悪いです。CSSローカリゼーションメカニズム-CSS定義を変更(オーバーライド)する方法を実装する必要がある場合があります。これにより、ローカリゼーション担当者は、オンデマンドでスタイルの問題を修正できます。レンダリングされたページの各HTML要素が一意のIDを持っていることを確認してください-正確に対象を指定できます。

文化固有の問題

西洋文化に特有のグラフィック、色、音の使用は避けてください。本当に必要な場合は、ローカライズの手段を提供してください。方向に敏感なグラフィックスは避けてください(アラビア語やヘブライ語を言うためにローカライズしようとすると問題になるため)。また、全世界が同じ数字を使用していると仮定しないでください(つまり、アラビア語には当てはまりません)。

ToString()およびParse()

サポートされていない限り、ToString()を呼び出すときは、必ず CultureInfo 渡してください。そうすれば、あなたはあなたの意図にコメントしています。例:内部で何らかの数値を使用しており、何らかの理由でそれを文字列に変換する必要がある場合:

int i = 42;
var s = i.ToString(CultureInfo.InvariantCulture);

ユーザーに表示される数値の場合:

var s = i.ToString(CultureInfo.CurrentCulture); // formatting culture used

同じことがParse()、TryParse()、さらにParseExact()にも当てはまります。CultureInfoを適切に使用しないと、いくつかの厄介なバグが発生する可能性があります。これは、Microsoftの貧しい人々が、善意に満ち、CultureInfo.CurrentCultureを既定の1つとして扱うことをお勧めすることを決定したためです(何も渡さない場合に使用されます)-結局、誰かがToString( )ユーザーに表示したいですか?常にそうであるとは限りません-たとえば、アプリケーションのバージョン番号をデータベースに保存してから、バージョンクラスのインスタンスに変換してみてください。幸運を。

日付とタイムゾーン

DateTime を常に UTCで保存およびインスタンス化しください(DateTime.NowではなくDateTime.UtcNowを使用してください)。表示時にローカル形式でローカル時間に変換します:

DateTime now = DateTime.UtcNow;
var s = now.ToLocalTime().ToString(CultureInfo.CurrentCulture);

本文に時間参照を含むメールを送信する必要がある場合は、必ずタイムゾーン情報を含めてください。UTCオフセットと都市のリストの両方を含めてください。

DateTime someDate; // i.e. from database
var formattedDate = String.Format("{0} {1}", 
             someDate.ToLocaleTime().ToString(CultureInfo.CurrentCulture),
             TimeZoneInfo.Local.DisplayName);

複合メッセージ

すでに文字列を連結しないように警告されています。代わりに、おそらく上記のようにString.Format()を使用します。ただし、複合メッセージの使用は最小限に抑える必要があると述べなければなりません。それは、ターゲットの文法規則が非常に一般的に異なるためです。そのため、翻訳者は文を並べ替えるだけでなく(プレースホルダとString.Format()を使用して解決します)、置換されるもの。例を挙げましょう。

// Multiple plural forms
English: 4 viruses found.
Polish: Znaleziono 4 wirusy. **OR** Znaleziono 5 wirusów.

// Conjugation
English: Program encountered incorrect character | Application encountered incorrect character.
Polish: Program napotkał nieznaną literę | Aplikacja napotkała nieznaną literę.

その他の連結の問題

連結は文字列に制限されません。コントロールを一緒にレイアウトすることは避けてください:

[番号付きのテキストボックス]日後にもう一度通知します。

これは次のように再設計する必要があります。この日数でもう一度通知する:[テキストボックス]。

文字エンコードとフォント

Unicode(つまりUTF-8)のテキストは常に保存、転送します。フォントをハードコードしないでください-ローカライズではフォントの変更が必要になる場合があり、デフォルトのフォントフォールバックメカニズムをオフにします(Winformsの場合)。ほとんどのフィールドで「奇妙な」文字(つまりユーザー名)を許可することを忘れないでください。

テスト

おそらく、いわゆる疑似翻訳を実装する必要があります。つまり、たとえばドイツ文化のリソースを作成し、接頭辞と接尾辞を追加して英語の文字列をコピーします。プレースホルダーをラップして、複合文字列を簡単に検出することもできます。擬似翻訳の目的は、ハードコードされた文字列、レイアウトの問題、複合メッセージの過度の使用などのローカライズ可能性の問題を検出することです。


5
複合メッセージについて-複数のフォームを一度実行する必要がありました。私は拡張String.Format:それはこのクールな構文サポートできるように"There {0:was|were} {0} {0:virus|viruses} found."あなたができるように、各言語は、独自のルールをロードすることができ"Znaleziono {0} {0:wirusy|wirusów}." ます。ソースはGitHubの上にあるgithub.com/scottrippey/SmartFormat/wiki
スコットRippey

2
@Scott Rippeyあなたはポーランドの例では、読み込むことに気づいた"Znaleziono 4 wirusy。OR Znaleziono 5wirusówを。" <-ポーランド語は、他の多くの言語と同様に、複数の複数形を持ち、それらを区別する規則も複雑になる可能性があります。ここでは、話せないのでポーランド語を辞めなければなりませんが、私の言語では、101個の複数形は1個のものと同じです。GNU gettextがこの問題にどのように取り組んでいるかをご覧ください
gregopet

2
@gregopet私のポーランド語の例は、私が話さないので不自然でしたが、それはまさにSmartFormatプロジェクトが行うことです。より良い例は次のとおり"{0} {0:plik|pliki|plików}"です。フォーマッタには、3つのフォームのどれを使用するかを決定し、特殊なケースを正しく決定するポーランドのルールがあります。現在、ルールの追加に取り組んでいるので、このgettext記事は非常に役立ちます。ありがとうございます。
スコットリッピー

擬似ローカライズのために、pseudolocalize.com
JerSchneid

74

考慮すべき基本的な事項:

すべての文字列リソースを外部化する

すべてのリソースは、ローカライズのために渡すことができる外部ファイルに含まれている必要があります。これらもローカライズしたい場合は、エラーメッセージを忘れないでください。

文字列の展開に十分なスペースを確保する

一部の言語の文字列は、たとえばギリシャ語のように最大30%長くなる傾向があるため、必要に応じて文字列を拡張できるようにUIを設計してください。フランス語のかなり極端な例を次に示します。

Ok-> Accepter(フランス語-400%拡張)

出発点として何らかの疑似翻訳を行うことをお勧めします(http://en.wikipedia.org/wiki/Pseudolocalization)。または、Google翻訳またはBingを介してリソースを翻訳できます。これにより、実際の翻訳がどのように見えるかがわかります。

画像内のテキストに注意してください

アプリケーションで画像を使用している場合-画像にテキストが含まれていないことを確認してください-これは明らかに翻訳できません。

Windowsフォルダーへのパスをハードコーディングしないでください

明らかですが、私は過去にそれを見てきました。たとえばC:\Program Files、Windowsの一部の国際バージョンで翻訳されています。たとえばC:\Programme、ドイツ語のOS上です。

ロケール固有の用語を使用しない

たとえば、フォームの「高校」を誰かに尋ねた場合、これは西ヨーロッパではほとんど意味がありません。

文字列の連結による文字列の作成を避けます

たとえば、これは無害に見えます。

strWelcome = ReadExternalString("Welcome"); 
strMessage = strWelcome + ", " + UserName;

しかし、たとえば日本語の語順は異なるため、これは意味をなさない可能性があります。

時刻/日付設定

必ずOSから時刻/日付形式を取得してください。


@Jimmy C、言語に依存しない論理的一貫性のために文字列をどのように構築しますか?
-smartcaveman

14
@Smartは「{0}、{1}」などのリソースで何かを行い、それをローカライズするときにstring.formatを使用して、グリーティングとユーザー名を渡します。さらに、「現在の{0}速度は{1} {2}」であり、「Engine」、「50」、および「MPH」を渡すことができ、文を翻訳するときに{ 0}など、その言語で意味のある場所
テイラー

4
良いリストJimmyC。「Windowsフォルダーへのパスをハードコーディングしないでください」は、Windowsパスの文字列連結の代わりに「常にPath.Combineを使用する」ことを思い出しました。

@ジミー-C素晴らしい答え!

1
Environment.GetFolderPathを使用すると、これらのフォルダーの英語名に依存せずに、マイドキュメントなどの一般的なパスへの有効なパスを取得できます。
Crippledsmurf

24

アジア言語の特別な考慮事項

すでにここにあるすべての素晴らしい答えに加えて、アジア言語の注意点がいくつかあります。

異なる長さのテキストに注意してください

中国語、韓国語のテキストは(あなたは通常、同じことを書くことが少ないブロック状の文字を必要とするので)同等の英語テキストよりもはるかに短い傾向にあるので、ページが実際に見えるかもしれ中国語ではなくドイツ語でいっぱい詰まって...あなたは何をする必要がありますここで見栄えをよくするために、ここでいくつかの動的なサイズ設定を行います。

ただし、日本語のテキストは通常​​、文字数の点で同等の英語のテキストよりもはるかに長くなる傾向があります。

ベースラインレイアウトと「スライドした」外観に注意してください

通常、アジア文字はベースライン上に配置され、ディセンダーは含まれません(つまり、y、g、q、jなどの下部)。テキストはアジア言語のみであるため(つまり、西洋のアルファベットはありません)、テキストは上にシフトされたように見えます。

数値のフォーマットとローカライズされた数値単位

数値の書式設定を異なる方法で処理します。アジアのさまざまな国では、数字のフォーマット方法が異なります。通貨についても同じです。たとえば、東アジアでは、10,000(wan)が一般的な単位です。インドでは、100,000(lakhs)が一般的です。

現地通貨

一部の国の通貨には多くのゼロがあり、小数点がない(たとえば、日本、インドネシア、イタリア)が、他の通貨には小数点以下2桁まであります。

異なる語順に注意してください

語順は常に同じとは限りません。文字列が異なるデータの組み合わせに由来する場合、単語の順序をハードコーディングする代わりに、文字列の書式設定で{0}、{1}などを使用するのが最善です。

ロケール固有の並べ替えを使用する

ソートは言語ごとおよびロケールごとに異なります。常にO / Sのロケール固有のソートに依存する必要があります。

全角/半角文字には非常に注意してください

「全角」と「半角」の文字の違いに注意してください。ブラケット、句読点などには、標準のASCIIとは異なる「全角」バージョンを含めることができます。これらの文字に基づいて検索または文字列分割を行う場合、最初にすべての全角記号を半角相当に変換する必要があります。

ピリオドはドットではありません...カンマはカンマではありません...

データ入力の落とし穴に注意してください。たとえば、中国語では、ピリオドはドット「。」ではありません。カンマは「、」ではなく全角です。データ入力を行うユーザーが誤ってアジア言語のIMEを有効にする可能性がある場合は、西洋の句読点を検索しようとしないでください。

電話番号

電話番号のフォーマットには何も想定しないでください。市外局番などが常にあるわけではなく、別の形式にすることもできます。通常、国ごとにフォーマット文字列があります。

仮定しないでください人しかいないのでしょう1つの携帯電話番号、または1つのそれはアジアでこの方法ではありませんファックス番号などを。

住所-思っているよりも密度が高い

アドレスについては、何も想定しないでください。郵便番号が常にあるとは限りません。郵便番号は必ずしも数字であるとは限りません。国には州/州がない場合があります。国はただの大都市(シンガポールなど)かもしれません。特定のアジア諸国では、家の最小単位は「部屋X、ユニットY、セクションZ、フロアA、ブロックB、グループC、エステートD」です。一般に、アドレスで許可されるフィールドの数と文字の数は非常に自由です。

あいさつ文

あなたはおそらく、セックスのために「M」と「F」を使用して安全だが、礼拝だけなど氏、夫人に限定されるものではない-私たちはそうではありませんそれはまだ奇妙な...


1
最後の段落で私は微笑んだ。
BoltClock

ああ、私たち(i18nの人たち)はまだ開始していませんでした...表面を削ることしかできませんでした:) GB18030サポートのような特定の問題について話す場合、私たちの投稿は長すぎて処理できません:)ありがとうとにかくあなたのメモのために、私はかなりの数のアイテムを逃しました。
パウェウダイダ

最後のことについて、私はイギリスが性別として「その他」を正式に受け入れたと信じています。トランスジェンダーを考える。
バートフリーデリ

11

基本的な手順の一部は、画面に表示される文字列がコード内のリテラルではないことを確認することです。Winformsを実行している場合、各フォームにはUIリソースがあります。ダイアログ、レポートなどの場合は、プロジェクトリソースファイルを使用してください。

したがって、コードで「アップロードに失敗しました」の代わりに、Resources.UploadFailedのようなものがあるかもしれません

この方法で、使用する言語ごとに新しいリソースファイルを作成できます(そして.Netがこれを支援します)。また、各ファイルにローカライズされた文字列があります。

編集 UIを実行しているときに言及するのを忘れましたが、そこに物を詰め込まないようにしてください。ローカライズする言語によっては、不動産が問題になる場合があります。私は、文字列の成長の最大の攻撃者としてドイツ語とポルトガル語を使用するプロジェクトに取り組みました。英語で問題のない文字列を注意深くしなければ、フランス語とイタリア語はドイツ語で爆発します。


1
私のL10nの経験から、ロシアは最悪のシナリオです。ただし、TableLayoutPanelsの適切なユーザーがいるWinformsでは、文字列の成長を適切に処理できます。
パウェウダイダ

ええ、私の経験は英語、ドイツ語、ポルトガル語、イタリア語、フランス語、スペイン語、日本語の7言語に限定されていました。しかし、ロシア語には多くの接尾辞と接頭辞が付いている傾向があるため、ロシア人が悪いことがわかります
-taylonr

9

アセンブリでFXCopまたはVisual Studio Code Analysis(まったく同じ)を実行することをお勧めします。

これらは、次のような適切なカルチャ指向のオーバーロードを使用しない.NETコードの検出に適しています。CA1305:IFormatProviderを指定します。

これらのツールは、通常コード内の無数の問題を検出するため、イライラさせられますが、それでも、各ルールに従わなくても、多くを学ぶ必要があります。


これはデフォルトですか、それともグローバリゼーション固有のルールを検索するために設定を指定する必要がありますか?
-smartcaveman

@smartcaveman-これはデフォルトです(実際、これらのツールには多くのデフォルトルールがあると思う人もいます:
サイモン

7

リソースを読み込む特定の方法に加えて、最初に擬似ローカライズバージョンでテストすることを確認します。そうしないと、最後まで国際化の考慮事項が省略された場所に気付かないでしょう。


擬似ローカライズするための迅速で簡単な方法として、pseudolocalize.comで無料のオンラインツールを構築しました
JerSchneid

6

他のすべての有用なヒントに加えて、不足しているものを次に示します。

一部の国では複数の言語を使用していることを考慮してください。たとえば、カナダでは、ユーザーは英語とフランス語を簡単に切り替えることができると期待しています。

ユーザーに1文字の回答を期待する質問をする場合、ユーザーが「Y」キーを押して「はい」と言うことを期待しないでください。

ストアドプロシージャでは、SQL DBの日付がUSA形式であることに注意してください

DBにテキスト文字列を配置すると、後で再展開せずに言語を追加できます。

書かれたテキストファイルを翻訳のために送信するときは、翻訳者が正しい単語を選択できるように、常にコンテキストの説明を含めてください。たとえば、コンテキストなしで、「pitch:」を音やサッカーをする場所に関係するものに変換できます

住所ラベルは常に変換する必要があります。カナダの州、アメリカの州、イギリスの郡


5

あなたが考慮する必要があります:

  1. 多言語のルーティング

  2. すべてのハードコード文字列をリソースファイルに移動する

プロパティの例:

型:

[Display(Name = <Resource for display name>.<field for this property>)]
[Required(ErrorMessage = <Resource for error message>.<field for this validate message>)]
public string TestProperty { get; set; }

見る:

@Html.LabelFor(m=>m.TestProperty)
@Html.EditorFor(m => m.TestProperty)
@Html.ValidationMessageFor(m => m.TestProperty)

5

これは、残りの回答で言及されていないものです。

アプリケーションの複雑さとそのローカリゼーションに応じて、代替リソースプロバイダーを実装し、ローカライズされたリソースをデータベースに保持することを強くお勧めします。デフォルトのASP.NETローカライズスキームでは、すべてのリソースがRESXファイルに保持されます。

  1. Visual Studioで編集するのは苦痛です
  2. アプリケーションのコンパイル/出荷/実行後に、ローカライズされたリソースの配布と管理を制限します。

可能なユースケースとして、アプリケーションの言語パックを提供し、UIを介して言語をインポートおよびエクスポートする機能を検討してください。ここでは、RESXファイルは役に立ちません。

このようなシナリオでは、代替リソースプロバイダーが非常に役立ちます。実装方法の詳細については、こちらを参照してください。もちろん、これはエンタープライズアプリケーションで一般的に見られるまれなケースですが、依然として有効です。


1
これらのすばらしい答えの答えを見て時間を割いていただき、それでも何か新しくて役に立つものを提供してくれてありがとう。
-smartcaveman

+1; Asp.NETで大規模なWebアプリケーションを構築し、データベースを介して翻訳を行うことになりました。多くの場合、新しい機能が追加されましたが、当社の翻訳者は特定の用語の専門家ではなかったため、「なぜXに単語Yを使用しているのが明らかに間違っているのですか?」
-gregopet

3

最も重要なことは、さまざまな言語でコンテンツを管理することです。私はいくつかのウェブサイトを自分で開発しましたが、さまざまな言語でコンテンツを管理することが最大の課題です。

データベースを使用してリソース/コンテンツを保存しています。これにより、必要な言語サポートを柔軟に追加できます。特定の言語のリソースが見つからない場合、英語にフォールバックするロジックを実装しました。

後でトランスレーターを使用して、英語の値を任意の言語に変換できます。


2

国際化で考慮すべき事項の要約:

  • すべての情報は国際化する必要があります。グラフィックには、国際化する情報が含まれている可能性があることを考慮してください。

  • 問題を引き起こす可能性があるため、言語に応じてフィールドまたは文字列のサイズ。

  • 単語の順序は、使用している言語によって異なるため、ある言語の順序は別の言語の順序と同じになります。

  • 日付の形式が言語ごとに変わることを考慮する必要があります


1

やるトルコ試験

ソフトウェアの国際化は、最高の状況では困難ですが、国際化の問題の議論で特定の国がどれほど頻繁に登場するかは常に驚きました:トルコ ...

ローカリゼーションや国際化について気にする場合は、できるだけ早くトルコ語ロケールでコードを実行してください。これは、ほとんどの(ただし、すべてではありません)カルチャとロケールで実行されるコードの強力な先駆者です。

サイト/プログラムがトルコ語クライアントで正常に動作する場合、他のほとんどのプラットフォームで確実に実行できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.