Javaプログラミングにおいて、ソフトウェアの国際化(Internationalization, I18N)は、グローバルな市場で成功を収めるために欠かせない要素です。国際化対応とは、ソフトウェアが異なる言語や文化に対応できるように設計されることを意味します。このプロセスには、テキストの翻訳、日付や通貨フォーマットの調整、文化特有の機能の実装などが含まれます。
特にJavaでは、リソースバンドルと呼ばれる仕組みを利用することで、アプリケーションを複数の言語に対応させることが容易になります。リソースバンドルは、テキストやその他のリソースを言語ごとに分けて管理できるため、コードの中でのハードコーディングを避け、メンテナンス性の高い国際化対応が可能です。また、これをJavaのパッケージと組み合わせることで、整理された構造で国際化対応を実現できます。本記事では、Javaのパッケージとリソースバンドルを活用して、効果的に国際化対応を行う方法を詳しく解説します。
国際化対応の概要
国際化対応(Internationalization, I18N)は、ソフトウェア開発において、アプリケーションが異なる言語や文化的背景を持つユーザーに対して柔軟に対応できるようにするプロセスです。この対応は、ソフトウェアが特定の言語や地域のユーザーに向けたバージョンを作成する際に、最小限の変更で済むように設計されることを目指しています。
国際化対応が求められる背景には、グローバル市場での競争が激化し、多言語対応が必須となっていることがあります。企業は世界中のユーザーに自社製品を提供するため、製品が異なる言語や文化にスムーズに適応することが重要です。例えば、英語を母国語としないユーザーにとって、母国語で利用できるソフトウェアはユーザーエクスペリエンスを大幅に向上させます。
国際化対応には主に以下の要素が含まれます:
- テキストの翻訳:ユーザーインターフェースに表示される文字列を複数の言語に翻訳。
- 日付や通貨のフォーマット:地域ごとのフォーマットに合わせて表示。
- 文化特有の機能:文化的な差異に基づいた機能の実装。
国際化対応を効果的に行うことで、ソフトウェアはグローバルに展開可能となり、ユーザーの多様なニーズに応えることができます。本記事では、この国際化対応をJavaでどのように実装するかを、具体的な手法とともに紹介していきます。
Javaのパッケージ構造の理解
Javaのパッケージは、関連するクラスやインターフェースをグループ化するための機能で、コードの整理と管理を効率化する重要な要素です。パッケージを使用することで、名前空間を確立し、クラス名の重複を避けるとともに、ソフトウェアの構造を論理的に整理することができます。
パッケージは、ディレクトリの階層構造と連動しており、各パッケージは特定の機能や役割に応じてクラスをまとめる役割を果たします。例えば、あるアプリケーションで国際化対応を行う場合、言語リソースを管理するクラス群を「resources」パッケージにまとめ、UI関連のクラス群を「ui」パッケージにまとめることが考えられます。このように、パッケージを活用することで、プロジェクトの規模が大きくなった場合でも、構造が明確で理解しやすいコードベースを維持することができます。
また、パッケージはアクセス制御の観点からも重要です。クラスやメソッドのアクセスレベルを適切に設定することで、必要以上に外部に公開しないクラスやメソッドを制御でき、セキュリティや保守性が向上します。
国際化対応においては、リソースバンドルを適切なパッケージに配置することで、複数の言語や地域に対応したリソース管理を効率化できます。次のセクションでは、このパッケージとリソースバンドルをどのように組み合わせて国際化対応を実現するかを詳しく見ていきます。
リソースバンドルの基本概念
リソースバンドル(Resource Bundle)は、Javaで国際化対応を実現するための中心的な仕組みで、アプリケーションが異なる言語や地域に対応するためのテキストやその他のリソースを管理するための手段を提供します。リソースバンドルは、キーと値のペアで構成されるプロパティファイルとして実装され、各言語や地域ごとに異なるファイルが用意されます。
リソースバンドルは、特定の言語や地域に依存しないコードを記述する際に特に有用です。例えば、ユーザーインターフェースに表示するメッセージやラベル、エラーメッセージなどのテキストは、リソースバンドルを使用して外部化することで、言語ごとに異なるファイルから動的に読み込むことができます。これにより、コード内に直接テキストをハードコーディングする必要がなくなり、アプリケーションの保守性が大幅に向上します。
リソースバンドルは、通常、次の形式で定義されます:
- ベース名:リソースバンドルの共通部分(例:
Messages
)。 - 言語コード:言語を指定するコード(例:
_en
、_fr
)。 - 地域コード:地域を指定するコード(例:
_US
、_FR
)。
例えば、Messages_en_US.properties
というファイルは、米国英語向けのリソースバンドルを表します。このファイル内で、welcome.message=Welcome
のようにキーと値が定義されます。
Javaでは、ResourceBundle
クラスを使用してリソースバンドルを読み込み、適切な言語や地域に応じたテキストを取得します。これにより、同じコードベースで多言語対応を実現できるため、グローバル市場向けのソフトウェア開発が効率的に行えます。
次のセクションでは、このリソースバンドルを実際にどのように作成するか、その手順を詳しく解説します。
リソースバンドルの作成方法
リソースバンドルの作成は、Javaで国際化対応を行うための基本的なステップです。リソースバンドルは、通常、プロパティファイルとして定義され、各言語や地域ごとに異なるファイルを作成します。ここでは、リソースバンドルの具体的な作成手順を紹介します。
1. リソースバンドルのベースファイルを作成する
まず、デフォルト言語用のプロパティファイルを作成します。このファイルは、言語コードや地域コードを持たないベースファイルです。例えば、Messages.properties
という名前で作成します。このファイルには、アプリケーションで使用するすべてのテキストリソースのキーと対応するデフォルトの値が含まれます。
例:
welcome.message=Welcome to our application!
exit.prompt=Are you sure you want to exit?
2. 言語および地域ごとのプロパティファイルを作成する
次に、異なる言語や地域に対応するプロパティファイルを作成します。各ファイル名には、ベース名の後に言語コードや地域コードを付けます。例えば、英語(アメリカ)用のファイルはMessages_en_US.properties
、フランス語(フランス)用のファイルはMessages_fr_FR.properties
となります。
例:
Messages_en_US.properties
:
welcome.message=Welcome to our application!
exit.prompt=Are you sure you want to exit?
Messages_fr_FR.properties
:
welcome.message=Bienvenue dans notre application !
exit.prompt=Êtes-vous sûr de vouloir quitter ?
3. ファイルを適切なパッケージに配置する
作成したプロパティファイルは、Javaプロジェクト内の適切なパッケージに配置します。一般的には、リソースバンドル専用のパッケージ(例:com.example.resources
)を作成し、その中にプロパティファイルを保存します。これにより、リソースが整理され、他のコードと分離されて管理がしやすくなります。
4. `ResourceBundle`クラスを使用してリソースを読み込む
リソースバンドルを読み込むためには、ResourceBundle
クラスを使用します。例えば、以下のコードで適切なリソースバンドルを読み込み、テキストリソースを取得します。
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", Locale.US);
String welcomeMessage = bundle.getString("welcome.message");
System.out.println(welcomeMessage);
このコードでは、Locale.US
に基づいてMessages_en_US.properties
が読み込まれ、welcome.message
キーに対応する値「Welcome to our application!」が出力されます。
これで、Javaアプリケーションでリソースバンドルを使用した国際化対応ができるようになりました。次のセクションでは、リソースバンドルとパッケージをどのように組み合わせて国際化対応をさらに強化するかを解説します。
パッケージとリソースバンドルの組み合わせ
Javaで国際化対応を行う際、パッケージとリソースバンドルを組み合わせることで、より整理された構造でリソースを管理し、拡張性やメンテナンス性を向上させることができます。ここでは、その具体的な手法について解説します。
1. パッケージ構造の設計
国際化対応を行うプロジェクトでは、リソースバンドル専用のパッケージを作成し、関連するリソースファイルをその中に配置します。例えば、アプリケーションの他の部分と分離してリソースを管理するために、com.example.resources
というパッケージを作成することが考えられます。
このパッケージ内には、言語や地域ごとのプロパティファイルを配置します。例えば、英語とフランス語に対応するファイルを以下のように配置します。
com/example/resources/Messages.properties
com/example/resources/Messages_en_US.properties
com/example/resources/Messages_fr_FR.properties
このようにパッケージを使ってファイルを整理することで、特定の言語や地域に対応するリソースが明確に分かれ、管理しやすくなります。
2. リソースバンドルの優先順位
Javaでは、ResourceBundle.getBundle
メソッドを使用してリソースバンドルを読み込む際、指定されたロケールに最も適したリソースバンドルが自動的に選択されます。例えば、Locale.FRANCE
が指定された場合、Messages_fr_FR.properties
が優先的に読み込まれますが、もしこのファイルが存在しない場合は、Messages_fr.properties
やMessages.properties
といったより一般的なファイルが順次読み込まれます。
この仕組みにより、複数の言語や地域に対して柔軟に対応できるアプリケーションが構築可能です。
3. クラスベースのリソースバンドル
リソースバンドルはプロパティファイルだけでなく、クラスとしても実装できます。例えば、ListResourceBundle
を継承したクラスを作成することで、より複雑なロジックを含むリソースバンドルを実装できます。
public class Messages_en_US extends ListResourceBundle {
@Override
protected Object[][] getContents() {
return new Object[][] {
{"welcome.message", "Welcome to our application!"},
{"exit.prompt", "Are you sure you want to exit?"}
};
}
}
このクラスをcom.example.resources
パッケージに配置し、他のプロパティファイルと併用することで、柔軟なリソース管理が可能になります。
4. リソースバンドルの組み合わせによる拡張
特定の機能ごとに異なるリソースバンドルを作成し、それらを必要に応じて組み合わせることも可能です。例えば、UIメッセージ用、エラーメッセージ用、ヘルプメッセージ用など、異なるカテゴリごとにリソースバンドルを分けて管理することで、メンテナンスがしやすくなります。
まとめると、Javaのパッケージ構造とリソースバンドルを効果的に組み合わせることで、スケーラブルでメンテナンスしやすい国際化対応を実現できます。次のセクションでは、このリソースバンドルを実際に読み込み、アプリケーション内で利用する方法について説明します。
リソースバンドルの読み込みと利用
リソースバンドルを作成した後、それをJavaアプリケーション内で適切に読み込み、利用することで、国際化対応を実現します。ここでは、リソースバンドルの読み込み手順と、それを使用してアプリケーション内でテキストリソースを動的に表示する方法を解説します。
1. リソースバンドルの読み込み
Javaでは、ResourceBundle
クラスを使用してリソースバンドルを読み込みます。getBundle
メソッドを使用することで、指定したベース名とロケールに基づいて適切なリソースバンドルを取得できます。
Locale locale = new Locale("en", "US"); // 米国英語のロケールを指定
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", locale);
上記の例では、com.example.resources.Messages
というベース名を持つリソースバンドルが、指定されたLocale.US
に基づいて読み込まれます。これにより、Messages_en_US.properties
ファイルが存在する場合、そのファイルが優先的に使用されます。
2. リソースバンドルから値を取得する
リソースバンドルからテキストリソースを取得するには、getString
メソッドを使用します。キーを指定することで、対応する値を取得できます。
String welcomeMessage = bundle.getString("welcome.message");
System.out.println(welcomeMessage);
このコードを実行すると、welcome.message
キーに対応するテキストが出力されます。例えば、米国英語の設定では「Welcome to our application!」というメッセージが表示されます。
3. ロケールに応じたリソースの切り替え
アプリケーションで異なるロケールに応じてリソースを動的に切り替える場合、Locale
オブジェクトを変更してResourceBundle
を再取得します。これにより、ユーザーの言語設定に応じたメッセージを表示できます。
Locale localeFR = new Locale("fr", "FR"); // フランス語(フランス)のロケールを指定
ResourceBundle bundleFR = ResourceBundle.getBundle("com.example.resources.Messages", localeFR);
String welcomeMessageFR = bundleFR.getString("welcome.message");
System.out.println(welcomeMessageFR); // 「Bienvenue dans notre application !」が出力されます
このようにして、異なるロケールに基づいてメッセージやラベルなどを切り替えることが可能です。
4. リソースバンドルの利用の応用例
リソースバンドルを活用することで、アプリケーション内のさまざまな箇所で動的なテキスト表示が可能になります。例えば、エラーメッセージ、メニューのラベル、ボタンのテキストなど、ユーザーインターフェース全体を国際化対応にすることができます。
また、デフォルトのロケールを設定することで、特定のロケールが設定されていない場合でも、デフォルトのメッセージが表示されるようにすることができます。これにより、ユーザーが言語設定を持たない場合でも、適切なメッセージを提供できます。
Locale.setDefault(Locale.US); // デフォルトロケールを米国英語に設定
ResourceBundle defaultBundle = ResourceBundle.getBundle("com.example.resources.Messages");
String defaultWelcomeMessage = defaultBundle.getString("welcome.message");
System.out.println(defaultWelcomeMessage); // 米国英語のメッセージがデフォルトで出力されます
以上のように、リソースバンドルを効果的に利用することで、柔軟でスケーラブルな国際化対応を実現できます。次のセクションでは、地域ごとのリソースバンドル管理のポイントと具体的な実践例について解説します。
地域別のリソースバンドル管理
国際化対応を行う際には、言語や地域ごとに異なるリソースを適切に管理することが重要です。リソースバンドルを地域別に管理することで、ユーザーに対してより適切な情報を提供し、アプリケーションのユーザーエクスペリエンスを向上させることができます。ここでは、地域別のリソースバンドル管理のポイントと具体的な実践例を紹介します。
1. 地域ごとのリソースバンドルの構造
地域別のリソースバンドル管理では、各地域や言語に対応するプロパティファイルを作成し、それぞれの文化や言語に適したリソースを提供します。これにより、特定の地域や言語に向けたカスタマイズが可能になります。
例えば、以下のような構造でリソースバンドルを管理することが考えられます:
com/example/resources/Messages.properties // デフォルトのリソース
com/example/resources/Messages_en_US.properties // 米国英語用リソース
com/example/resources/Messages_en_GB.properties // 英国英語用リソース
com/example/resources/Messages_fr_FR.properties // フランス語(フランス)用リソース
このように各地域ごとにリソースを分けることで、細かな文化的な違いにも対応できるようになります。
2. フォールバック戦略の重要性
リソースバンドルを利用する際、指定されたロケールに対応するプロパティファイルが存在しない場合には、Javaは自動的にフォールバックメカニズムを使用して最も近いロケールのリソースバンドルを選択します。これにより、特定のロケール用のリソースバンドルが存在しない場合でも、アプリケーションが適切に動作することが保証されます。
例えば、Messages_en_AU.properties
が存在しない場合、Messages_en.properties
、さらにそれがなければMessages.properties
が使用されます。このフォールバックメカニズムを理解し、利用することで、リソースの管理がより柔軟になります。
3. 地域ごとの文化的配慮
地域別にリソースバンドルを管理する際には、単に言語を翻訳するだけでなく、文化的なニュアンスや慣習を考慮することが重要です。例えば、同じ「OK」ボタンのラベルでも、地域によっては異なる言い回しが好まれることがあります。また、日付や数値のフォーマットも地域ごとに異なるため、リソースバンドルでこれらのフォーマットを管理することが推奨されます。
# 米国英語用リソース
date.format=MM/dd/yyyy
currency.symbol=$
# フランス語用リソース
date.format=dd/MM/yyyy
currency.symbol=€
このように、地域ごとの文化や慣習に応じたリソースを用意することで、ユーザーの期待に沿ったエクスペリエンスを提供できます。
4. 実践例: 地域別メッセージの表示
地域ごとのリソースバンドルを活用して、アプリケーション内で異なるメッセージやフォーマットを動的に切り替えることが可能です。例えば、以下のコードでは、ユーザーのロケールに応じたメッセージを表示します。
Locale localeFR = new Locale("fr", "FR");
ResourceBundle bundleFR = ResourceBundle.getBundle("com.example.resources.Messages", localeFR);
String dateFormat = bundleFR.getString("date.format");
String currencySymbol = bundleFR.getString("currency.symbol");
System.out.println("Date Format: " + dateFormat);
System.out.println("Currency Symbol: " + currencySymbol);
このコードをフランスのロケールで実行すると、日付フォーマットが「dd/MM/yyyy」、通貨シンボルが「€」と表示されます。同様に、他のロケールでも適切なリソースが使用されます。
まとめると、地域別のリソースバンドル管理を適切に行うことで、アプリケーションはより多様な文化や言語に対応でき、ユーザーにとって使いやすいソフトウェアとなります。次のセクションでは、国際化対応を効果的にテストし、デバッグする方法について解説します。
応用: 国際化対応のためのデバッグとテスト
国際化対応を実施する際には、単にリソースバンドルを作成するだけでなく、その実装が正しく機能しているかを徹底的にテストし、デバッグすることが不可欠です。ここでは、国際化対応のテストとデバッグを効果的に行うための戦略を紹介します。
1. 各ロケールのテスト環境設定
国際化対応をテストするためには、複数のロケールに対応するテスト環境を設定する必要があります。Javaでは、Locale
クラスを使用して、異なるロケールをシミュレーションすることができます。例えば、テストスクリプト内で異なるロケールを指定し、そのロケールに対応するリソースバンドルが正しく読み込まれるかを確認します。
public void testResourceBundleForLocale(Locale locale) {
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", locale);
String message = bundle.getString("welcome.message");
System.out.println("Locale: " + locale.toString() + " - Message: " + message);
}
// テスト実行例
testResourceBundleForLocale(Locale.US);
testResourceBundleForLocale(Locale.FRANCE);
このように、各ロケールでメッセージが正しく表示されるかを確認することで、リソースバンドルが正しく設定されているかをチェックできます。
2. 境界ケースと異常系のテスト
国際化対応では、異常なロケールや存在しないロケールが指定された場合の動作もテストする必要があります。これには、存在しないリソースバンドルが指定されたときのフォールバック動作や、ロケールが未設定の状態でのデフォルトリソースの使用などが含まれます。
// 存在しないロケールを指定してテスト
Locale invalidLocale = new Locale("xx", "XX");
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", invalidLocale);
String message = bundle.getString("welcome.message");
System.out.println("Message with invalid locale: " + message);
このテストでは、指定されたロケールが存在しない場合に、デフォルトのリソースバンドルが使用されるかどうかを確認します。これにより、アプリケーションがどのようにフォールバックするかを検証できます。
3. 自動化テストの導入
国際化対応のテストを効率化するために、自動化テストを導入することが推奨されます。JUnitなどのテストフレームワークを使用して、各ロケールに対するテストケースを自動化することで、テストの漏れを防ぎ、開発サイクル全体の生産性を向上させることができます。
@Test
public void testMessagesForAllLocales() {
Locale[] locales = { Locale.US, Locale.FRANCE, new Locale("es", "ES") };
for (Locale locale : locales) {
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", locale);
assertNotNull("Bundle should not be null", bundle);
assertTrue("Welcome message should not be empty", !bundle.getString("welcome.message").isEmpty());
}
}
このような自動化テストを実装することで、複数のロケールに対して一貫したテストが行え、リソースバンドルの品質を確保できます。
4. ログとデバッグメッセージの活用
国際化対応のデバッグにおいては、適切なログとデバッグメッセージを活用することが重要です。リソースバンドルの読み込み状況や、キーの存在チェックなどをログ出力することで、どの箇所で問題が発生しているかを迅速に特定できます。
try {
ResourceBundle bundle = ResourceBundle.getBundle("com.example.resources.Messages", Locale.US);
String message = bundle.getString("welcome.message");
System.out.println("Message: " + message);
} catch (MissingResourceException e) {
System.err.println("Missing resource: " + e.getKey());
}
このコードは、リソースが見つからない場合にエラーメッセージを表示し、問題を特定するのに役立ちます。ログファイルを活用することで、デバッグの効率が向上します。
5. ユーザーテストの実施
技術的なテストだけでなく、実際のユーザーを対象としたテストも重要です。特に、多文化対応が求められる場合には、異なる地域のユーザーによるテストを実施し、文化的な違いに起因する問題がないかを確認します。これにより、実際の使用状況に基づいたフィードバックを得ることができ、より高品質な国際化対応が実現できます。
まとめると、国際化対応を成功させるためには、各ロケールに対する徹底的なテストとデバッグが不可欠です。これにより、アプリケーションがグローバルなユーザーにとっても使いやすいものになるでしょう。次のセクションでは、国際化対応を実装する具体的な多言語対応の実践例を紹介します。
演習: 多言語対応の実装例
ここでは、Javaアプリケーションで多言語対応を実装する具体的な例を通じて、リソースバンドルの活用方法をさらに深く理解します。実際のコードを使用して、異なる言語でのメッセージ表示を動的に切り替える方法を学びます。
1. プロジェクトの準備
まず、簡単なJavaコンソールアプリケーションを作成します。このアプリケーションでは、ユーザーの選択した言語に応じて、異なるメッセージを表示します。必要なファイルは、以下のように構成します:
src/
└── com/
└── example/
└── i18n/
├── Main.java
└── resources/
├── Messages.properties
├── Messages_en_US.properties
└── Messages_fr_FR.properties
2. リソースバンドルの作成
まず、デフォルトのメッセージを定義したMessages.properties
ファイルを作成します。このファイルには、アプリケーションで使用するメッセージのキーと値が含まれます。
# Messages.properties
welcome.message=Welcome to our application!
exit.message=Thank you for using our application!
次に、英語(米国)とフランス語(フランス)用のリソースバンドルを作成します。
# Messages_en_US.properties
welcome.message=Welcome to our application!
exit.message=Thank you for using our application!
# Messages_fr_FR.properties
welcome.message=Bienvenue dans notre application !
exit.message=Merci d'utiliser notre application !
3. 多言語対応のメインプログラム
次に、Main.java
ファイルを作成し、ユーザーの選択に応じて言語を切り替えるコードを実装します。
package com.example.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.println("Select language (1: English, 2: French): ");
int choice = scanner.nextInt();
Locale locale;
if (choice == 2) {
locale = Locale.FRANCE;
} else {
locale = Locale.US;
}
ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.resources.Messages", locale);
System.out.println(bundle.getString("welcome.message"));
// アプリケーションのロジックがここに続く
System.out.println(bundle.getString("exit.message"));
}
}
このコードでは、ユーザーが言語を選択し、その選択に基づいて適切なリソースバンドルが読み込まれます。英語を選んだ場合はMessages_en_US.properties
が、フランス語を選んだ場合はMessages_fr_FR.properties
が使用されます。
4. アプリケーションの実行と確認
プロジェクトをビルドして実行すると、ユーザーは言語を選択でき、選択した言語に対応するメッセージが表示されます。
実行例:
Select language (1: English, 2: French): 2
Bienvenue dans notre application !
Merci d'utiliser notre application !
フランス語を選択した場合、上記のようにフランス語のメッセージが表示されます。同様に、英語を選択すると、英語のメッセージが表示されます。
5. 演習のまとめと応用
この演習では、Javaのリソースバンドルを使用して多言語対応を実装する基本的な手法を学びました。これを応用することで、より大規模なアプリケーションにおいても、簡単に多言語対応を実装できます。
また、異なる地域や文化に対応したリソースバンドルを作成することで、ユーザーエクスペリエンスを向上させ、グローバルな市場に対応するアプリケーションを構築することが可能です。さらに、リソースバンドルと外部ファイルやデータベースを組み合わせることで、動的なコンテンツ管理を実現することもできます。
次のセクションでは、これまでの内容をまとめ、Javaでの国際化対応の重要性とその効果的な実装方法を再確認します。
まとめ
本記事では、Javaを使用した国際化対応の重要性と具体的な実装方法について解説しました。Javaのパッケージ構造とリソースバンドルを効果的に組み合わせることで、グローバルな市場に対応できる柔軟でスケーラブルなアプリケーションを構築できることがわかりました。
国際化対応の基本的な概念から、リソースバンドルの作成方法、地域別のリソース管理、テストとデバッグの重要性、そして実際の多言語対応の実装例に至るまで、幅広くカバーしました。これらの手法を適切に活用することで、異なる文化や言語を持つユーザーに対しても、最適なエクスペリエンスを提供できるアプリケーションを開発することができます。
今後のプロジェクトでこれらの知識を活用し、より多くのユーザーに喜ばれるソフトウェアを作成してください。
コメント