Implement kyujitai

rust
Elnu 1 year ago
parent ccba51e277
commit 3b7e03874f

@ -4,6 +4,8 @@ use std::str::FromStr;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use serde_yaml::Value; use serde_yaml::Value;
use crate::kyujitai::{Kyujitai, self};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Challenge { pub struct Challenge {
pub japanese: Vec<Vec<Vec<ChallengeWord>>>, pub japanese: Vec<Vec<Vec<ChallengeWord>>>,
@ -44,23 +46,23 @@ impl<'de> Deserialize<'de> for ChallengeWord {
)); ));
}; };
let text = map.get("text").map(|value| match value { let text = map.get("text").map(|value| match value {
Value::String(string) => vec![Furigana { Value::String(string) => vec![Furigana::new(
kanji: string.clone(), string.clone(),
furigana: None, None,
}], )],
Value::Sequence(sequence) => sequence Value::Sequence(sequence) => sequence
.iter() .iter()
.map(|value| match value { .map(|value| match value {
Value::String(kanji) => Furigana { Value::String(kanji) => Furigana::new(
kanji: kanji.to_owned(), kanji.to_owned(),
furigana: None, None,
}, ),
Value::Mapping(mapping) => { Value::Mapping(mapping) => {
let (kanji, furigana) = mapping.iter().next().unwrap(); let (kanji, furigana) = mapping.iter().next().unwrap();
Furigana { Furigana::new(
kanji: kanji.as_str().unwrap().to_owned(), kanji.as_str().unwrap().to_owned(),
furigana: Some(furigana.as_str().unwrap().to_owned()), Some(furigana.as_str().unwrap().to_owned())
} )
} }
_ => panic!(), _ => panic!(),
}) })
@ -122,9 +124,23 @@ impl FromStr for PartOfSpeech {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Furigana { pub struct Furigana {
pub kanji: String, pub kanji: String,
pub kyujitai: Option<String>,
pub furigana: Option<String>, pub furigana: Option<String>,
} }
impl Furigana {
fn new(kanji: String, furigana: Option<String>) -> Self {
Self {
kyujitai: match kanji.to_kyujitai() {
kyujitai if kyujitai.eq(&kanji) => None,
kyujitai => Some(kyujitai),
},
kanji,
furigana,
}
}
}
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct Translation { pub struct Translation {
pub author: Option<String>, pub author: Option<String>,

@ -0,0 +1,387 @@
const KYUJITAI: &[(char, char)] = &[
('万', '萬'),
('与', '與'),
('両', '兩'),
('並', '竝'),
('乗', '乘'),
('乱', '亂'),
('争', '爭'),
('亜', '亞'),
('仏', '佛'),
('仮', '假'),
('会', '會'),
('伝', '傳'),
('余', '餘'),
('体', '體'),
('価', '價'),
('併', '倂'),
('倹', '儉'),
('偽', '僞'),
('児', '兒'),
('党', '黨'),
('内', '內'),
('円', '圓'),
('冊', '册'),
('写', '寫'),
('冴', '冱'),
('処', '處'),
('剣', '劍'),
('剤', '劑'),
('剰', '剩'),
('励', '勵'),
('労', '勞'),
('効', '效'),
('勅', '敕'),
('勧', '勸'),
('勲', '勳'),
('区', '區'),
('医', '醫'),
('即', '卽'),
('巻', '卷'),
('参', '參'),
('収', '收'),
('双', '雙'),
('叙', '敍'),
('号', '號'),
('台', '臺'),
('嘱', '囑'),
('団', '團'),
('囲', '圍'),
('図', '圖'),
('国', '國'),
('圏', '圈'),
('圧', '壓'),
('尭', '堯'),
('堕', '墮'),
('塁', '壘'),
('塩', '鹽'),
('増', '增'),
('壊', '壞'),
('壌', '壤'),
('壮', '壯'),
('壱', '壹'),
('売', '賣'),
('声', '聲'),
('変', '變'),
('奥', '奧'),
('奨', '奬'),
('姫', '姬'),
('婿', '壻'),
('嬢', '孃'),
('学', '學'),
('実', '實'),
('宝', '寶'),
('寛', '寬'),
('寝', '寢'),
('寿', '壽'),
('対', '對'),
('専', '專'),
('将', '將'),
('当', '當'),
('尚', '尙'),
('単', '單'),
('巣', '巢'),
('営', '營'),
('厳', '嚴'),
('尽', '盡'),
('届', '屆'),
('属', '屬'),
('岳', '嶽'),
('峡', '峽'),
('巌', '巖'),
('帯', '帶'),
('帰', '歸'),
('広', '廣'),
('庁', '廳'),
('廃', '廢'),
('弐', '貳'),
('弥', '彌'),
('弾', '彈'),
('彦', '彥'),
('径', '徑'),
('従', '從'),
('徴', '徵'),
('徳', '德'),
('応', '應'),
('恒', '恆'),
('恵', '惠'),
('悩', '惱'),
('恋', '戀'),
('悪', '惡'),
('悦', '悅'),
('惨', '慘'),
('慎', '愼'),
('懐', '懷'),
('戦', '戰'),
('戯', '戲'),
('戸', '戶'),
('戻', '戾'),
('払', '拂'),
('抜', '拔'),
('択', '擇'),
('拝', '拜'),
('担', '擔'),
('拠', '據'),
('拡', '擴'),
('挟', '挾'),
('挿', '插'),
('捜', '搜'),
('挙', '擧'),
('掲', '揭'),
('揺', '搖'),
('摂', '攝'),
('撃', '擊'),
('教', '敎'),
('数', '數'),
('断', '斷'),
('旧', '舊'),
('昼', '晝'),
('晋', '晉'),
('晩', '晚'),
('暁', '曉'),
('暦', '曆'),
('来', '來'),
('条', '條'),
('枢', '樞'),
('栄', '榮'),
('桟', '棧'),
('桜', '櫻'),
('検', '檢'),
('楽', '樂'),
('楼', '樓'),
('槙', '槇'),
('様', '樣'),
('概', '槪'),
('横', '橫'),
('権', '權'),
('欠', '缺'),
('欧', '歐'),
('歓', '歡'),
('歩', '步'),
('歴', '歷'),
('残', '殘'),
('殴', '毆'),
('殻', '殼'),
('毎', '每'),
('気', '氣'),
('没', '沒'),
('沢', '澤'),
('浄', '淨'),
('浅', '淺'),
('涙', '淚'),
('浜', '濱'),
('渉', '涉'),
('渇', '渴'),
('渓', '溪'),
('渋', '澁'),
('済', '濟'),
('清', '淸'),
('温', '溫'),
('満', '滿'),
('湿', '濕'),
('湾', '灣'),
('滞', '滯'),
('滝', '瀧'),
('潜', '潛'),
('瀬', '瀨'),
('灯', '燈'),
('炉', '爐'),
('為', '爲'),
('点', '點'),
('焼', '燒'),
('犠', '犧'),
('状', '狀'),
('狭', '狹'),
('独', '獨'),
('猟', '獵'),
('献', '獻'),
('獣', '獸'),
('瑶', '瑤'),
('瓶', '甁'),
('産', '產'),
('画', '畫'),
('畳', '疊'),
('痴', '癡'),
('発', '發'),
('盗', '盜'),
('県', '縣'),
('真', '眞'),
('研', '硏'),
('砕', '碎'),
('礼', '禮'),
('禄', '祿'),
('禅', '禪'),
('秘', '祕'),
('称', '稱'),
('税', '稅'),
('稲', '稻'),
('穂', '穗'),
('穏', '穩'),
('穣', '穰'),
('窃', '竊'),
('粋', '粹'),
('糸', '絲'),
('経', '經'),
('絵', '繪'),
('続', '續'),
('継', '繼'),
('緒', '緖'),
('緑', '綠'),
('総', '總'),
('縄', '繩'),
('縁', '緣'),
('縦', '縱'),
('繊', '纖'),
('缶', '罐'),
('聡', '聰'),
('聴', '聽'),
('粛', '肅'),
('胆', '膽'),
('脱', '脫'),
('脳', '腦'),
('臓', '臟'),
('舎', '舍'),
('舗', '舖'),
('艶', '艷'),
('芸', '藝'),
('茎', '莖'),
('荘', '莊'),
('蔵', '藏'),
('薫', '薰'),
('薬', '藥'),
('虚', '虛'),
('虫', '蟲'),
('蚕', '蠶'),
('蛍', '螢'),
('蛮', '蠻'),
('衛', '衞'),
('装', '裝'),
('褒', '襃'),
('覇', '霸'),
('覚', '覺'),
('覧', '覽'),
('観', '觀'),
('触', '觸'),
('訳', '譯'),
('証', '證'),
('誉', '譽'),
('読', '讀'),
('謡', '謠'),
('譲', '讓'),
('豊', '豐'),
('賛', '贊'),
('践', '踐'),
('転', '轉'),
('軽', '輕'),
('辞', '辭'),
('辺', '邊'),
('逓', '遞'),
('遥', '遙'),
('遅', '遲'),
('郎', '郞'),
('郷', '鄕'),
('酔', '醉'),
('醸', '釀'),
('釈', '釋'),
('鉄', '鐵'),
('鉱', '鑛'),
('銭', '錢'),
('鋭', '銳'),
('鋳', '鑄'),
('錬', '鍊'),
('録', '錄'),
('鎮', '鎭'),
('関', '關'),
('闘', '鬪'),
('陥', '陷'),
('険', '險'),
('随', '隨'),
('隠', '隱'),
('隣', '鄰'),
('隷', '隸'),
('雑', '雜'),
('霊', '靈'),
('青', '靑'),
('静', '靜'),
('頼', '賴'),
('顔', '顏'),
('顕', '顯'),
('飲', '飮'),
('餅', '餠'),
('駅', '驛'),
('駆', '驅'),
('騒', '騷'),
('験', '驗'),
('髄', '髓'),
('髪', '髮'),
('竜', '龍'),
('鶏', '鷄'),
('麦', '麥'),
('黄', '黃'),
('黒', '黑'),
('黙', '默'),
('斉', '齊'),
('斎', '齋'),
('歯', '齒'),
('齢', '齡'),
('亀', '龜'),
('告', '吿'),
('屡', '屢'),
('湾', '灣'),
('亘', '亙'),
('凜', '凛'),
('刃', '刄'),
('呉', '吳'),
('回', '囘'),
('妊', '姙'),
('娯', '娛'),
('強', '强'),
('携', '攜'),
('曽', '曾'),
('歳', '歲'),
('粘', '黏'),
('糾', '糺'),
('絶', '絕'),
('萌', '萠'),
('説', '說'),
('祷', '禱'),
('鎌', '鐮'),
('閲', '閱'),
('麺', '麵'),
('祢', '禰'),
];
pub trait Kyujitai {
fn to_kyujitai(&self) -> String;
fn to_shinjitai(&self) -> String;
}
impl Kyujitai for String {
fn to_kyujitai(&self) -> String {
let mut output = String::with_capacity(self.len());
'outer: for shinjitai in self.chars() {
for (other_shinjitai, kyujitai) in KYUJITAI {
if shinjitai == *other_shinjitai {
output.push(kyujitai.clone());
continue 'outer;
}
}
output.push(shinjitai.clone());
}
output
}
fn to_shinjitai(&self) -> String {
let mut output = String::with_capacity(self.len());
'outer: for kyujitai in self.chars() {
for (shinjitai, other_kyujitai) in KYUJITAI {
if kyujitai == *other_kyujitai {
output.push(shinjitai.clone());
continue 'outer;
}
}
output.push(kyujitai.clone());
}
output
}
}

@ -10,6 +10,8 @@ use sass_rocket_fairing::SassFairing;
mod challenge; mod challenge;
use challenge::Challenge; use challenge::Challenge;
mod kyujitai;
#[get("/<challenge>")] #[get("/<challenge>")]
fn get_challenge(challenge: u32) -> Template { fn get_challenge(challenge: u32) -> Template {
Template::render( Template::render(

@ -9,6 +9,18 @@
<a href="/{{ challenge - 1 }}">Previous</a> <a href="/{{ challenge - 1 }}">Previous</a>
<a href="/{{ challenge + 1 }}">Next</a> <a href="/{{ challenge + 1 }}">Next</a>
<div lang="ja"> <div lang="ja">
<script>
let kyujitai = false;
function kyujitaiToggle() {
document.querySelectorAll("[data-kyujitai]").forEach(segment => {
let newText = segment.getAttribute("data-kyujitai");
segment.setAttribute("data-kyujitai", segment.firstChild.data);
segment.firstChild.data = newText;
})
kyujitai = !kyujitai;
}
</script>
<button onclick="kyujitaiToggle(); this.innerHTML = kyujitai ? '新字体' : '旧字体'"">旧字体</button>
{% for line in content.japanese %} {% for line in content.japanese %}
{% for subline in line %} {% for subline in line %}
<p> <p>
@ -17,7 +29,8 @@
<a href="{{ word.dictionary }}" target="_blank"{% if word.pos %} class="{{ word.pos }}" title="{{ word.pos }}"{% endif %}> <a href="{{ word.dictionary }}" target="_blank"{% if word.pos %} class="{{ word.pos }}" title="{{ word.pos }}"{% endif %}>
{% endif %} {% endif %}
{% for segment in word.text %} {% for segment in word.text %}
<ruby>{{ segment.kanji }}<rp>(</rp><rt>{{ segment.furigana | safe }}</rt><rp>)</rp></ruby> <!-- TODO: Don't use ruby for all segments -->
<ruby{% if segment.kyujitai %} data-kyujitai="{{ segment.kyujitai }}"{% endif %}>{{ segment.kanji }}<rp>(</rp><rt>{{ segment.furigana | safe }}</rt><rp>)</rp></ruby>
{% endfor %} {% endfor %}
{% if word.dictionary %} {% if word.dictionary %}
</a> </a>

Loading…
Cancel
Save