我正在进行这项任务,即使用命令行界面。我使用一个简单的switch语句来创建这个命令行界面的控件,但是当我添加国际化支持作为我的赋值的一部分时,由于变量需要保持不变,我的switch语句已经崩溃。我该如何解决这个问题?
public class Editor {
private boolean running = true;
public static ArrayList<String> command = new ArrayList<String>();
Locale enLocale = new Locale("en", "GB");
ResourceBundle messages = ResourceBundle.getBundle("BaseBundle", enLocale);
String open = messages.getString("open");
String saveas = messages.getString("saveas");
String put = messages.getString("put");
String rot90 = messages.getString("rot90");
String mono = messages.getString("mono");
String help = messages.getString("help");
String quit = messages.getString("quit");
String look = messages.getString("look");
String undo = messages.getString("undo");
private String get = messages.getString("get");
Parser parser = new Parser();
public Editor() {
}
public void run() {
System.out.println("fotoshop");
while (running) {
command = parser.readInput();
interpret(command);
}
System.out.println("fotoshop exiting");
}
public void interpret(ArrayList<String> command) {
switch (command.get(0)) {
case open: OpenCommand.execute();
case saveas: SaveCommand.execute();
case put: PutCommand.execute();
case get: GetCommand.execute();
case rot90: ApplyRot90.execute();
case mono: ApplyMono.execute();
case help: HelpCommand.execute();
case quit: running = false;
case look: LookCommand.execute();
case undo;
}
}
}
答案 0 :(得分:2)
我对Java的国际化不是很熟悉,但我认为你应该使用的一般模式是这样的:
switch
换句话说,维护某种类型的地图,它可以将您想要支持的任何语言的命令映射到命令英语语言命令。然后,重构您的String input = parser.readInput();
String command = i18Map.get(input);
switch (command.get(0)) {
case "open": OpenCommand.execute();
case "saveas": SaveCommand.execute();
case "put": PutCommand.execute();
case "get": GetCommand.execute();
// etc.
}
语句以打开那些英语常量而不是变量:
<select class="bookly-select-mobile bookly-js-select-employee">
<option value="">Any</option>
<option value="1">Brandon Davis</option>
<option value="2">Ryan Floyd</option>
</select>
答案 1 :(得分:0)
您是否看过以下技巧来实现动态切换? 这可能是一种矫枉过正,但值得一看。
您可以使用String而不是Integer来定义它,以将其映射到应用程序应支持的不同语言中的不同操作。
java-tip-3-how-to-implement-dynamic-switch
class Switcher {
private Map<Integer, Command> caseCommands;
private Command defaultCommand;
private Command getCaseCommandByCaseId(Integer caseId) {
if (caseCommands.containsKey(caseId)) {
return caseCommands.get(caseId);
} else {
return defaultCommand;
}
}
public Switcher() {
caseCommands = new HashMap<Integer, Command>();
setDefaultCaseCommand(new DoNothingCommand());
}
public void addCaseCommand(Integer caseId, Command caseCommand) {
caseCommands.put(caseId, caseCommand);
}
public void setDefaultCaseCommand(Command defaultCommand) {
if (defaultCommand != null) {
this.defaultCommand = defaultCommand;
}
}
public void on(Integer caseId) {
Command command = getCaseCommandByCaseId(caseId);
command.execute();
}
}
您的主要课程:
public class Main {
public static void main(String[] args) {
Switcher switcher = new Switcher();
switcher.addCaseCommand(1, new Command() {
@Override
public void execute() {
System.out.println("Command on {id: 1}");
}
});
switcher.addCaseCommand(2, new Command() {
@Override
public void execute() {
System.out.println("Command on {id: 2}");
}
});
switcher.addCaseCommand(3, new Command() {
@Override
public void execute() {
System.out.println("Command on {id: 3}");
}
});
switcher.setDefaultCaseCommand(new Command() {
@Override
public void execute() {
System.out.println("Command on {default}");
}
});
for (int i = 1; i <= 4; i++) {
switcher.on(i);
}
}
}
//输出
Command on {id: 1}
Command on {id: 2}
Command on {id: 3}
Command on {default}
甚至更好地避免在hashmap中直接硬编码所有消息,因此在添加新语言支持时必须重新编译更改代码
将示例程序国际化
如果您查看国际化的源代码,您会注意到这一点 硬编码的英文消息已被删除。因为消息 不再是硬编码的,因为语言代码是在 运行时,可以在全球范围内分发相同的可执行文件没有 本地化需要重新编译。该计划已经 国际化。
您可能想知道消息文本发生了什么或者是什么 语言和国家代码的意思。别担心。你将了解到 当您逐步完成国际化过程时,这些概念 示例程序。
<强> 1。创建属性文件
属性文件存储有关a特征的信息 程序或环境。属性文件采用纯文本格式。您 可以使用几乎任何文本编辑器创建文件。
在示例中,属性文件存储了可翻译文本 要显示的消息。在该计划国际化之前, 这段文字的英文版本是硬编码的
System.out.println
陈述。默认属性文件,即 名为MessagesBundle.properties,包含以下行:
greetings = Hello
farewell = Goodbye
inquiry = How are you?
现在 消息在属性文件中,它们可以被翻译成 各种语言。不需要更改源代码。该 法语翻译器创建了一个名为的属性文件MessagesBundle_fr_FR.properties
,其中包含以下行:
greetings = Bonjour.
farewell = Au revoir.
inquiry = Comment
allez-VOUS?请注意,等号右侧的值 已翻译,但左侧的键没有 改变。这些键不能更改,因为它们将被引用 当你的程序获取翻译的文本时。属性文件的名称很重要。例如,名称
MessagesBundle_fr_FR.properties
文件包含fr语言代码 和FR国家代码。创建时也使用这些代码 区域设置对象。<强> 2。定义区域设置
Locale对象标识特定语言和国家/地区。该 以下语句定义语言为英语的语言环境 而这个国家就是美国:
aLocale = new Locale("en","US");
下一个示例创建Locale 加拿大和法国的法语对象:
caLocale = new Locale("fr","CA");
frLocale = new Locale("fr","FR");
该计划非常灵活。而不是使用硬编码语言和 国家/地区代码,程序在运行时从命令行获取它们 时间:
String language = new String(args[0]);
String country = new String(args[1]);
currentLocale = new Locale(language, country);
区域设置 对象只是标识符。定义区域设置后,将其传递给 执行有用任务的其他对象,例如格式化日期和 数字。这些对象因其行为而对区域设置敏感 根据Locale的不同而不同。 ResourceBundle就是一个例子 区域设置敏感对象。第3。创建ResourceBundle
ResourceBundle对象包含特定于语言环境的对象。你用 ResourceBundle对象用于隔离区域设置敏感数据,例如 可翻译的文本。在示例程序中,支持ResourceBundle 由包含我们想要的消息文本的属性文件 显示。
ResourceBundle创建如下:
messages = ResourceBundle.getBundle(&#34; MessagesBundle&#34;,currentLocale); 传递给getBundle方法的参数标识了哪些属性 文件将被访问。第一个参数MessagesBundle引用 这个属性文件系列:
MessagesBundle_en_US.properties MessagesBundle_fr_FR.properties MessagesBundle_de_DE.properties Locale,这是第二个 getBundle的参数,指定哪个MessagesBundle文件 选择。创建区域设置时,语言代码和国家/地区 代码被传递给它的构造函数。注意语言和 国家/地区代码按照属性名称中的MessagesBundle进行操作 文件。
现在你所要做的就是从中获取翻译的消息 ResourceBundle中。
<强> 4。从ResourceBundle
获取文本属性文件包含键值对。价值观包括 程序将显示的翻译文本。你指定了 从ResourceBundle获取已翻译的消息时的密钥 使用getString方法。例如,要检索消息 通过问候键标识,您可以按如下方式调用getString:
String msg1 = messages.getString(&#34; greetings&#34;);示例程序使用 关键的问候,因为它反映了消息的内容,但是 它可能使用了另一个String,例如s1或msg1。只记得 密钥在程序中是硬编码的,它必须存在于 属性文件。如果您的翻译人员意外修改了密钥 属性文件,getString无法找到消息。
<强>结论强>
那就是它。如您所见,国际化程序也不是 难。它需要一些规划和一些额外的编码,但是 好处是巨大的。为您提供概述 国际化进程,本课的示例程序是 故意保持简单。当您阅读以下课程时,您将会这样做 了解更高级的国际化功能 Java编程语言。
来源官方文件:https://docs.oracle.com/javase/tutorial/i18n/intro/steps.html
答案 2 :(得分:0)
使用if else语句
示例强>
String com = command.get(0);
if (com.equals(open)) {
OpenCommand.execute()
} else if (com.equals(saveas)) {
SaveCommand.execute();
} ...
答案 3 :(得分:0)
执行此操作的一种方法是使用Map
,其中键是国际化字符串,值是您要执行的命令。因此,假设所有不同的Command
类(OpenCommand
,SaveCommand
等)都有一个公共子类型Command
,其中声明了execute
方法,您可以像这样填补地图。
Map<String,Command> commandsByInternationalisedString = new HashMap<String,Command>();
Locale enLocale = new Locale("en", "GB");
ResourceBundle messages = ResourceBundle.getBundle("BaseBundle", enLocale);
commandsByInternationalisedString.add(messages.getString("open"), new OpenCommand());
commandsByInternationalisedString.add(messages.getString("saveas"), new SaveAsCommand());
commandsByInternationalisedString.add(messages.getString("put"), new PutCommand());
所以现在你有一个带有Command
对象的地图,对应于用户可能输入的任何命令。要使用它,你可以这样做。
public void interpret(ArrayList<String> command) {
Command toExecute = commandsByInternationalisedString.get(command.get(0));
if (toExecute != null ) {
toExecute.execute();
} else {
System.out.println("That's not a valid command");
}
}