🔄 「言葉蔵」&「ローカル漢字変換エンジン」両対応クライアント開発マニュアル
本ドキュメントでは、SKK形式を共通言語とする「言葉蔵 (Kotobagura)」と「ローカル漢字変換エンジン」の両方に対して、動的に切り替え・フォールバック対応できるクライアントアプリ(Chrome拡張機能やWebアプリ)の実装方法を解説します。
1. 📌 各エンジンの拡張機能 ID
メッセージング(chrome.runtime.sendMessage)で通信を行う際、それぞれの識別用IDを定義します。
- 言葉蔵 (Kotobagura): ID
jlalooojpaebmgahmikbgnnomdcmhgap
- ローカル漢字変換エンジン: ID
cddamopplhdhbpgphpnaineilgecdiaa
2. 🤝 両APIの完全互換性(mode: "localengine")
言葉蔵とローカルエンジンは、コアとなる変換機能のインターフェースが完全に統一されています。さらに、言葉蔵の CONVERT リクエスト時に mode: "localengine" を指定することで、どちらのエンジンにリクエストを送っても全く同じデータ構造(配列)でレスポンスを受け取ることが可能です。
【出力データ例: mode: "localengine" 指定時(両エンジン共通)】
{
"success": true,
"data": [
[
"なごや",
[ "名古屋", "名護や", "なごや" ]
]
]
}
3. ⚖️ APIの相違点と固有機能
各エンジンは役割が異なるため、UIや特定機能に関する固有のAPIを持っています。これらの機能を利用する際は、現在アクティブなエンジンを判別して処理を分岐させる必要があります。
| 機能 / 特徴 |
言葉蔵 (フロント・ハイブリッド型) |
ローカル (バックエンド・特化型) |
| 通信とアーキテクチャ |
クラウドAPI(Google/Yahoo)とローカル辞書を統合したハイブリッド仕様。 |
完全オフライン。外部通信は一切なく、通信遅延や利用制限なし。 |
| メモ帳の制御 API |
搭載: TOGGLE_MEMO_PAD や SET_MEMO_TEXT などを使い、外部からテキストの読み書きが可能。 |
非搭載: メモ帳機能自体が存在しません。 |
| 強制UI制御 API |
非搭載: ブラウザ標準のフォーカス検知に依存します。 |
搭載: SHOW_KEYBOARD や SET_DUMMY_IME_ENABLED が可能。 |
| パネル表示 API |
OPEN_HISTORY_PANEL (履歴パネルを開く) |
OPEN_MANAGEMENT_PANEL (総合管理パネルを開く) |
4. 💻 実用的な両対応クライアント実装サンプル (JavaScript)
互換モード(mode: "localengine")を使用し、クライアント側でのパース処理(データ整形の分岐)を不要にしたシンプルで堅牢なラッパー関数の実装例です。
/**
* どちらのエンジンにも対応した汎用変換クライアント
* @param {string} engineId - 対象の拡張機能ID
* @param {string} text - 変換したいひらがな、またはローマ字
* @returns {Promise<Array<string>>} 変換候補の文字列配列
*/
async function fetchFromEngine(engineId, text) {
return new Promise((resolve, reject) => {
// スリープ復帰や通信遅延を考慮し、1500msでタイムアウトを設定
const timeout = setTimeout(() => reject(new Error("Engine request timeout")), 1500);
chrome.runtime.sendMessage(
engineId,
{
action: "CONVERT",
text: text,
mode: "localengine", // ★ 両エンジンで共通の配列フォーマットを強制する
useRomaji: true, // ローマ字入力を自動でひらがなに変換
separateParticle: true // 助詞の自動切り離しを有効化
},
(response) => {
clearTimeout(timeout);
// 拡張機能が未インストール、または通信エラーの場合
if (chrome.runtime.lastError) {
return reject(new Error("Engine not found: " + chrome.runtime.lastError.message));
}
// エンジン側の処理エラー
if (!response || !response.success || !response.data) {
return reject(new Error("Engine processing failed"));
}
// mode: "localengine" を指定しているため、パーサーは不要で直接配列を取り出せる
const candidates = (response.data[0] && Array.isArray(response.data[0][1]))
? response.data[0][1] : [];
resolve(candidates);
}
);
});
}
5. 🔍 起動時の自動検出・フォールバック実装
ユーザーがどちらのエンジンを導入しているか分からない場合や、優先順位をつけて自動で切り替えたい場合に有効な「自動検出(PING)」のサンプルです。
// 優先順位に応じたエンジンIDの候補リスト
const ENGINE_IDS = {
kotobagura: "jlalooojpaebmgahmikbgnnomdcmhgap",
localEngine: "cddamopplhdhbpgphpnaineilgecdiaa"
};
let activeEngineId = null;
/**
* 導入されているエンジンを自動検出する
*/
async function detectActiveEngine() {
for (const [name, id] of Object.entries(ENGINE_IDS)) {
if (await checkPing(id)) {
activeEngineId = id;
console.log(`[OK] アクティブなエンジンを検出しました: ${name} (${id})`);
return id;
}
}
console.warn("[WARN] 利用可能な変換エンジンが見つかりませんでした。");
return null;
}
/**
* PINGによる生存確認
*/
function checkPing(targetId) {
return new Promise((resolve) => {
chrome.runtime.sendMessage(targetId, { action: "PING" }, (res) => {
if (chrome.runtime.lastError || !res || !res.success) {
resolve(false);
} else {
resolve(true);
}
});
});
}
💡 ヒント:言葉蔵固有のメタデータ(sources等)を利用したい場合
もし言葉蔵が返す「どの辞書からヒットしたか」等のリッチな情報が必要な場合は、mode: "localengine" を指定せず、デフォルトのレスポンス(response.full_sentence_candidates)を受け取るようにし、エンジンに応じてデータを取り出す専用のパーサーを実装してください。