将语言代码三个字符(ISO 639-2)转换为两个字符代码(ISO 639-1)

本教程将介绍将语言代码三个字符(ISO 639-2)转换为两个字符代码(ISO 639-1)的处理方法,这篇教程是从别的地方看到的,然后加了一些国外程序员的疑问与解答,希望能对你有所帮助,好了,下面开始学习吧。

将语言代码三个字符(ISO 639-2)转换为两个字符代码(ISO 639-1) 教程 第1张

问题描述

我正在开发一个使用文本到语音(TTS)引擎的Android应用程序。TTS组件以Locale对象列表的形式返回可用语言列表。

但每个Locale对象的Locale::getLanguageLocale::getISO3Language两个方法返回相同的3字符代码(ISO 639-2)。通常getLanguage()以2字符格式(ISO 639-1)返回语言代码,但对于特定设备,代码为3个字符。国家代码也是如此。但是,我需要两个字符格式的语言和国家代码(ISO 639-1)。

有人知道进行转换的方法吗?请注意,我需要一个具有两个字母格式的语言和国家/地区代码的相应Locale对象。

推荐答案

tl;dr

作为一种解决办法,请根据ISO 639-1将每个已知的Locale映射到其两个字母的语言代码。

new LocaleLookup().lookupTwoLetterLanguageCode( Locale.CANADA_FRENCH )

fr

或可能只分析Locale::toString的文本。

Locale
.CANADA_FRENCH
.toString()// fr_CA
.split( "_" ) // Array: { "fr" , "CA" }
[ 0 ]// Grab first element in array, "fr". 

fr

对于两个字母的国家/地区代码,请使用拆分字符串的第二部分。使用1而不是0的索引。

Locale
.CANADA_FRENCH
.toString()// fr_CA
.split( "_" ) // Array: { "fr" , "CA" }
[ 1 ]// Grab first element in array, "CA". 

CA

错误?

Locale::getLanguage将返回3个字母的代码似乎是一个错误。Javadoc在其代码示例中使用了两个字母的代码。但不幸的是,Javadoc没有明确指定2个或3个字母。我建议您向OpenJDK项目提交一个请求,以澄清此Java代码。

解决方法

作为一种解决办法,您或许可以调用Locale.getISOLanguages来获取所有已知语言的两个字母代码的数组。然后把那些循环起来。对于每个对象,使用在Javadoc中看到的代码,传递两个字母的代码来限制Locale对象进行比较:

if (locale.getLanguage().equals(new Locale("he").getLanguage()))

从此版本中,您可以在区域设置和两个字母的代码之间使用您自己的Map

示例类

这是我第一次尝试这样的变通地图。

在构造函数中,我们获得所有已知区域设置和所有已知2字母ISO 639-1语言代码的列表。

接下来,我们执行嵌套循环。对于每个地区,我们循环所有两个字母的语言代码,直到找到匹配项。注意,我们做的是进行字符串匹配。Javadoc警告我们ISO 639标准稳定的;代码正在更改。报价:

注意:ISO 639不是一个稳定的标准-某些语言的代码已更改。Locale的构造函数可以识别代码已更改的语言的新代码和旧代码,但此函数始终返回旧代码。如果要检查代码已更改的特定语言,请不要执行以下操作

if (locale.getLanguage().equals("he")) // BAD!

相反,请执行

if (locale.getLanguage().equals(new Locale("he").getLanguage())) // GOOD.

因此,我们的内部循环查看每个已知的两个字母的语言代码,并获取该语言的Locale对象。然后,if语句比较getLanguage的输出(A)外部循环的Locale和(B)内部循环生成的仅语言的Locale(由两个字母的代码生成)。在您情况下,您声称某个设备正在为我们对getLanguage的调用输出3个字母的代码值。但无论是2个字母还是3个字母,都无关紧要。我们只是在寻找匹配项。

实例化后,我们可以通过调用lookupTwoLetterLanguageCode方法向LocaleLookup实例请求匹配特定Locale的两个字母的代码。

LocaleLookup localeLookup = new LocaleLookup();
Locale locale = Locale.CANADA_FRENCH;
String code = localeLookup.lookupTwoLetterLanguageCode( locale );

System.out.println( "Locale: " + locale.toString() + " " + locale.getDisplayName( Locale.getDefault() ) + " | ISO 639-1 code: " + code );

区域设置:FR_CA法语(加拿大)|ISO 639-1代码:FR

我只是在猜测这一切。我没有仔细考虑过,也没有测试过任何这一点。所以买家-当心,这个解决方案值你花的每一分钱。祝你好运。

这是整个类,其中public static void main用作演示。

package work.basil.example;

import java.util.*;

public class LocaleLookup
{
 private Map < Locale, String > mapLocaleToTwoLetterLangCode;

 public LocaleLookup ( )
 {
  this.mapLocaleToTwoLetterLangCode = new HashMap <>( Locale.getAvailableLocales().length );
  this.makeMaps();
  System.out.println( "mapLocaleToTwoLetterLangCode = " + mapLocaleToTwoLetterLangCode );
 }

 private void makeMaps ( )
 {
  // Get all locales.
  Set < Locale > locales = Set.of( Locale.getAvailableLocales() );


  // Get all languages, per 2-letter code.
  Set < String > twoLetterLanguageCodes = Set.of( Locale.getISOLanguages() ); // Returns: An array of ISO 639 two-letter language codes.

  for ( Locale locale : locales )
  {
for ( String twoLetterLanguageCode : twoLetterLanguageCodes )
{
 if ( locale.getLanguage().equals( new Locale( twoLetterLanguageCode ).getLanguage() ) )
 {
  this.mapLocaleToTwoLetterLangCode.put( locale , twoLetterLanguageCode );
  break;
 }
}
  }
//  System.out.println( "locales = " + locales );
//  System.out.println( "twoLetterLanguageCodes = " + twoLetterLanguageCodes );
 }

 public String lookupTwoLetterLanguageCode ( final Locale locale )
 {
  String code = this.mapLocaleToTwoLetterLangCode.get( locale );
  Objects.requireNonNull( code );
  return code;
 }


 public static void main ( String[] args )
 {
  LocaleLookup localeLookup = new LocaleLookup();
  Locale locale = Locale.CANADA_FRENCH;
  String code = localeLookup.lookupTwoLetterLanguageCode( locale );

  System.out.println( "Locale: " + locale.toString() + " " + locale.getDisplayName( Locale.getDefault() ) + " | ISO 639-1 code: " + code );
 }
}

这是我在Java 15预发布版本中生成的映射。注意可能是不正确的,因为我在预发布版本中看到了一些关于区域设置的错误。

好了关于将语言代码三个字符(ISO 639-2)转换为两个字符代码(ISO 639-1)的教程就到这里就结束了,希望趣模板源码网找到的这篇技术文章能帮助到大家,更多技术教程可以在站内搜索。