JavaScript国際化API:Firefoxの実装

国際化とは何ですか?



国際化(国際化、ただし簡潔にするために-i18n 、つまりi、さらに18文字とn、ロシア語では17番目になります)は、異なる言語を話すさまざまな視聴者に簡単に適応できるアプリケーションを作成する方法です。 すべてのユーザーが同じ地域から来て、同じ言語を使用していると仮定すると、間違いを犯すのは非常に簡単です-特にあなたが提案していることについて考えさえしない場合。



function formatDate(d) { //    ,  //.  ? var month = d.getMonth() + 1; var date = d.getDate(); var year = d.getFullYear(); return month + "/" + date + "/" + year; } function formatMoney(amount) { //   –  ,     .  ? return "$" + amount.toFixed(2); } function sortNames(names) { function sortAlphabetically(a, b) { var left = a.toLowerCase(), right = b.toLowerCase(); if (left > right) return 1; if (left === right) return 0; return -1; } //     ,   ? names.sort(sortAlphabetically); }
      
      







歴史的に、JavaScriptでの国際化のサポートは不十分です。 and17をサポートしてフォーマットするには、toLocaleString()メソッドを使用します。 概要行には、特定の言語実装が提供する詳細が含まれています-選択する方法はありません(曜日は曜日に必要ですか?年は重要ですか?)。 すべての詳細が含まれていても、形式は正しくない場合があります-パーセントではなく小数など また、ロケールを選択することはできません。



ソート時には、ロケール(照合)に基づいたテキストのほとんど役に立たない比較が推奨されます。 localeCompare()がありますが、扱いにくいインターフェースを備えているため、ソートには適していません。 そして彼女も、ロケールを選択できません。



これらの制限は非常に複雑であるため、重要なアプリケーションはデータをサーバーに送信して必要な操作を実行し、ロケールに依存して結果を取得します。 金額のフォーマットのみを目的とした、サーバーとのデータの転送。 でたらめ。



i17とJSの新しいAPI



新しいECMAScript国際化APIはJS機能を強化します 日付と数字の書式設定とテキストの並べ替えのために、すべての機能が提供されています。 ロケールは選択できますが、パフォーマンスの目的で、操作の前に毎回ではなく、一度だけ行うことができます。



しかし、このAPIは万能薬ではありませんが、せいぜい「良い試み」です。 正確な出力形式は設定されていません。 実装では、エキゾチックな言語をサポートするか、単にすべてのフォーマットオプションを無視します。 ほとんどの実装は多くのロケールをサポートしますが、保証はありません。



Firefoxの実装は、Unicodeの国際コンポーネント(ICU)ライブラリに依存しています。ICUライブラリ自体は、Unicode Common Locale Data Repository(CLDR)に依存しています。 ただし、ほとんどのICU機能はJavaScriptで記述されています。



国際インターフェイス



i17i APIはIntlオブジェクトに存在します。 Intl.Collat​​or、Intl.DateTimeFormat、およびIntl.NumberFormatの3つのコンストラクターが含まれています。 オブジェクトの作成は次のとおりです。



 var ctor = "Collator"; //     var instance = new Intl[ctor](locales, options);
      
      







localesは、言語タグまたは複数の言語タグを含むオブジェクトを指定する文字列です。 タグ-en(英語)、de-AT(オーストリアのドイツ語)、zh-Hant-TW(伝統的な表記の台湾の中国語)のような行。 タグには、-u-key1-value1-key2-value2 ...という形式でUnicode拡張を含めることができます。各キーは拡張キーです。 異なるデザイナーはこれを異なって解釈します。



options-プロパティがフォーマットとソートを決定するオブジェクト。



Firefoxは、ソート用に400を超えるロケールをサポートし、フォーマット用に600を超えるロケールをサポートしているため、おそらく必要なロケールはそこにあります。



Intlは特定の動作を保証しません。 要求されたロケールがサポートされていない場合、Intlは要求を最適に処理しようとします。 サポートされている場合、その動作は厳密に設定されていません。 特定の設定セットが特定の形式に一致することを想定しないでください。 これはブラウザごとに、またはバージョンごとに異なる場合があります。 書式設定コンポーネントは指定されていません-曜日の短いエントリは、「S」、「Sa」、または「Sat」です。



日付と時刻のフォーマット



設定


 weekday, era "narrow", "short", or "long". (era –   : BC/AD,    ,  ..) month "2-digit", "numeric", "narrow", "short"  "long" year day hour, minute, second "2-digit"  "numeric" timeZoneName "short"  "long" timeZone  "UTC"     UTC.   "CEST"  "America/New_York"   ,      Firefox.
      
      







正確な形式は指定されていませんが、ポイントは「狭い」、「短い」、および「長い」が異なる長さの結果を生成することです-「S」または「Sa」、「土」、および「土曜日」。 結論は、短い形式では土曜日と日曜日があいまいな場合があり、「S」が生成される可能性があります。 「2桁」と「数値」は、2桁またはフルサイズの日付レコードを意味します:「70」と「1970」。



特別な設定もあります:

 hour12 12-  24- .    .       ,    – 0   12pm,      .
      
      







localeMatcher(「ルックアップ」または「ベストフィット」の値)とformatMatcher(「基本」または「ベストフィット」)の2つの特別なプロパティがあり、どちらもデフォルトで「ベストフィット」です。 ロケールとフォーマットの使用方法を定義します。 これらはほとんど使用されず、無視できます。



ロケール関連の設定


DateTimeFormatを使用すると、カスタムカレンダーおよび数値システムを使用した書式設定が可能になります。 これらの詳細は、Unicode拡張機能の設定の言語タグで設定されます。



たとえば、タイのタイ語のタグはth-THです。 Unicode拡張形式は-u-key1-value1-key2-value2 ...です。カレンダーシステムのキーはca、数値はnuです。 タイの数値システムはタイ語の値を持ち、中国語は中国語です。 したがって、日付をフォーマットするには、言語タグの最後にこれらの拡張子を追加します:th-TH-u-ca-chinese-nu-thai。



詳細についてはドキュメントをお読みください。





DateTimeFormatオブジェクトを作成したら、format()関数を使用して使用する必要があります。 これは関連する関数なので、直接呼び出す必要はありません。 タイムスタンプまたは日付オブジェクトが渡されます。



 var msPerDay = 24 * 60 * 60 * 1000; // July 17, 2014 00:00:00 UTC. var july172014 = new Date(msPerDay * (44 * 365 + 11 + 197));
      
      







アメリカ英語の日付をフォーマットしましょう。 2桁の月/日/年、時間/分、タイムゾーンを短い記録に含めます。



 var options = { year: "2-digit", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", timeZoneName: "short" }; var americanDateTime = new Intl.DateTimeFormat("en-US", options).format; print(americanDateTime(july172014)); // 07/16/14, 5:00 PM PDT
      
      







ポルトガルのブラジル人とポルトガルのポルトガル人についても同じことをしましょう。 年の完全な記録と月の名前を使用して、UTCゾーンで形式をより本格的にします。



 var options = { year: "numeric", month: "long", day: "numeric", hour: "2-digit", minute: "2-digit", timeZoneName: "short", timeZone: "UTC" }; var portugueseTime = new Intl.DateTimeFormat(["pt-BR", "pt-PT"], options); // 17 de julho de 2014 00:00 GMT print(portugueseTime.format(july172014));
      
      







最も人気のあるものから最も人気のないものまでをリストした、公用語を使用したUTCのコンパクトなスイスの列車のスケジュール:



 var swissLocales = ["de-CH", "fr-CH", "it-CH", "rm-CH"]; var options = { weekday: "short", hour: "numeric", minute: "numeric", timeZone: "UTC", timeZoneName: "short" }; var swissTime = new Intl.DateTimeFormat(swissLocales, options).format; print(swissTime(july172014)); // Do. 00:00 GMT
      
      







年と年号のある日本のカレンダーを使用して、日本語で日付を表示してみましょう。



 var jpYearEra = new Intl.DateTimeFormat("ja-JP-u-ca-japanese", { year: "numeric", era: "long" }); print(jpYearEra.format(july172014)); // 平成26年
      
      







そして今、タイの数字と中国のカレンダーを使用して、タイの長い日付:



 var options = { year: "numeric", month: "long", day: "numeric" }; var thaiDate = new Intl.DateTimeFormat("th-TH-u-nu-thai-ca-chinese", options); print(thaiDate.format(july172014)); // ๒๐ 6 ๓๑
      
      







数値の書式設定



設定


数値の書式設定の基本設定は次のとおりです。



 style "currency", "percent"  "decimal" ( )    currency    USD  CHF. ,  style = "currency",    . currencyDisplay "code", "symbol"  "name",   "symbol". "code"   , "symbol"    $  £. "name"   . minimumIntegerDigits   1  21 (),   1.     . minimumFractionDigits, maximumFractionDigits   0  20 ().      minimumFractionDigits,    maximumFractionDigits   .   –    ( 2,  0  3)  style = "currency",  0.    0, 3   ,    –    . minimumSignificantDigits, maximumSignificantDigits   1  21 ().  ,       ,       . useGrouping  ,   true.       ( ,      ).
      
      







ロケール設定


NumberFormatは、DateTimeFormatと同様に、nuキーを使用した数値のカスタム書式設定をサポートしています。 たとえば、中国語の言語タグはzh-CNです。 漢数字システムは、hanidecとして定義されています。 このシステムの番号をフォーマットするには、Unicode拡張をタグとして添付します:zh-CN-u-nu-hanidec。



機能の詳細な説明については、ドキュメントを参照してください。





最初に、漢数字入力を使用して中国語の通貨をフォーマットします。 通貨スタイルを選択してから、中国の人民元(元)のコードを使用し、デフォルトで小数部の通常の数でグループ化します。



 var hanDecimalRMBInChina = new Intl.NumberFormat("zh-CN-u-nu-hanidec", { style: "currency", currency: "CNY" }); print(hanDecimalRMBInChina.format(1314.25)); // ¥ 一,三一四.二五
      
      







次に、米国と英国の規則に従ってガソリンの価格をフォーマットします



 var gasPrice = new Intl.NumberFormat("en-US", { style: "currency", currency: "USD", minimumFractionDigits: 3 }); print(gasPrice.format(5.259)); // $5.259
      
      







エジプトでの使用に対するアラブの関心を試してみましょう。 小数点以下が少なくとも2桁あることを確認してください。 番号の順序は、録音が右から左のシステムでは異なる場合があります。



 var arabicPercent = new Intl.NumberFormat("ar-EG", { style: "percent", minimumFractionDigits: 2 }).format; print(arabicPercent(0.438)); // ٤٣٫٨٠٪
      
      







現在は、アフガニスタンで使用されているペルシア語です。 整数部で少なくとも2桁、小数部で2桁以下。



 var persianDecimal = new Intl.NumberFormat("fa-AF", { minimumIntegerDigits: 2, maximumFractionDigits: 2 }); print(persianDecimal.format(3.1416)); // ۰۳٫۱۴
      
      







最後に、バーレーンディナールの数をアラビア語で出力します。 これらのディナールは特徴のない1000分の1に分割されているため、小数点以下3桁が必要です。



 var bahrainiDinars = new Intl.NumberFormat("ar-BH", { style: "currency", currency: "BHD" }); print(bahrainiDinars.format(3.17)); // د.ب.‏ ٣٫١٧٠
      
      







仕分け



設定


 usage "sort"  "search" (  "sort") "base", "accent", "case"  "variant".    ,         ,    .  ""     –     “a” and “ä”   ,    – .   "base"     (    “a”, “A”  “ä”  ). "accent"     ,    (“a”  “A”  ,  “ä”    ). "case"     ,   (“a”  “ä”  ,  “A”  ). , "variant"    .   "sort"    "variant";  –    . numeric  ,         .  ,   numeric   "F-4 Phantom II", "F-14 Tomcat", "F-35 Lightning II";    numeric   "F-14 Tomcat", "F-35 Lightning II", "F-4 Phantom II". caseFirst "upper", "lower"  "false" ( ).      - "upper"     ("B", "a", "c"), "lower"  ("a", "c", "B")  "false"   ("a", "B", "c"). ignorePunctuation  , false  , ,       (  "biweekly"  "bi-weekly"  ).
      
      







ロケール設定


Unicode拡張機能の並べ替え設定はcoとして設定され、アドレス帳(phonebk)、辞書(dict)などの並べ替えの種類を設定します。



さらに、キーknおよびkfは、オプションオブジェクトの数値およびcaseFirstプロパティを複製できます。 しかし、彼らのサポートは保証されていないので、それらを使用しないほうが良いです。





Collat​​orオブジェクトには比較機能があります。 引数xとyを取り、x <yの場合は0未満、x = yの場合は0、x> yの場合は0より大きい数値を返します。



ドイツの名前をソートしてみましょう。 ドイツには、アドレス帳と辞書という2つの異なるソートシーケンスがあります。 1つ目は発音に基づいており、「ä」、「ö」などが「ae」、「oe」などとして表示されます。



 var names = ["Hochberg", "Hönigswald", "Holzman"]; var germanPhonebook = new Intl.Collator("de-DE-u-co-phonebk"); //  ["Hochberg", "Hoenigswald", "Holzman"]: // Hochberg, Hönigswald, Holzman print(names.sort(germanPhonebook.compare).join(", "));
      
      







一部の単語はウムラウトで接続されているため、ウムラウトを無視して辞書でソートすることは理にかなっています(たとえば、シェーンの前のシェーンなど、単語がウムラウトのみで異なる場合を除きます)。



 var germanDictionary = new Intl.Collator("de-DE-u-co-dict"); //  ["Hochberg", "Honigswald", "Holzman"]: // Hochberg, Holzman, Hönigswald print(names.sort(germanDictionary.compare).join(", "));
      
      







アメリカ英語の規則に従って、さまざまなエラー、ランダムなアクセント、発音区別記号が付いたFirefoxのバージョンを並べ替えます。 バージョン番号を考慮し、数字ではなく数字の値でソートします。



 var firefoxen = ["FireFøx 3.6", "Fire-fox 1.0", "Firefox 29", "FÍrefox 3.5", "Fírefox 18"]; var usVersion = new Intl.Collator("en-US", { sensitivity: "base", numeric: true, ignorePunctuation: true }); // Fire-fox 1.0, FÍrefox 3.5, FireFøx 3.6, Fírefox 18, Firefox 29 print(firefoxen.sort(usVersion.compare).join(", "));
      
      







最後に、大文字と小文字を区別しないアクセントで文字列検索を実行します。



 var decoratedBrowsers = [ "A\u0362maya", // A͢maya "CH\u035Brôme", // CH͛rôme "FirefÓx", "sAfàri", "o\u0323pERA", // ọpERA "I\u0352E", // I͒E ]; var fuzzySearch = new Intl.Collator("en-US", { usage: "search", sensitivity: "base" }); function findBrowser(browser) { function cmp(other) { return fuzzySearch.compare(browser, other) === 0; } return cmp; } print(decoratedBrowsers.findIndex(findBrowser("Firêfox"))); // 2 print(decoratedBrowsers.findIndex(findBrowser("Safåri"))); // 3 print(decoratedBrowsers.findIndex(findBrowser("Ãmaya"))); // 0 print(decoratedBrowsers.findIndex(findBrowser("Øpera"))); // 4 print(decoratedBrowsers.findIndex(findBrowser("Chromè"))); // 1 print(decoratedBrowsers.findIndex(findBrowser("IË"))); // 5
      
      







追加情報



特定のロケールで操作がサポートされているかどうか、またはロケール自体がサポートされているかどうかを判断すると役立つ場合があります。 これを行うために、各コンストラクターには、supportedLocales()関数があり、各プロトタイプでは、resolvedOptions()関数があります。



 var navajoLocales = Intl.Collator.supportedLocalesOf(["nv"], { usage: "sort" }); print(navajoLocales.length > 0 ? "Navajo collation supported" : "Navajo collation not supported"); var germanFakeRegion = new Intl.DateTimeFormat("de-XX", { timeZone: "UTC" }); var usedOptions = germanFakeRegion.resolvedOptions(); print(usedOptions.locale); // de print(usedOptions.timeZone); // UTC
      
      







遺伝的行動



ES5より前は、toLocaleString関数とlocaleCompare関数にはそのような高度なセマンティクスがなく、設定を受け入れず、実際には役に立たなかった。 したがって、Intl操作をサポートするように動作が変更されました。 ロケールに関するプログラムの正確な動作が特に重要でない場合は、古い関数を使用できます。 それ以外の場合は、Intlのプリミティブを直接使用することをお勧めします。



おわりに



国際化は非常に興味深いトピックであり、その複雑さは人間のコミュニケーションの性質によってのみ制限されます。 国際化APIは、この複雑さの小さいながらも必要な部分に対処し、ローカライズ対応のWebアプリケーションの作成を容易にします。



All Articles