Java 如何使用C10N库启用返回翻译字符串的类

Java 如何使用C10N库启用返回翻译字符串的类,java,internationalization,c10n,Java,Internationalization,C10n,我想使用来管理Java项目中的翻译,但我不知道如何使用它来支持类生成翻译字符串 请考虑以下单个语言示例: public interface Pet { public String getBreed(); } public class Dog implements Pet { private String breed; public Dog(String breed) { this.breed = breed; } public St

我想使用来管理Java项目中的翻译,但我不知道如何使用它来支持类生成翻译字符串

请考虑以下单个语言示例:

public interface Pet {
    public String getBreed();
}

public class Dog implements Pet {

    private String breed;

    public Dog(String breed) {
        this.breed = breed;
    }

    public String getBreed() {
        return this.breed;
    }

}
然后,我想更改以前的实现以支持i18n

因此,我可以使用C10N声明一些翻译:

public interface DogBreeds{
    @En("dalmatian")
    @It("dalmata")
    String dalmatian();

    @En("poodle")
    @It("barboncino")
    String poodle();
}
现在,我想在类中使用这些方法之一来返回翻译后的字符串。
其思想是以某种方式将方法传递给类,然后从类的方法调用它。
换句话说,该类应该能够基于当前语言环境返回正确的翻译,而当前语言环境在运行时可能会发生变化

public class Dog implements Pet {

    public Dog(??) {
        // the class should receive all the translations
        // related to a specific breed
    }

    public String getBreed() {
        // here I want to return the correct breed name translation,
        // based on the current locale
        return ??;
    }

}
Dog
类不应直接访问
dogbrides
接口。例如,
Dog
可能是库的一部分,而
dogbrides
可能在主项目中声明

Dog
类不应该只保存基于当前区域设置的一个翻译,而是保存所有可用的翻译,以便在区域设置更改时返回正确的翻译

这是一种干净的方法吗?
如果没有,还有什么选择?

我会尝试:

public class Dog implements Pet {
    private static final DogBreeds BREEDS = C10N.get(DogBreeds.class);    

    public Dog() {
        // no need to pass the translations to the constructor
    }

    public String getBreed() {
        // Since you're wanting to specify a message key dynamically,
        // you need to use getString instead of BREEDS.poodle().
        return BREEDS.getString(myBreed);
    }

}

如果您想将
dogbride
(主项目)和
Dog
(库)分开,那么考虑到您的主项目引用库(而不是相反),您需要在库中引入一些其他共享接口,比如说,
BreedNameProvider

public interface BreedNameProvider{
  String dalmatian();
  String poodle();
}
然后您可以将其传递给
Dog
类构造函数:

public class Dog implements Pet {
 private final BreedNameProvider bnp;
 public Dog(BreedNameProvider bnp) {
   this.bnp = bnp;
 }

 public String getBreed() {
   return bnp.poodle();
 }
}
BreedNameProvider
的实现可以在主项目中声明,因此可以安全地访问
dogbrides
接口

编辑:您可以使用更通用的
BreedNameProvider
,在运行时通过工作区域设置切换返回所需的翻译:

//Declared in your library
public interface BreedNameProvider{
  String getBreedName();
}

public class Dog implements Pet {
 private final BreedNameProvider bnp;
 public Dog(BreedNameProvider bnp) {
   this.bnp = bnp;
 }

 public String getBreed() {
   return bnp.getBreedName();
 }
}
在主项目中,当实例化不同类型的
狗时
只需传递
BreedNameProvider
的实现,该实现将返回所需品种的本地化字符串:

public class MainProject{
  private static final DogBreeds breeds = C10N.get(DogBreeds.class);

  public void createDogs(){
    //Create a poodle
    Dog poodle = new Dog(new BreedNameProvider(){
      @Override
      public String getBreedName(){
        return breeds.poodle();
      }
    });

    //Create dalmatian
    Dog dalmatian = new Dog(new BreedNameProvider(){
      @Override
      public String getBreedName(){
        return breeds.dalmatian();
      }
    });
  }
}
实际上,这相当于将方法“传递”给
Dog
构造函数,这正是您在原始帖子中要求的。在java中,这几乎是在不牺牲编译时安全性的情况下实现这一点的唯一方法

实现
BreedNameProvider
的另一种方法如下:

public class MainProject{
  private static final DogBreeds breeds = C10N.get(DogBreeds.class);

  class CodeBreedNameProvider implements BreedNameProvider{
    private final String breedCode;

    CodeBreedNameProvider(String breedCode){
      this.breedCode = breedCode;
    }

    @Override
    public String getBreedName(){
      switch(breedCode){
        case "poodle": return breeds.poodle();
        case "dalmatian": return breeds.dalmatian();
        //... more if needed
      }
      return "unknown breed code " + breedCode;
    }
  }

  public void createDogs(){
    //Create a poodle
    Dog poodle = new Dog(new CodeBreedNameProvider("poodle"));

    //Create dalmatian
    Dog dalmatian = new Dog(new CodeBreedNameProvider("dalmatian"));
  }
}

你看过主页上的文档了吗?它们明确地显示了该做什么。@chrylis是的,我做了,但不是我的问题不清楚,就是我不理解文档。我会再写一些细节。你的要求毫无意义。C10N的整个要点是类型安全的消息绑定,它要求您指定要从中查找的类型。如果你不想要类型安全,那么完全跳过C10N,只使用常规的消息资源包。请参阅我的编辑:类
不应该直接引用
狗种
接口可能我的问题不够清楚。我需要做的是实例化一只
Dog
,它从
dalmatian()
方法中获取品种名称,另一只使用
poodle()
(依此类推)。所以我不想传递整个界面,只想传递一个特定的翻译。如果这毫无意义,还有其他选择吗?例如,声明多个
C10N
接口并传递一个特定的接口…如果您在狗的实例化之前知道品种名称,您不能将品种名称传递给其构造器吗?如果直到运行时才知道名称,可以让更通用的BreedNameProvider#getBreedName()执行逻辑并返回适当的值。或者可能我没有理解这个问题,对吗?我不想根据当前区域设置只向类传递一个字符串。
Dog
类应该能够基于当前区域设置返回犬种名称,即使区域设置在运行时发生更改。我更新了我的问题,我希望它现在更清楚一点。请看我的答案中的编辑。希望这能把事情弄清楚。