Locale クラスは ISO 639-2(3桁)の言語コードを受け付けるのか?
ISO 639-2 (alpha-3) では、言語を 3 桁のアルファベットで識別できるよう定義しています(例: 日本語は jpn
)。
この言語識別子を使って、Java の Locale
オブジェクトを生成できるのでしょうか?
Java の Locale クラス の説明には、次のように記載されています。
言語に alpha-2 コードと alpha-3 コードの両方がある場合は、alpha-2 コードを使用する必要があります。
また、Locale クラスのコンストラクタ の第 1 引数の説明には、次のように書かれています。
language - ISO 639 alpha-2 または alpha-3 言語コード、または最高 8 文字の言語のサブタグ。
実際に試してみると、alpha-2 コード(2桁)はほぼすべて対応しているのに対し、alpha-3 コード(3桁)は対応がいまいちのようです。
fun main() {
// alpha-2 で指定
println(Locale("ja").displayLanguage) // 日本語 (OK)
println(Locale("en").displayLanguage) // 英語 (OK)
println(Locale("fr").displayLanguage) // フランス語 (OK)
println(Locale("zh").displayLanguage) // 中国語 (OK)
// alpha-3 で指定
println(Locale("jpn").displayLanguage) // 日本語 (OK)
println(Locale("eng").displayLanguage) // 英語 (OK)
println(Locale("fra").displayLanguage) // fra (NG)
println(Locale("zho").displayLanguage) // zho (NG)
}
Locale
クラスが認識できる alpha-2 コードの一覧は、Locale.getISOLanguages()
で取得できます。
一方、認識できる alpha-3 コードの一覧を取得するメソッドは存在しませんが、上記の結果をみる限り、フランス語を表す fra
と中国語を表す zho
という言語コードからは、Locale
クラスは言語情報をうまく生成してくれません。
何とも使いにくいですね。
alpha-2 コード(2桁)で正しい言語情報を持つ Locale
オブジェクトを生成できるのであれば、そのオブジェクトから getISO3Language()
で alpha-3 コード(3桁)を取得することができます。
つまり、fr
に対応するコードが fra
であることは判別できます。
この情報を使って、うまく逆変換するテーブルを作れば、alpha-3 コードからももう少しロバストに Locale
オブジェクトを生成できるようになりそうです。
ISO 639-2(3桁)の言語コードから Locale オブジェクトを生成するユーティリティ
下記の LanguageLocales
クラスは、ISO 639-1(2桁)や ISO 639-2(3桁)の言語コードから Locale
オブジェクトを取得するためのユーティリティクラスです。
/**
* Language utility for obtaining the Locale object corresponding
* to the given ISO 639-1/2 language code such as "fra".
*
* ```
* val locale = LanguageLocales["fra"]
* ```
*/
class LanguageLocales {
companion object {
/** Map of ISO 639-1/2 code to Locale */
private val localeMap = mutableMapOf<String, Locale>()
init {
// ISO 639 の言語識別子(2桁)リストを利用してマップを作成します
val alpha2s: Array<String> = Locale.getISOLanguages();
for (code in alpha2s) {
val loc = Locale(code)
localeMap[code] = loc // from Alpha2
localeMap[loc.getISO3Language()] = loc // from Alpha3
}
}
/** ISO 639 の言語コード(2桁/3桁)から Locale オブジェクトを取得します. */
operator fun get(alpha2or3: String): Locale {
var loc: Locale? = localeMap[alpha2or3]
if (loc == null) {
loc = Locale(alpha2or3)
localeMap[alpha2or3] = loc
}
return loc
}
}
}
Locale
オブジェクトの第 1 引数に言語コードを渡してオブジェクト生成するより、LanguageLocales
クラスを使って Locale
オブジェクトを取得した方が、正しい言語情報を取得できる可能性が上がります。
fun main() {
// alpha-2 で指定
println(LanguageLocales["ja"].displayLanguage) // 日本語 (OK)
println(LanguageLocales["en"].displayLanguage) // 英語 (OK)
println(LanguageLocales["fr"].displayLanguage) // フランス語 (OK)
println(LanguageLocales["zh"].displayLanguage) // 中国語 (OK)
// alpha-3 で指定
println(LanguageLocales["jpn"].displayLanguage) // 日本語 (OK)
println(LanguageLocales["eng"].displayLanguage) // 英語 (OK)
println(LanguageLocales["fra"].displayLanguage) // フランス語 (OK)
println(LanguageLocales["zho"].displayLanguage) // 中国語 (OK)
}
もちろん、すべての ISO 639-2 (alpha-3) コードに対応しているわけではないので、その点は注意してください。