어떻게 변환하는 Microsoft 로캘 ID(릴)에 언어 코드 또는 로케일체에서 Java

StackOverflow https://stackoverflow.com/questions/1192361

  •  19-09-2019
  •  | 
  •  

문제

내가 필요로 번역 Microsoft 로캘 ID, 등 1033(미국 영어),중 하나는 ISO639 언어 코드 또는 직접적으로 자바 로캘 인스턴스입니다.(편집:또는 단순히으로"Language 국가/지역에서"Microsoft 의 테이블이 있습니다.)

이것이 가능한,그리고 무엇이 가장 쉬운 방법이 있을까?바람직하게만 사용하는 JDK 표준 라이브러리는 물론이지만,가능하지 않은 경우,제 3 자 라이브러리입니다.

도움이 되었습니까?

해결책 2

이 매핑을 할 준비가되지 않은 Java 솔루션이없는 것처럼 보이기 시작했을 때, 우리는 적어도 지금은 우리 자신의 무언가를 굴리는 데 ~ 20 분이 걸렸습니다.

우리는 말의 입에서 정보를 가져 왔습니다. http://msdn.microsoft.com/en-us/goglobal/bb96464.aspx, 그리고 (Excel을 통해) 복사하여 다음과 같은 .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) { ... }

그리고 네, 이것은 실제로 매핑되지 않습니다 언어 코드 또는 로케일 대상 (내가 원래 요청한 것), 그러나 Microsoft의 "언어 - 국가/지역"설명에. 이것이 우리의 현재 요구에 충분하다는 것이 밝혀졌습니다.

면책 조항 : 이것은 실제로 자바에서 직접 수행하는 최소한의 "더미"방법이며, 자신의 코드베이스에서 LCID 매핑 정보의 사본을 보관하고 유지하는 것은 그다지 우아하지 않습니다. (반면에, 나는 거대한 라이브러리 항아리를 포함 시키 거나이 간단한 매핑을 위해 지나치게 복잡한 일을하고 싶지 않을 것입니다.) 따라서이 대답에도 불구하고, 더 우아한 솔루션 또는 기존 라이브러리를 게시하십시오. 당신이 그런 것을 알고 있다면.

다른 팁

당신이 사용할 수 GetLocaleInfo 이렇게 하는(당신이 가정에서 실행되고 윈도우(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 전화입니다.(Tip:상수를 방출로 수을 찾아 그들의 값이다.)

샘플 JNA 코드:

를 사용하는 사용자가 좀 더 관련이지만,관리에 대한 비교적 사소한 작업입니다.

적어도,내가 찾으로 사용하는 기본화를 구축하는 데이터베이스 전환.나는 확실하지 않을 경우 윈도우에는 길을 열거 Lcid 있지만,그밖에 뭔가가 있습니다.Net.으로 구축 수준의 것,이것은 거대한 부담이 있습니다.내가 원하는 것을 방지하는 수동 유지관리의 목록입니다.

다음 코드는 프로그래밍 방식으로 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이 지원하지 않는 지역을 인스턴스화하는 것이 기술적으로 불가능하다고 생각하지 않으므로 이것은 아마도 우리가 할 수있는 최선 일 것입니다 ...

Google의 첫 번째 히트였습니다 "Java LCID"의 경우이 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이므로 찾기가 너무 어렵지 않아야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top