Java-「ローカライズってなんぞ！？」

## 前置き
こんにちは、皆さんがお盆休みでもせっせこ勉強している雑魚SEだよ。
今日はJava Goldの試験範囲でローカライズについての出題があるんだけど、私があまり気にしたことのない内容だったので
黒本の回答をもとにまとめてみたよ！

## ロケール情報って？
> javaは、それぞれの国や地域に柔軟に対応するためのクラスやインターフェースが提供されています。このうち、最も基盤となるクラスがjava.util.Localeです。このクラスは地域や言語といった「ロケール情報」を扱うためのクラスです。
--黒本より引用

「ふーん(　´_ゝ｀)ﾌｰﾝ、そんなのなんでもいいけどなー」

…きっと知識がないからありがたみも分からないのかな。

「あれ、もしかしてこれ使えば、アクセスしてきた人の個人情報（住所とか）も分かっちゃうかな！？」

(；ﾟдﾟ)ｺﾞｸﾘ…

## Localクラスの使用例1（国と言語の表示）
```java
import java.util.Locale;

public class LocaleSample1 {
	public void printLocale() {
		Locale local = Locale.getDefault();
		//国を表示する
		System.out.println(local.getCountry());
		//言語を表示する
		System.out.println(local.getLanguage());
	}
}
```
### 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/5712e3bf-ef47-5a98-3981-bdc6d246f09f.png)

「ふー、そう簡単に個人情報なんて出ないか笑」

（なんか個人情報が出ちゃうんじゃないかと思ってドキドキするなー笑）

「JPが国で、jaが日本語ってこと？」

>language
ISO 639 alpha-2またはalpha-3言語コード、または最大8文字の英字の登録済み言語サブタグ(将来の拡張のため)。言語にalpha-2コードとalpha-3コードの両方がある場合は、alpha-2コードを使用する必要があります。有効な言語コードの完全なリストはIANA言語サブタグ・レジストリで参照できます(「Type: language」を検索)。言語フィールドの大文字と小文字は区別されませんが、Localeでは常に小文字に正規化されます。
整形式の言語の値は、[a-zA-Z]{2,8}という形式です。ただし、これは拡張言語を含まないため、完全なBCP47言語プロダクションではありません。これらは最新の3文字の言語コードで置き換えられるため、必要ありません。
例: "en" (英語)、"ja" (日本語)、"kok" (コンカニ語)
country (region)
ISO 3166 alpha-2の国コードまたはUN M.49 numeric-3の地域コード。有効な国コードおよび地域コードの完全なリストはIANA言語サブタグ・レジストリで参照できます(「Type: region」を検索)。国(地域)フィールドの大文字と小文字は区別されませんが、Localeでは常に大文字に正規化されます。
整形式の国/地域の値は、[a-zA-Z]{2}|[0-9]{3}という形式です。
例: "US" (米国)、"FR" (フランス)、"029" (カリブ)
--公式リファレンスより引用：https://docs.oracle.com/javase/jp/8/docs/api/java/util/Locale.html

「IANA言語？なんじゃらほいほい」

調べてみたら、確かにlanguageで「ja:Japanese」、regionで「JP：Japan」がありました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/6b0c8a84-c1ef-7da1-376b-672adda22c94.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/f0fdf47f-6e96-ae9f-2b42-5740baee15a6.png)

IANA言語サブタグ・レジストリ：https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry

## ロケール情報を構築する方法
>Localeクラスのインスタンスを生成するには、以下の5つの方法があります。
1.getDefaultメソッドを使う
2.コンストラクタを使う
3.ロケール定数を使う
4.ビルダーを使う
5.ファクトリメソッドを使う

「５つ！？多すぎだろ！（本田圭佑）」

ここでプログラミング川柳をひとつ...

最初から
　一番使うの
　　教えてくれ
（雑魚SE心の叫び）

「字余りひどくて見てられないね...」

## Localeクラスのコンストラクタ
Localeクラスのコンストラクタは引数に言語コード(language)、国コード（country)、派生情報(variant）の３つを受け取れるようにオーバーロードされています。
・Local(String language)
・Local(String language, String country)
・Local(String language, String country, String variant)

「派生情報ってなんやねん！」

>コンストラクタの第三引数に渡す派生情報は、ベンダーまたはブラウザに固有のコードです。例えば、WindowsにはWIN、MacintoshにはMAC、POSIXにはPOSIXを使います。もし、この派生情報が2つある場合には、それらをアンダースコアで区切り、重要なものを最初に指定します。
例えば、Traditional Spanish（イスパニア語）のロケール情報を使う場合には、次のコード例のように言語、国、派生情報を指定してLocaleクラスのインスタンスを生成します。
Locale locale = new Locale("es","ES","Traditional_WIN");
--JavaGold黒本解説より引用

「...ってTraditional Sapnish（イスパニア語）ってなんやねん笑」

サンプルコードだったらわかりやすい国にしてくれよ！
おしえてChatGPTせんせーーーい！

>JavaのLocaleクラスのコンストラクタでvariant(派生情報)がありますが、これについて解説してください
(ChatGPT解答）
variantは、特定の地域やカルチャーに固有のローカルなバリエーションを表現するために使用されます。たとえば、同じ言語と国であっても、地域によって独自の文化的要素や言語の違いが存在する場合に、variantを使ってその差異を表現することができます。
・・・
さらに、variantを使用して特定の地域やカルチャーを区別する例を見てみましょう。中国の広東省を表すローカル情報を取得する場合、以下のようにvariantを指定します。
Locale cantoneseLocale = new Locale("zh", "CN", "HK");
ここで、"zh"は中国語の言語コードを表し、"CN"は中国の国コードを表します。そして、"HK"は香港を表すvariantとして広東省の特定の地域を示しています。
注意すべき点として、variantは必ずしも全てのロケールで必要なわけではありません。通常、言語コードと国コードだけで特定のローカル情報を表現できる場合もあります。

「なるほど、必ず必要なものではないのね」

## ロケール定数を使用したインスタンス化
| 定数 | 言語 | 国 | 説明 |
|:-:|:-:|:-:|:-:|
| static Locale.JAPAN  | ja  | JP  | 日本のロケール情報  |
| static Locale.US  | en | US  | アメリカのロケール情報  |
| static Locale.CANADDA  | en  | CA  | カナダのロケール情報  |
| static Locale.CANADA_FRENCH  | fr  | CA  | カナダのロケール情報  |
| static Locale.UK  | en  | GB  | イギリスのロケール情報  |
```java
Locale locale = Locale.CANADA_FRENCH;
```
「なんか一番使いやすそうなの出てきたぞ？これだけ使えばいいじゃん。」
>APIドキュメントを見ればわかるようにそれほど多くのバリエーションが用意されているわけではないのです。
（Java SE 11では、24種類しかありません。）
もし、ロケール定数が用意されていない場合には、言語コードや国コードを間違えないように注意しながら、コンストラクタを使う必要があります。  --JavaGold黒本解説より引用

「まるで俺の心を読んでいるかのような解説...見事だ！！」

## Builderを使ったインスタンス化
>Builderクラスを使ったインスタンス化は次のような手順で行います。
1.Builderクラスのインスタンスを生成する
2.各Setterメソッドを使ってロケール情報を生成する
3.buildメソッドでLocaleクラスのインスタンスを生成する

```java
Builder builder = new Locale.Builder();
                  .setLanguage("jp")
                  .setRegion("JP")
                  .setScript("Japan")
                  .build();
```

「コンストラクタで生成するより簡単そう..だけどScriptってなんだ？」

ということでまたまたChatGPTせんせーーーい！
>スクリプトは、言語コードの一部として使用され、特定の言語を表すために使用されるシンボルです。Locale.Builderクラスは、Localeオブジェクトを作成するためのビルダークラスであり、主に言語、国、地域、そしてオプションとしてバリアントやエクステンションを設定することができますが、スクリプトを直接設定する方法は提供されていません。"ja"は日本語の言語コードを表し、"Jpan"は日本語のスクリプトコードを表します。ただし、多くの場合、スクリプトは自動的に判別されるため、setScript()メソッドを使用する必要はありません。スクリプトコードを明示的に指定する必要がある場面は非常に限られています。一般的な場合は、言語コードと国コードのみで十分です。
--ChatGPT先生の回答

「つまり、言語を指定しようとしていて、setLanguageやsetRegionと一緒に使わないといけなく、大体自動で判別されるから必要ないってことか」

...頑張って調べて必要ないってわかると虚しいね...

## ファクトリメソッドを使ったインスタンス生成
解説によるとこの方法については、Java Goldの試験範囲を超えているらしい
覚えておくべきは、LocalクラスのforLanguageTagメソッドを使用することでIETF言語タグに準拠したLocalクラスのインスタンスを生成してその参照を返すらしい
```java
Locale locale = Locale.forLanguageTag("es-US-x-lvariant-POSIX");
System.out.println(locale);
```
試験範囲じゃないらしいので解説も割愛します。

「パッと見て何を設定しているのかよくわからないから個人的にもあんまり使わないだろうなー」

本日はいったんここまで！
Localクラスについて基本的なことを学べたけど個人情報が洩れる..みたいなことはさすがに資格の解説にはなかったっです笑