Java 地区和多语言支持的最佳实践是什么?

Java 地区和多语言支持的最佳实践是什么?,java,locale,Java,Locale,我想在我的程序中有多种语言。javaLocale类有一些区域设置,例如Locale.GERMAN、Locale.ENGLISH等等。但我需要额外的地区,例如西班牙语等 我如何储存和正确使用它们?最佳做法是什么 我是否应该创建某种LanguageHandler,将所有必需的区域设置存储在一个数组中?在这方面有什么经验和做法吗 编辑:该应用程序适用于桌面,并用Java编写。获取所有受支持地区的列表: 您可以使用localespanish=newlocale(“es”、“es”)在西班牙地区

我想在我的程序中有多种语言。java
Locale
类有一些区域设置,例如
Locale.GERMAN
Locale.ENGLISH
等等。但我需要额外的地区,例如西班牙语等

我如何储存和正确使用它们?最佳做法是什么

我是否应该创建某种LanguageHandler,将所有必需的区域设置存储在一个数组中?在这方面有什么经验和做法吗


编辑:该应用程序适用于桌面,并用Java编写。

获取所有受支持地区的列表:

您可以使用
localespanish=newlocale(“es”、“es”)
在西班牙地区使用西班牙语

我如何储存和正确使用它们?最佳做法是什么

据我所知,您不必存储受支持地区的主列表。你可以边走边用。通过如上所述定义语言环境,可以通过传递语言环境对象来帮助您加载ResourceBundle,但是您需要为要在应用程序中使用的每个语言环境创建ResourceBundle

例如,对于不同语言中的一些资源,您可能需要考虑翻译。< /P> 进一步阅读如何使用locale初始化resourceBundle


您可以始终使用与ISO 3166标准相对应的国家代码。对于西班牙人来说,那将是

Locale西班牙语=新语言环境(“es”、“es”);
正确无误,应予以接受。他的评论促成了这一回答

枚举 关于如何跟踪应用程序当前支持的区域设置,请定义枚举。枚举是处理编译时已知且在执行期间不变的项列表的好方法。见甲骨文

public enum L10n 
{
    fr_CA , es_ES ;  // Names of reference variables automatically set to point to objects automatically instantiated when this class loads.
}
使用构造函数传递由每个枚举元素表示的
Locale
对象。我们使用
L10n
作为枚举的类名,“L10n”是“本地化”一词的常见缩写

public enum L10n 
{
    // Enum elements.
    fr_CA( Locale.CANADA_FRENCH ) , 
    es_ES( new Locale("es", "ES") ) ;

    final private Locale locale ;

    // Constructor
    L10n( Locale localeArg ) 
    {
        this.locale = Objects.requireNonNull( localeArg ) ;
    }

}
枚举元素是常量。因此,在Java命名约定中,每个元素名称都应该是大写的,比如
FR\u CA
&
ES\u ES
。我认为我们这里的情况是一个例外,因为上/小写对于程序员认识每个名字的意义(语言和文化代码)很重要。 您可以使用此枚举中包含的
Locale
对象访问资源包。我们添加了一个
getResourceBundle
方法来提供此功能

public enum L10n 
{
    // Enum elements.
    fr_CA( Locale.CANADA_FRENCH ) , 
    es_ES( new Locale("es", "ES") ) ;

    final private Locale locale ;  // Remember the `Locale` object behind each element in this enum.

    // Constructor
    L10n( Locale localeArg ) 
    {
        this.locale = Objects.requireNonNull( localeArg ) ;
    }

    // Access the ResourceBundle for a particular locale.
    public ResourceBundle getResourceBundle() 
    {
        …
    }

}
注意:想想看。在整个应用程序中,每个枚举对象只有一个实例。所以,如果可以跨线程调用,
getResourceBundle
方法必须是线程安全的。如果只从单个UI相关线程中调用,那么线程安全就不是问题。但是请记住考虑测试套件、日志记录或其他可能从主UI线程以外的线程调用的其他地方。 使用该
getResourceBundle
方法的示例

L10n preferredLocalization = L10n.es_ES ;  // Perhaps taken from a dialog interaction with user.
ResourceBundle resourceBundle = preferredLocalization.getResourceBundle() ;
这个枚举现在充当资源包处理前面的一个façade。您可以重构处理代码,而不会影响整个应用程序中调用
L10n::getResourceBundle
的位置

若要显示应用程序支持的本地化列表,请添加获取显示名称的方法。此方法委托给包含的
Locale
对象的方法。您可能希望将该显示名称本地化为每个语言环境本身的语言和文化规范

public enum L10n 
{
    // Enum elements.
    fr_CA( Locale.CANADA_FRENCH ) , 
    es_ES( new Locale("es", "ES") ) ;

    final private Locale locale ;  // Remember the `Locale` object behind each element in this enum.

    // Constructor
    L10n( Locale localeArg ) 
    {
        this.locale = Objects.requireNonNull( localeArg ) ;
    }

    // Access the ResourceBundle for a particular locale.
    public ResourceBundle getResourceBundle() 
    {
        …
    }

    // For presentation to the user.
    public String getDisplayName() 
    {
        String name = this.locale.getDisplayName( this.locale ) ;  // Pass a `Locale` to `Locale::getDisplayName` to have that locale's name automatically localized. 
        return name ;
    }

}
获取显示名称的列表

您可以获得枚举元素的集合。
Enum.values
方法是在中定义的一种特殊的“隐式”方法,返回定义为该枚举上元素的所有对象的数组。不幸的是,Javadoc中几乎没有提到这个方法,在方法的描述中也有提及

for ( L10n localization : L10n.values() )
{
    System.out.println( localization.getDisplayName() );
}
法国(加拿大)

español(españa)


通过在enum类中添加另一个成员字段来表示该语言和文化的国旗图标,您甚至可以更喜欢它。然后,该标志可以出现在用户界面中,以标识当前本地化。将每个枚举元素的图标图像作为构造函数上的第二个参数传递。或者在enum类上编写代码以查找图标图像。当然,在我们的enum类中添加一个
getFlag
方法,以返回所述标志图像。

是的,我知道如何创建重源捆绑包,我将为每种语言创建一个。但是,以某种方式将我的应用程序支持的所有语言存储在一个数组/数组列表中,这是一个明智的想法吗?那么,每当我想要获得自定义资源或其他东西时,我就不必创建新的locale对象了?是的,这样做是有意义的。您可以定义枚举并提供工厂方法来加载资源束,然后强制用户选择枚举中定义的值。每当您添加一个以上的资源时,您都可以在enum中添加一个条目,以便客户端可以使用它。好的,听起来不错。你能解释一下我是如何创建工厂方法的吗?不太清楚您的想法是什么……方法和实践取决于您的程序运行的环境。它是桌面应用程序吗?安卓应用程序?网络应用?例如,对于台式机和移动设备,期望系统默认区域设置与用户期望的匹配是合理的,但对于web appRelated:Awesome answer则不然!谢谢你的解释。