どのように変換MicrosoftロケールID(LCID)言語コードまたはロケールのオブジェクトにJava
質問
私化する必要があり、 MicrosoftロケールID, など1033(英語)のいずれかを ISO639言語コード または直接には、Java ロケール インスタンス.(編集:でも、単に"言語-国/地域"マイクロソフトマイクロソフトがありました。)
こんなことが可能なので、何が最も簡単な方法は?好ましくは使用JDKの標準ライブラリ、トータル-プロデュースでこれが不可能な場合は、第3者機関図書館があります。
解決 2
、我々は、少なくとも今のところ、私たち自身の何かをロール〜20分かかっています。
// MSDN:私たちは、馬の口、すなわちのhttpから情報を取りました。 microsoft.com/en-us/goglobal/bb964664.aspx には、このようなファイルの.propertiesに(エクセル経由)、それをコピーし、貼り付けます:
1078 = Afrikaans - South Africa
1052 = Albanian - Albania
1118 = Amharic - Ethiopia
1025 = Arabic - Saudi Arabia
5121 = Arabic - Algeria
...
(あなたは、ファイルをダウンロードすることができますここをお持ちの場合似ている必要があります。)
そして、そこマップに.propertiesファイルから情報を読み取り、非常に単純なクラスだ、との変換を行うための方法を持っています。
Map<String, String> lcidToDescription;
public String getDescription(String lcid) { ... }
国/地域 - そして、はい、これは実際には(私はもともと尋ねです)の言語コードまたはのLocaleオブジェクトのにマップされませんが、Microsoftの「言語へ"説明。これは私たちの現在の必要性のために十分であったが。
免責事項:これは本当にあなた自身のコードベースにLCIDマッピング情報のコピーをJavaで自分でそれをやって、と明らかに保つ(および維持)のミニマル、「ダミー」の方法は、非常にエレガントされていないです。この答えにもかかわらず、だから、(一方で、どちらも私は巨大なライブラリのjarファイルを含めるか、これだけの単純なマッピング。のための非常に複雑何かをしたいんだろう)、をよりエレガントなソリューションや既存のライブラリを投稿すること自由に感じをあなたがそのようなものを知っていれば。
他のヒント
を使用できる GetLocaleInfo このと仮定したWindows(win2k+)).
このC++コードの方法を示してその機能を利用する:
#include "windows.h"
int main()
{
HANDLE stdout = GetStdHandle(STD_OUTPUT_HANDLE);
if(INVALID_HANDLE_VALUE == stdout) return 1;
LCID Locale = 0x0c01; //Arabic - Egypt
int nchars = GetLocaleInfoW(Locale, LOCALE_SISO639LANGNAME, NULL, 0);
wchar_t* LanguageCode = new wchar_t[nchars];
GetLocaleInfoW(Locale, LOCALE_SISO639LANGNAME, LanguageCode, nchars);
WriteConsoleW(stdout, LanguageCode, nchars, NULL, NULL);
delete[] LanguageCode;
return 0;
}
いかに作るこ JNA ます。(ヒント:放定数はintとして表値です。)
サンプルJNAコード:
を用いJNIはありますが、管理可能なレベルであるため、比較的自明な課題です。
したがって、少なくともいう用語話の場の構築のための変換データベースです。くなった場合はWindowsのような列挙のLCIDs、国内外のトップ選手が集結するものです。います。として構築レベルのものなのがこの巨大な負担となります。いを避けるためにはマニュアル整備をクリックします。
次のコードは、プログラムでそれが簡単に最新のマッピングを維持することは、MicrosoftのLCIDコードとJavaロケール間のマッピングを作成します。
import java.io.IOException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
/**
* @author Gili Tzabari
*/
public final class Locales
{
/**
* Maps a Microsoft LCID to a Java Locale.
*/
private final Map<Integer, Locale> lcidToLocale = new HashMap<>(LcidToLocaleMapping.NUM_LOCALES);
public Locales()
{
// Try loading the mapping from cache
File file = new File("lcid-to-locale.properties");
Properties properties = new Properties();
try (FileInputStream in = new FileInputStream(file))
{
properties.load(in);
for (Object key: properties.keySet())
{
String keyString = key.toString();
Integer lcid = Integer.parseInt(keyString);
String languageTag = properties.getProperty(keyString);
lcidToLocale.put(lcid, Locale.forLanguageTag(languageTag));
}
return;
}
catch (IOException unused)
{
// Cache does not exist or is invalid, regenerate...
lcidToLocale.clear();
}
LcidToLocaleMapping mapping;
try
{
mapping = new LcidToLocaleMapping();
}
catch (IOException e)
{
// Unrecoverable runtime failure
throw new AssertionError(e);
}
for (Locale locale: Locale.getAvailableLocales())
{
if (locale == Locale.ROOT)
{
// Special case that doesn't map to a real locale
continue;
}
String language = locale.getDisplayLanguage(Locale.ENGLISH);
String country = locale.getDisplayCountry(Locale.ENGLISH);
country = mapping.getCountryAlias(country);
String script = locale.getDisplayScript();
for (Integer lcid: mapping.listLcidFor(language, country, script))
{
lcidToLocale.put(lcid, locale);
properties.put(lcid.toString(), locale.toLanguageTag());
}
}
// Cache the mapping
try (FileOutputStream out = new FileOutputStream(file))
{
properties.store(out, "LCID to Locale mapping");
}
catch (IOException e)
{
// Unrecoverable runtime failure
throw new AssertionError(e);
}
}
/**
* @param lcid a Microsoft LCID code
* @return a Java locale
* @see https://msdn.microsoft.com/en-us/library/cc223140.aspx
*/
public Locale fromLcid(int lcid)
{
return lcidToLocale.get(lcid);
}
}
import com.google.common.collect.HashMultimap;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.SetMultimap;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import org.bitbucket.cowwoc.preconditions.Preconditions;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Generates a mapping between Microsoft LCIDs and Java Locales.
* <p>
* @see http://stackoverflow.com/a/32324060/14731
* @author Gili Tzabari
*/
final class LcidToLocaleMapping
{
private static final int NUM_COUNTRIES = 194;
private static final int NUM_LANGUAGES = 13;
private static final int NUM_SCRIPTS = 5;
/**
* The number of locales we are expecting. This value is only used for performance optimization.
*/
public static final int NUM_LOCALES = 238;
private static final List<String> EXPECTED_HEADERS = ImmutableList.of("lcid", "language", "location");
// [language] - [comment] ([script])
private static final Pattern languagePattern = Pattern.compile("^(.+?)(?: - (.*?))?(?: \\((.+)\\))?$");
/**
* Maps a country to a list of entries.
*/
private static final SetMultimap<String, Mapping> COUNTRY_TO_ENTRIES = HashMultimap.create(NUM_COUNTRIES,
NUM_LOCALES / NUM_COUNTRIES);
/**
* Maps a language to a list of entries.
*/
private static final SetMultimap<String, Mapping> LANGUAGE_TO_ENTRIES = HashMultimap.create(NUM_LANGUAGES,
NUM_LOCALES / NUM_LANGUAGES);
/**
* Maps a language script to a list of entries.
*/
private static final SetMultimap<String, Mapping> SCRIPT_TO_ENTRIES = HashMultimap.create(NUM_SCRIPTS,
NUM_LOCALES / NUM_SCRIPTS);
/**
* Maps a Locale country name to a LCID country name.
*/
private static final Map<String, String> countryAlias = ImmutableMap.<String, String>builder().
put("United Arab Emirates", "U.A.E.").
build();
/**
* A mapping between a country, language, script and LCID.
*/
private static final class Mapping
{
public final String country;
public final String language;
public final String script;
public final int lcid;
Mapping(String country, String language, String script, int lcid)
{
Preconditions.requireThat(country, "country").isNotNull();
Preconditions.requireThat(language, "language").isNotNull().isNotEmpty();
Preconditions.requireThat(script, "script").isNotNull();
this.country = country;
this.language = language;
this.script = script;
this.lcid = lcid;
}
@Override
public int hashCode()
{
return country.hashCode() + language.hashCode() + script.hashCode() + lcid;
}
@Override
public boolean equals(Object obj)
{
if (!(obj instanceof Locales))
return false;
Mapping other = (Mapping) obj;
return country.equals(other.country) && language.equals(other.language) && script.equals(other.script) &&
lcid == other.lcid;
}
}
private final Logger log = LoggerFactory.getLogger(LcidToLocaleMapping.class);
/**
* Creates a new LCID to Locale mapping.
* <p>
* @throws IOException if an I/O error occurs while reading the LCID table
*/
LcidToLocaleMapping() throws IOException
{
Document doc = Jsoup.connect("https://msdn.microsoft.com/en-us/library/cc223140.aspx").get();
Element mainBody = doc.getElementById("mainBody");
Elements elements = mainBody.select("table");
assert (elements.size() == 1): elements;
for (Element table: elements)
{
boolean firstRow = true;
for (Element row: table.select("tr"))
{
if (firstRow)
{
// Make sure that columns are ordered as expected
List<String> headers = new ArrayList<>(3);
Elements columns = row.select("th");
for (Element column: columns)
headers.add(column.text().toLowerCase());
assert (headers.equals(EXPECTED_HEADERS)): headers;
firstRow = false;
continue;
}
Elements columns = row.select("td");
assert (columns.size() == 3): columns;
Integer lcid = Integer.parseInt(columns.get(0).text(), 16);
Matcher languageMatcher = languagePattern.matcher(columns.get(1).text());
if (!languageMatcher.find())
throw new AssertionError();
String language = languageMatcher.group(1);
String script = languageMatcher.group(2);
if (script == null)
script = "";
String country = columns.get(2).text();
Mapping mapping = new Mapping(country, language, script, lcid);
COUNTRY_TO_ENTRIES.put(country, mapping);
LANGUAGE_TO_ENTRIES.put(language, mapping);
if (!script.isEmpty())
SCRIPT_TO_ENTRIES.put(script, mapping);
}
}
}
/**
* Returns the LCID codes associated with a [country, language, script] combination.
* <p>
* @param language a language
* @param country a country (empty string if any country should match)
* @param script a language script (empty string if any script should match)
* @return an empty list if no matches are found
* @throws NullPointerException if any of the arguments are null
* @throws IllegalArgumentException if language is empty
*/
public Collection<Integer> listLcidFor(String language, String country, String script)
throws NullPointerException, IllegalArgumentException
{
Preconditions.requireThat(language, "language").isNotNull().isNotEmpty();
Preconditions.requireThat(country, "country").isNotNull();
Preconditions.requireThat(script, "script").isNotNull();
Set<Mapping> result = LANGUAGE_TO_ENTRIES.get(language);
if (result == null)
{
log.warn("Language '" + language + "' had no corresponding LCID");
return Collections.emptyList();
}
if (!country.isEmpty())
{
Set<Mapping> entries = COUNTRY_TO_ENTRIES.get(country);
result = Sets.intersection(result, entries);
}
if (!script.isEmpty())
{
Set<Mapping> entries = SCRIPT_TO_ENTRIES.get(script);
result = Sets.intersection(result, entries);
}
return result.stream().map(entry -> entry.lcid).collect(Collectors.toList());
}
/**
* @param name the locale country name
* @return the LCID country name
*/
public String getCountryAlias(String name)
{
String result = countryAlias.get(name);
if (result == null)
return name;
return result;
}
}
Mavenの依存関係:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>
<dependency>
<groupId>org.bitbucket.cowwoc</groupId>
<artifactId>preconditions</artifactId>
<version>1.25</version>
</dependency>
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.8.3</version>
</dependency>
使用方法:
System.out.println("Language: " + new Locales().fromLcid(1033).getDisplayLanguage());
"言語:英語の" 印刷されます。
の意味、LCID 1033は英語にマップます。
の注:これは、あなたの実行時のJVM上で利用可能なロケールのマッピングを生成します。つまり、あなただけのすべての可能なロケールのサブセットを取得します。それは言った、私はあなたのJVMがサポートされていないロケールをインスタンス化することは技術的には可能であるとは思わないので、これはおそらく、私たちができる最善である...
は、最初のヒットでした"JavaのLCID" のためのGoogleのの上、このjavadocは次のとおりです。
gnu.java.awt.font.opentype.NameDecoder
プライベート静的java.util.Localeの getWindowsLocale(int型LCID)
Maps a Windows LCID into a Java Locale. Parameters: lcid - the Windows language ID whose Java locale is to be retrieved. Returns: an suitable Locale, or null if the mapping cannot be performed.
私はどここのライブラリをダウンロードするについて行くにはわからないんだけど、それはGNUですので、それを見つけるのはそれほど難しいことではありません。