Skip to content

Commit a6921e3

Browse files
许君山许君山
authored andcommitted
feat: add romaji support using wanakana
1 parent 6d0a5af commit a6921e3

4 files changed

Lines changed: 41 additions & 11 deletions

File tree

backend/package-lock.json

Lines changed: 12 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

backend/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"dependencies": {
1212
"cors": "^2.8.5",
1313
"express": "^4.18.2",
14-
"kuromoji": "^0.1.2"
14+
"kuromoji": "^0.1.2",
15+
"wanakana": "^5.3.1"
1516
}
1617
}

backend/server.js

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import express from 'express';
22
import cors from 'cors';
33
import kuromoji from 'kuromoji';
4+
import * as wanakana from 'wanakana';
45
import { conjugate } from './conjugationEngine.js';
56

67
const app = express();
@@ -26,7 +27,15 @@ kuromoji.builder({ dicPath: 'node_modules/kuromoji/dict' }).build((err, _tokeniz
2627
function detectVerbType(verb) {
2728
if (!tokenizer) throw new Error('Tokenizer not ready');
2829

29-
const tokens = tokenizer.tokenize(verb);
30+
// 处理罗马音输入,将其转换为平假名
31+
const hiraganaVerb = wanakana.toHiragana(verb);
32+
33+
// 特殊情况硬编码:カ变动词(来る / くる)
34+
if (hiraganaVerb === 'くる' || hiraganaVerb === '来る') {
35+
return 'KURU';
36+
}
37+
38+
const tokens = tokenizer.tokenize(hiraganaVerb);
3039
if (tokens.length === 0) return null;
3140

3241
// 对于像 勉強する 这样的词,动词部分在最后
@@ -60,21 +69,31 @@ app.get('/api/conjugate', (req, res) => {
6069
});
6170
}
6271

72+
// 处理罗马音,转换成平假名
73+
// 比如:nomu -> のむ,taberu -> たべる
74+
// 原有的汉字会被保留(如 飲む 不变)
75+
const processedVerb = wanakana.toHiragana(verb);
76+
6377
// 如果前端没有传 type,就用 kuromoji 自动推断
6478
if (!type) {
6579
if (!tokenizer) {
6680
return res.status(503).json({ error: 'Dictionary is initializing, please try again later.' });
6781
}
68-
type = detectVerbType(verb);
82+
type = detectVerbType(processedVerb);
6983
if (!type) {
7084
return res.status(400).json({
71-
error: `Could not automatically detect verb type for '${verb}'. Please ensure it is a valid dictionary form Japanese verb or provide the type manually.`
85+
error: `Could not automatically detect verb type for '${verb}' (parsed as '${processedVerb}'). Please ensure it is a valid dictionary form Japanese verb or provide the type manually.`
7286
});
7387
}
7488
}
7589

76-
const result = conjugate(verb, type);
77-
res.json(result);
90+
const result = conjugate(processedVerb, type);
91+
// 如果转换后有变化,可以在返回结果里告诉前端这是基于罗马音解析的
92+
res.json({
93+
...result,
94+
originalInput: verb,
95+
parsedAs: processedVerb
96+
});
7897
} catch (error) {
7998
res.status(400).json({
8099
error: error.message

frontend/src/App.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
id="verb"
1818
v-model="form.verb"
1919
type="text"
20-
placeholder="例如:飲む、食べる、勉強する"
20+
placeholder="例如:飲む、食べる、nomu、taberu"
2121
@keyup.enter="conjugate"
2222
>
2323
</div>
@@ -36,8 +36,9 @@
3636
<h3>活用结果</h3>
3737
<div class="result-grid">
3838
<div class="result-item">
39-
<span class="label">原形</span>
39+
<span class="label">原形 (解析为)</span>
4040
<span class="value">{{ result.dictionaryForm }}</span>
41+
<span v-if="result.originalInput !== result.parsedAs" class="example" style="margin-top: 4px; font-size: 0.8em">从罗马音 "{{ result.originalInput }}" 转换</span>
4142
</div>
4243
<div class="result-item">
4344
<span class="label">动词类型</span>

0 commit comments

Comments
 (0)