自定义资源密钥生成以促进向后兼容性



我最近刚刚发现,您可以将资源的键从默认的"方法名称";方法转换为自定义指定的键。

我现在正在考虑将格式切换为";点分隔的";格式(通常在Java项目中使用)。

我知道,这可以通过使用@Key("my.new.key")注释或使用@GenerateKeys注释提供自定义KeyGenerator来实现。

问题是,我正在寻找一个既支持我的新格式又支持旧格式的解决方案。这是向后兼容性所必需的。我向公众发布我的工具,他们可以提供自己的属性文件(带有自定义内容)。这意味着我不能更改它们的密钥以匹配我的新格式。

我现在正在寻找一个使用新密钥(如果可用)并在必要时返回到旧密钥的解决方案。

我觉得我很聪明,想出了这个KeyGenerator:

public class MyKeyGenerator implements KeyGenerator
{
    private PropertyResourceBundle bundle;
    
    @Override
    public String generateKey(Message msg)
    {
        if(bundle == null)
        {
            try
            {
                File file = urlToResourceFile(Text.class.getName()); /* Finds the properties file */
                bundle = new PropertyResourceBundle(new FileInputStream(file));
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
        }
        
        String key = msg.getKey();
        
        if(key != null)
        {
            if(bundle.containsKey(key))
                return key;
        }
        
        return msg.getMethodName();
    }
}

它将检查新密钥是否存在于属性文件中。如果是,请将其退回,如果不是,请退回旧钥匙。

然而,我收到的是这个错误:

Computing all possible rebind results for 'my.package.here.i18n.Text'
        Rebinding my.package.here.i18n.Text
        Invoking generator com.google.gwt.i18n.rebind.LocalizableGenerator
            Processing interface my.package.here.i18n.Text
                Generating method body for generalSuccess()
                    [ERROR] No resource found for key 'general.success'
com.google.gwt.i18n.rebind.AbstractResource$MissingResourceException: No resource found for key 'general.success'
    at com.google.gwt.i18n.rebind.MessagesMethodCreator.createMethodFor(MessagesMethodCreator.java:1086)
    at com.google.gwt.i18n.rebind.AbstractLocalizableImplCreator.delegateToCreator(AbstractLocalizableImplCreator.java:501)
    at com.google.gwt.i18n.rebind.MessagesImplCreator.emitMethodBody(MessagesImplCreator.java:92)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.genMethod(AbstractGeneratorClassCreator.java:277)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.emitMethods(AbstractGeneratorClassCreator.java:239)
    at com.google.gwt.user.rebind.AbstractGeneratorClassCreator.emitClass(AbstractGeneratorClassCreator.java:118)
    at com.google.gwt.i18n.rebind.AbstractLocalizableImplCreator.generateConstantOrMessageClass(AbstractLocalizableImplCreator.java:225)
    at com.google.gwt.i18n.rebind.LocalizableGenerator.generate(LocalizableGenerator.java:151)
    at com.google.gwt.i18n.rebind.LocalizableGenerator.generate(LocalizableGenerator.java:124)
    at com.google.gwt.core.ext.IncrementalGenerator.generateNonIncrementally(IncrementalGenerator.java:40)
    at com.google.gwt.dev.javac.StandardGeneratorContext.runGeneratorIncrementally(StandardGeneratorContext.java:676)
    at com.google.gwt.dev.cfg.RuleGenerateWith.realize(RuleGenerateWith.java:41)
    at com.google.gwt.dev.shell.StandardRebindOracle$Rebinder.rebind(StandardRebindOracle.java:79)
    at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:276)
    at com.google.gwt.dev.shell.StandardRebindOracle.rebind(StandardRebindOracle.java:265)
    at com.google.gwt.dev.DistillerRebindPermutationOracle.getAllPossibleRebindAnswers(DistillerRebindPermutationOracle.java:91)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleGwtCreate(UnifyAst.java:387)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.handleMagicMethodCall(UnifyAst.java:465)
    at com.google.gwt.dev.jjs.impl.UnifyAst$UnifyVisitor.endVisit(UnifyAst.java:255)
    at com.google.gwt.dev.jjs.ast.JMethodCall.traverse(JMethodCall.java:244)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:117)
    at com.google.gwt.dev.jjs.ast.JCastOperation.traverse(JCastOperation.java:65)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:117)
    at com.google.gwt.dev.jjs.ast.JDeclarationStatement.traverse(JDeclarationStatement.java:48)
    at com.google.gwt.dev.jjs.ast.JModVisitor$ListContextImmutable.traverse(JModVisitor.java:170)
    at com.google.gwt.dev.jjs.ast.JModVisitor.acceptWithInsertRemoveImmutable(JModVisitor.java:336)
    at com.google.gwt.dev.jjs.ast.JBlock.traverse(JBlock.java:83)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:138)
    at com.google.gwt.dev.jjs.ast.JVisitor.accept(JVisitor.java:134)
    at com.google.gwt.dev.jjs.ast.JMethodBody.traverse(JMethodBody.java:82)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.ast.JMethod.visitChildren(JMethod.java:449)
    at com.google.gwt.dev.jjs.ast.JMethod.traverse(JMethod.java:418)
    at com.google.gwt.dev.jjs.ast.JModVisitor.traverse(JModVisitor.java:361)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:273)
    at com.google.gwt.dev.jjs.ast.JModVisitor.accept(JModVisitor.java:265)
    at com.google.gwt.dev.jjs.impl.UnifyAst.mainLoop(UnifyAst.java:940)
    at com.google.gwt.dev.jjs.impl.UnifyAst.exec(UnifyAst.java:665)
    at com.google.gwt.dev.jjs.JavaToJavaScriptCompiler.precompile(JavaToJavaScriptCompiler.java:672)
    at com.google.gwt.dev.jjs.JavaScriptCompiler.precompile(JavaScriptCompiler.java:34)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:271)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:223)
    at com.google.gwt.dev.Precompile.precompile(Precompile.java:139)
    at com.google.gwt.dev.Compiler.run(Compiler.java:167)
    at com.google.gwt.dev.Compiler.run(Compiler.java:132)
    at com.google.gwt.dev.Compiler$1.run(Compiler.java:99)
    at com.google.gwt.dev.CompileTaskRunner.doRun(CompileTaskRunner.java:55)
    at com.google.gwt.dev.CompileTaskRunner.runWithAppropriateLogger(CompileTaskRunner.java:50)
    at com.google.gwt.dev.Compiler.main(Compiler.java:106)

这似乎表明,我的KeyGenerator要么只在@Key不存在的情况下使用,要么在执行KeyGenerator之前执行GWT检查。

有人知道怎么解决这个问题吗?或者也许有人知道另一个解决方案?

更新

刚刚在这里找到这个:

@Key(String key)

指定要在此特定方法的外部格式中使用的键如果未提供,它将基于上面讨论的@GenerateKeys注释生成。

这似乎让我的目标遥不可及。。。还有其他建议吗?

你的目标可能并非遥不可及,但肯定不是一个容易的目标。GWT编译com.google.GWT.i18n.rebind.LocalizableGenerator时,会调用并执行其i18n魔术。这包括检查导致所述异常的钥匙。好消息是生成器非常强大,您可以滚动自定义实现。坏消息是生成器编写起来有些复杂,并且没有很好的文档记录。官方文件只是简单地提到了发电机。

因此,在第一次尝试中,我建议用您自己的版本替换默认的LocalizableGenerator。在你自己的生成器版本中,你可以抑制异常并添加你自己的资源加载逻辑(你最终可能会覆盖更多的类…)。我确信你可以覆盖本地模块配置(XML文件)中调用的生成器。虽然我没有尝试过。

如果失败,我看到的唯一选项就是运行您自己的I18N实现。我指的是一个完整的注释,您自己的注释带有自定义生成器和链接器,以创建必要的输出。。。

最新更新