从属性文件键生成字符串常量

Posted

技术标签:

【中文标题】从属性文件键生成字符串常量【英文标题】:Generate string constants from properties file keys 【发布时间】:2015-09-23 04:11:32 【问题描述】:

我正在使用 .properties 文件进行消息国际化。例如:

HELLO_WORLD = Hello World
HELLO_UNIVERSE = Hello Universe

然后在 Java 代码中:

String foo = resourceBundle.getString("HELLO_WORLD");

"HELLO_WORLD" 这样的字符串文字是有问题的,因为它们容易出错并且不能自动完成。我想从属性文件中的键生成代码,如下所示:

public interface Messages  // Or abstract class with private constructor
    public static final String HELLO_WORLD = "HELLO_WORLD";
    public static final String HELLO_UNIVERSE = "HELLO_UNIVERSE";

然后像这样使用它:

String foo = resourceBundle.getString(Messages.HELLO_WORLD);

有没有标准的方法来做到这一点?我更喜欢 Maven 插件,但我可以手动运行的任何独立工具都足以满足我的需求。

【问题讨论】:

这听起来很像android开发中的资源系统……不知道能不能用于非Android项目? 你想使用这个owner.aeonbits.org/docs/welcome 吗?它还提供了其他有用的功能,您可能会感兴趣,例如重载和热重载。 【参考方案1】:

最好反过来:

public enum Message 
    HELLO_WORLD,
    HELLO_UNIVERSE;

    public String xlat(Locale locale) 
        resourceBundle.getString(toString(), locale);
    

从该枚举生成一个属性模板。如果您的基本语言位于单独的 ..._en.properties 中,则可以对新消息重复此操作。

可以使用 values() 来完成生成 - 无需解析。虽然也许您想为属性 cmets 等引入一些注释。

【讨论】:

【参考方案2】:

以下代码将在您的项目根目录中生成界面MyProperties,然后您可以在任何地方使用该界面。

public class PropertiesToInterfaceGenerator 

    public static void main(String[] args) throws IOException 

        Properties properties = new Properties();
        InputStream inputStream =PropertiesToInterfaceGenerator.class.getClassLoader().getResourceAsStream("xyz.properties");
        if(null != inputStream )
            properties.load(inputStream);
        
        generate(properties);
    


    public static void generate(Properties properties) 
        Enumeration e = properties.propertyNames();
        try 
            FileWriter aWriter = new FileWriter("MyProperties.java", true);
            aWriter.write("public interface MyProperties\n");
            while (e.hasMoreElements()) 
                String key = (String) e.nextElement();
                String val =  properties.getProperty(key);
                aWriter.write("\tpublic static String "+key+" = \""+val+"\";\n");
            
            aWriter.write(" \n");
            aWriter.flush();      
            aWriter.close();
        catch(Exception ex)
            ex.printStackTrace();
        
    

【讨论】:

为什么要追加到文件中? 如果您担心软件工程,请先阅读softwareengineering.stackexchange.com/questions/49572/…【参考方案3】:

没有,从来没有人编写过这样的插件,它具有您所开发的所有功能,因为:

国际化可能有很多条目,最终你会得到一个巨大的类、接口、枚举或其他任何东西,这很糟糕。 maven/gradle 插件会为您生成类,但仅在编译时。我看到你提到了自动完成,这意味着你也需要一个 IDE 插件,这意味着构建工具(gradle/ant/...)的插件是不够的。这些插件之间的交互可能容易出错。 在项目后期,如果您或您的同事想要一个新的翻译条目,您将不得不重新生成类。这有点累。

在处理国际化时,推荐使用 i18n 之类的东西。如果你不想要一个新的库或者你的项目很小,你可以选择使用 eclipse 的 externalize strings 函数,见

安卓:Externalize strings for Android project

其他:help.eclipse.org - Java development user guide > Reference > Wizards and Dialogs > Externalize Strings Wizard

【讨论】:

只与键有关,最好在代码中引用这些键而不用错字...

以上是关于从属性文件键生成字符串常量的主要内容,如果未能解决你的问题,请参考以下文章

JVM四种常量池全方位细致讲解 这一篇就够了~

警告:不推荐使用常量 ::Fixnum 生成新模型时

Jave运行时常量池是啥意思?

java8中字符串常量以及GC相应处理机制

cstdlib库

cstdlib库