1.概要

  • 国際化とは、言語、地域、文化、政治に固有のさまざまなデータをサポートするためのアプリケーションを作成するプロセスです。




  • ** をさらに読むために、国際化のための非常にポピュラーな略語(おそらく実際の名前よりもポピュラー)があることを知っておくべきです –

    i18n

    は ‘i’と ‘n’の間の18文字のためです。

今日の企業向けプログラムでは、世界のさまざまな場所または複数の文化的地域の人々にサービスを提供することが重要です。異なる文化や言語の地域では、言語固有の説明だけでなく、通貨、数字の表現、さらには異なる日付と時刻の構成も決定されません。

たとえば、国固有の数字に注目しましょう。彼らは様々な小数点と千の区切り記号があります。

  • 102,300.45(アメリカ合衆国)

  • 102 300,45(ポーランド)

  • 102.300、45(ドイツ)

さまざまな日付形式もあります。

  • 2018年1月1日、月曜日、3:20:34 PM CET(アメリカ合衆国)

  • 1月1日2018 15時間20 CET(フランス)。

  • 2018年1月1日星期1時03时20分34秒CET(中国)

さらに、国によって通貨記号が異なります。

  • £1,200.60(イギリス)

  • €1.200,60(イタリア)

  • 1 200,60€(フランス)

  • 1,200.60米ドル(アメリカ合衆国)

知っておくべき重要な事実は、たとえ国が同じ通貨と通貨記号を持っていたとしても – フランスとイタリアのように – 彼らの通貨記号の位置は異なるかもしれないということです。

2.ローカライゼーション

  • Java内には、

    Locale

    クラスと呼ばれる素晴らしい機能があります。

これにより、文化的なロケールをすばやく区別し、コンテンツを適切にフォーマットすることができます。国際化プロセスの中で不可欠です。国際化と同じように、ローカライゼーションもその略語 –


l10n

.

を持っています


Locale

を使用する主な理由は、必要なロケール固有のフォーマットすべてに再コンパイルなしでアクセスできることです。アプリケーションは複数のロケールを同時に処理できるため、新しい言語をサポートするのは簡単です。

ロケールは通常、アンダースコアで区切られた言語、国、およびバリアントの略語で表されます。

  • de(ドイツ語)

  • it__CH(イタリア語、スイス)

  • en

    US

    UNIX(米国、UNIXプラットフォーム)


2.1. フィールド


  • Locale

    は言語コード、国別コード、および派生形で構成されていることをすでに学びました。設定可能なフィールドがさらに2つあります。

スクリプトと拡張機能** 。

フィールドのリストを見て、ルールが何であるかを見てみましょう。


  • 言語



    ISO 639 alpha-2またはalpha-3

    コード、あるいは登録済みです。

言語サブタグ。


  • 地域

    (Country)は

    ISO 3166 alpha-2

    country codeまたは__UNです。

数値3__市外局番。


  • Variant

    は、大文字と小文字を区別する値、または


Locale

のバリエーション。


  • スクリプト

    は有効な

    ISO 15924 alpha-4

    コードでなければなりません。


  • Extensions

    は単一の文字キーと


String


IANA Language Subtag Registry

には、

language



region



variant

、および

script

に指定できる値が含まれています。

可能な

extension

値のリストはありませんが、値は整形式のhttps://docs.oracle.com/javase/tutorial/i18n/locale/extensions.html[

BCP-47

]サブタグである必要があります。キーと値は常に小文字に変換されます。


2.2.

Locale.Builder



Locale

オブジェクトを作成する方法はいくつかあります。 1つの可能な方法は

Locale.Builder

を利用します。

Locale.Builder

には、オブジェクトを構築して同時にそれらの値を検証するために使用できる5つの設定メソッドがあります。

Locale locale = new Locale.Builder()
  .setLanguage("fr")
  .setRegion("CA")
  .setVariant("POSIX")
  .setScript("Latn")
  .build();

上記の

Locale



String

表現は

fr

CA

POSIX

#Latn__です。

setterメソッドでは

BCP-47

に準拠している必要がありますが、** 「variant」の設定はバリアント値に対する公式の制限がないため、少しトリッキーになるかもしれません。

そうでない場合は、

IllformedLocaleException

がスローされます。

検証に合格しない値を使用する必要がある場合は、値を検証しないため、

Locale

コンストラクタを使用できます。


2.3. コンストラクタ


Locale

には3つのコンストラクタがあります。


  • 新しいロケール(String language)


  • 新しいロケール(String language、String country)


  • 新しいロケール(String language、String country、String variant)

3パラメータのコンストラクタ

Locale locale = new Locale("pl", "PL", "UNIX");

有効な

variant

は、5から8文字の英数字または単一の数値の後に3文字の英数字の

String

でなければなりません。これらの要件を満たしていないため、コンストラクタを介してのみ

variant

フィールドに「UNIX」を適用できます。

ただし、

Locale

オブジェクトを作成するためにコンストラクタを使用することには1つの欠点があります。拡張子やスクリプトフィールドを設定することはできません。


2.4. 定数

これはおそらく

Locales

を取得するための最も簡単で制限された方法です。

Locale

クラスには、最も普及している国または言語を表すいくつかの静的定数があります。

Locale japan = Locale.JAPAN;
Locale japanese = Locale.JAPANESE;


2.5. 言語タグ


Locale

を作成するもう1つの方法は、静的ファクトリメソッド

forLanguageTag(String languageTag)

を呼び出すことです。このメソッドは

IETF BCP 47

規格を満たす

String

を必要とします。

これが私達がどのように英国

Locale

を作成できるかです:

Locale uk = Locale.forLanguageTag("en-UK");


2.6. 利用可能なロケール


Locale

オブジェクトを複数組み合わせて作成することはできますが、使用できない可能性があります。

注意すべき重要な注意点は、プラットフォーム上の

Locales

は、Java Runtime内にインストールされているものに依存していることです。

フォーマットに

Locales

を使用しているので、さまざまなフォーマッタがランタイムにインストールされている利用可能な

Locales

のさらに小さいセットを持つことができます。

利用可能なロケールの配列を取得する方法を確認しましょう。

Locale[]numberFormatLocales = NumberFormat.getAvailableLocales();
Locale[]dateFormatLocales = DateFormat.getAvailableLocales();
Locale[]locales = Locale.getAvailableLocales();

その後、

Locale

が利用可能な__Localesの中にあるかどうかを確認できます。

利用可能なロケールのセットは、Javaプラットフォームのさまざまな実装と機能のさまざまな分野で異なることを覚えておいてください。

サポートされているロケールの完全なリストはhttp://www.oracle.com/technetwork/java/javase/documentation/java9locales-3559485.html[OracleのJava SE Development Kit Webページ]にあります。]


2.7. デフォルトロケール

ローカライズ作業中は、

JVM

インスタンスのデフォルトの

Locale

が何であるかを知る必要があるかもしれません。幸いなことに、それを行う簡単な方法があります。

Locale defaultLocale = Locale.getDefault();

また、同様のセッターメソッドを呼び出して、デフォルトの

Locale

を指定することもできます。

Locale.setDefault(Locale.CANADA__FRENCH);


JVM

インスタンスに依存しない

JUnit

テストを作成したい場合は特に重要です。

3.数字と通貨

このセクションでは、ロケール固有のさまざまな規則に準拠する必要がある数字および通貨のフォーマッタについて説明します。

プリミティブな数値型(

int



double

)と同等のオブジェクト(

Integer



Double

)をフォーマットするには、

NumberFormat

クラスとその静的ファクトリメソッドを使用する必要があります。

2つの方法は私たちにとって興味深いものです。


  • NumberFormat.getInstance(ロケールロケール)


  • NumberFormat.getCurrencyInstance(ロケールのロケール)

サンプルコードを見てみましょう。

Locale usLocale = Locale.US;
double number = 102300.456d;
NumberFormat usNumberFormat = NumberFormat.getInstance(usLocale);

assertEquals(usNumberFormat.format(number), "102,300.456");

ご覧のとおり、

Locale

を作成し、それを使用して

NumberFormat

インスタンスを取得してサンプル番号をフォーマットするのと同じくらい簡単です。 ** 出力にはロケール固有の10進数と千の区切り記号が含まれています。

これは別の例です。

Locale usLocale = Locale.US;
BigDecimal number = new BigDecimal(102__300.456d);

NumberFormat usNumberFormat = NumberFormat.getCurrencyInstance(usLocale);
assertEquals(usNumberFormat.format(number), "$102,300.46");

通貨の書式設定には、数値の書式設定と同じ手順が含まれます。

唯一の違いは、フォーマッタが通貨記号と小数点以下の桁数を2桁に追加することです。

4.日時

それでは、数字のフォーマットよりも複雑な日付と時刻のフォーマットについて学びます。

まず第一に、我々はそれが完全に新しい

Date/Time

APIを含むので、日付と時刻のフォーマットがJava 8で著しく変化したことを知るべきです。

そのため、さまざまなフォーマッタクラスを見ていきます。


4.1.

DateTimeFormatter


  • Java 8が導入されて以来、日付と時刻をローカライズするためのメインクラスは

    DateTimeFormatter

    クラスです** 。これは

    TemporalAccessor

    インターフェースを実装するクラス(例えば、

    LocalDateTime



    LocalDate、LocalTime

    、または

    __ZonedDateTime)で動作します。


    DateTimeFormatterを作成するには、少なくともパターンを指定し、次に


    Localeを指定する必要があります。

    __コード例を見てみましょう:

Locale.setDefault(Locale.US);
LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
String pattern = "dd-MMMM-yyyy HH:mm:ss.SSS";

DateTimeFormatter defaultTimeFormatter = DateTimeFormatter.ofPattern(pattern);
DateTimeFormatter deTimeFormatter = DateTimeFormatter.ofPattern(pattern, Locale.GERMANY);

assertEquals(
  "01-January-2018 10:15:50.000",
  defaultTimeFormatter.format(localDateTime));
assertEquals(
  "01-Januar-2018 10:15:50.000",
  deTimeFormatter.format(localDateTime));


DateTimeFormatter

を取得した後は、

format()

メソッドを呼び出すだけでよいことがわかります。

より良い理解のために、我々は可能なパターン文字に精通しているべきです。

たとえば、手紙を見てみましょう。

Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   y       year-of-era                 year              2004; 04
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978

説明付きの可能なパターン文字はすべてhttps://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html[

DateTimeFormatter

]のJavaドキュメントにあります。最終的な値がシンボルの数に依存することを知るために** 。この例では、月の名前を完全に表示する「MMMM」がありますが、「M」の文字を1つ付けると、先頭に0を付けずに月の番号が表示されます。


DateTimeFormatter

を完成させるために、

LocalizedDateTime

のフォーマット方法を見てみましょう。

LocalDateTime localDateTime = LocalDateTime.of(2018, 1, 1, 10, 15, 50, 500);
ZoneId losAngelesTimeZone = TimeZone.getTimeZone("America/Los__Angeles").toZoneId();

DateTimeFormatter localizedTimeFormatter = DateTimeFormatter
  .ofLocalizedDateTime(FormatStyle.FULL);
String formattedLocalizedTime = localizedTimeFormatter.format(
  ZonedDateTime.of(localDateTime, losAngelesTimeZone));

assertEquals("Monday, January 1, 2018 10:15:50 AM PST", formattedLocalizedTime);


LocalizedDateTime

をフォーマットするために、

ofLocalizedDateTime(FormatStyle dateTimeStyle)

メソッドを使用し、定義済みの

FormatStyle.

を提供することができます。

Java 8 Date/Time APIの詳細については、既存の記事リンク:/java-8-date-time-intro[here]を参照してください。

** 4.2.

DateFormat



SimpleDateFormatter

**


Dates



Calendars

を利用するプロジェクトで作業することは依然として一般的なので、

DateFormat



SimpleDateFormat

クラスを使用して日付と時刻をフォーマットする機能を簡単に紹介します。

最初の能力を分析しましょう。

GregorianCalendar gregorianCalendar = new GregorianCalendar(2018, 1, 1, 10, 15, 20);
Date date = gregorianCalendar.getTime();

DateFormat ffInstance = DateFormat.getDateTimeInstance(
  DateFormat.FULL, DateFormat.FULL, Locale.ITALY);
DateFormat smInstance = DateFormat.getDateTimeInstance(
  DateFormat.SHORT, DateFormat.MEDIUM, Locale.ITALY);

assertEquals("giovedì 1 febbraio 2018 10.15.20 CET", ffInstance.format(date));
assertEquals("01/02/18 10.15.20", smInstance.format(date));


DateFormat



Dates

と連携して機能し、3つの便利なメソッドがあります。


  • getDateTimeInstance


  • getDateInstance


  • getTimeInstance

それらはすべて、パラメーターとして

DateFormat

の事前定義値を取ります。各メソッドはオーバーロードされているので、

Locale

を渡すことも可能です。

DateTimeFormatter

のようにカスタムパターンを使用したい場合は、

SimpleDateFormat

を使用できます。短いコードスニペットを見てみましょう。

GregorianCalendar gregorianCalendar = new GregorianCalendar(
  2018, 1, 1, 10, 15, 20);
Date date = gregorianCalendar.getTime();
Locale.setDefault(new Locale("pl", "PL"));

SimpleDateFormat fullMonthDateFormat = new SimpleDateFormat(
  "dd-MMMM-yyyy HH:mm:ss:SSS");
SimpleDateFormat shortMonthsimpleDateFormat = new SimpleDateFormat(
  "dd-MM-yyyy HH:mm:ss:SSS");

assertEquals(
  "01-lutego-2018 10:15:20:000", fullMonthDateFormat.format(date));
assertEquals(
  "01-02-2018 10:15:20:000" , shortMonthsimpleDateFormat.format(date));

5.カスタマイズ

いくつかの良い設計上の決定のために、私たちはロケール特有のフォーマットパターンに縛られていません、そして私たちは出力に完全に満足するようにほとんどすべての詳細を設定することができます。

  • 数字のフォーマットをカスタマイズするために、

    DecimalFormat



    DecimalFormatSymbols

    を使うことができます。

簡単な例を考えてみましょう。

Locale.setDefault(Locale.FRANCE);
BigDecimal number = new BigDecimal(102__300.456d);

DecimalFormat zeroDecimalFormat = new DecimalFormat("000000000.0000");
DecimalFormat dollarDecimalFormat = new DecimalFormat("$###,###.##");

assertEquals(zeroDecimalFormat.format(number), "000102300,4560");
assertEquals(dollarDecimalFormat.format(number), "$102 300,46");



DecimalFormat

ドキュメント

には、考えられるすべてのパターン文字が表示されます。

ここで知る必要があるのは、「000000000.000」が先行または後続のゼロを決定し、「、」が千単位の区切り文字で、「。」が10進数の1であることだけです。

通貨記号を追加することもできます。

DateFormatSymbol

クラスを使用しても同じ結果が得られることを以下で確認できます。

Locale.setDefault(Locale.FRANCE);
BigDecimal number = new BigDecimal(102__300.456d);

DecimalFormatSymbols decimalFormatSymbols = DecimalFormatSymbols.getInstance();
decimalFormatSymbols.setGroupingSeparator('^');
decimalFormatSymbols.setDecimalSeparator('@');
DecimalFormat separatorsDecimalFormat = new DecimalFormat("$###,###.##");
separatorsDecimalFormat.setGroupingSize(4);
separatorsDecimalFormat.setCurrency(Currency.getInstance(Locale.JAPAN));
separatorsDecimalFormat.setDecimalFormatSymbols(decimalFormatSymbols);

assertEquals(separatorsDecimalFormat.format(number), "$10^[email protected]");

ご覧のとおり、

DecimalFormatSymbols

クラスを使用すると、想像できる数値形式を指定できます。


  • SimpleDataFormatをカスタマイズするには、

    DateFormatSymbols__ ** を使用できます。

曜日名の変更がどれほど簡単かを見てみましょう。

Date date = new GregorianCalendar(2018, 1, 1, 10, 15, 20).getTime();
Locale.setDefault(new Locale("pl", "PL"));

DateFormatSymbols dateFormatSymbols = new DateFormatSymbols();
dateFormatSymbols.setWeekdays(new String[]{"A", "B", "C", "D", "E", "F", "G", "H"});
SimpleDateFormat newDaysDateFormat = new SimpleDateFormat(
  "EEEE-MMMM-yyyy HH:mm:ss:SSS", dateFormatSymbols);

assertEquals("F-lutego-2018 10:15:20:000", newDaysDateFormat.format(date));

6.リソースバンドル

最後に、

JVM

における国際化の重要な部分は

Resource Bundle

メカニズムです。


ResourceBundle

の目的は、別々のファイルに外部化できるローカライズされたメッセージ/説明をアプリケーションに提供することです。リソースバンドルの使い方と設定については、以前の記事 –

リソースバンドルのガイド

で説明しています。

7.まとめ


__Localと


それらを利用するフォーマッターは国際化されたアプリケーションを作成するのを助けるツールです。これらのツールを使用すると、複数のビルドやJavaが

Locale__をサポートしているかどうかを気にせずに、ユーザーの言語や文化の設定に動的に適応できるアプリケーションを作成できます。

ユーザーがどこにいても、どの言語でも話すことができる世界では、これらの変更を適用することができるということは、世界中のより多くのユーザーが私たちのアプリケーションをより直感的に理解できることを意味します。

Spring Bootアプリケーションを扱うときには、

Spring Boot Internationalization

という便利な記事もあります。

このチュートリアルのソースコードは、完全な例とともに、https://github.com/eugenp/tutorials/tree/master/core-java-8/src/test/java/com/baeldung/internationalization[over onにあります。 GitHub]。