9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

絵文字Translater作ってみた🐈‍⬛🐈

Last updated at Posted at 2024-11-30

はじめに

まったく何の役にも立ちませんが、

絵文字翻訳ツール的なものを作成してみました💪

今回作った絵文字翻訳ツール

  • 絵文字=>英語名に変換

絵文字Translater作ってみた_03.jpg

絵文字Translater作ってみた_04.jpg

  • 絵文字=>日本語名に変換

絵文字Translater作ってみた_03.jpg

絵文字Translater作ってみた_05.jpg

  • 名称=>絵文字に変換

絵文字Translater作ってみた.jpg

絵文字Translater作ってみた_02.jpg

  • 説明モード(絵文字のあとに説明を入れる)

絵文字Translater作ってみた_06.jpg

  • DarkMode

絵文字Translater作ってみた_08.jpg

  • (謎に、絵文字がゆっくり流れる背景アニメーションがあります)

絵文字Translater作ってみた.gif

成果物のURL

プロジェクト構成など

絵文字について

UnicodeコンソーシアムのFull Emoji Listの下記を参考に作成

下記の記事が絵文字の勉強になりました🙇‍♂️

力技で実装していく!💪

(生成AI時代なのに、力技で実装しています。まったく参考になりませんのでご了承ください。🙇‍♂️)

linderaというRust製の日本語形態素解析器を使ってみたかったので、

一部ロジックはRust(Wasm)で実装していきます。

まず、翻訳のデータを作成。

UnicodeコンソーシアムのFull Emoji ListのCLDR Short Nameを日本語訳し、Jsonのstring形式にする

emoji_json.rs
ub fn get_json() -> &'static str { r#"[
{"cd":"U+1F600","nm":"grinning face","jp":"ニヤニヤ顔"},
{"cd":"U+1F603","nm":"grinning face with big eyes","jp":"大きな目のニヤニヤ顔"},
//略
]"#
}

次に。置換する関数を作成。

replace_emoji_with_name 関数

文字列、language、explainフラグを受け取り、絵文字をShortNameに置き換えた新しい文字列を返す。

すべての文字がUnicode絵文字の範囲(U+1F000からU+1F9FF)内にあるかどうかを確認し、

もしすべての文字が絵文字の範囲内であれば、単体の絵文字として扱う。🐈

g.chars().count() > 1:g が複数の文字を含むかどうかを確認し、🐈‍⬛

複数の文字を含む場合、最初の文字が絵文字の範囲内にあるかどうかを確認。

最初の文字が絵文字の範囲内であれば、合体絵文字として扱う。

上記外はそのまま文字列として扱う。

get_short_name 関数

絵文字文字列、language、explainフラグを受け取り、ShortNameを返す。

format_emoji_to_unicode関数でemojiをUnicode形式の文字列に変換します(例: "U+1F600")。

JSONデータから絵文字情報を読み込み、Unicodeコードが一致するEmojiRowをフィルタリングする。

languageに応じて、英名、日本語名を取得する。

explain フラグが true の場合、絵文字直後に説明を追加する(例: "😀(grinning face)")。

explain フラグが false の場合、説明のみを返す(例: "(grinning face)")。

lib.rs
//略

#[wasm_bindgen]
pub fn replace_emoji_with_name(text: &str,language: u32,explain: bool) -> String {
    text.graphemes(true)
        .map(|g| {
            if g.chars().all(|c| (0x1F000..=0x1F9FF).contains(&(c as u32))) {
                //単体絵文字
                get_short_name(g, language,explain)
            } else {
                if g.chars().count() > 1 {
                    if let Some(c) = g.chars().next() {
                        if (0x1F000..=0x1F9FF).contains(&(c as u32)) {
                            //合体絵文字
                            get_short_name(g, language,explain)
                        } else { g.to_string() }
                    } else { g.to_string() }
                } else { g.to_string() }
            }
        })
        .collect()
}

/// emoji_unicodeに紐づくshort_nameにして返します(explainの時は絵文字直後に説明を入れる)
fn get_short_name(emoji :&str,language: u32,explain: bool) -> String {
    let mut result = String::new();
    let unicode = format_emoji_to_unicode(emoji);

    let emoji_rows: Vec<EmojiRow> = from_str(get_json()).unwrap();
    let objs = emoji_rows.iter()
        .filter(|item| item.cd.as_str() == unicode);
    for obj in objs {
        if language == 0 {
            result= obj.clone().nm;
        }
        if language == 1 {
            result= obj.clone().jp;
        }
        break;
    }

    if explain {
        let mut result_explain = String::new();
        result_explain.push_str(emoji);
        result_explain.push_str(&* format!("(*{}*)",result));
        result_explain
    }
    else {
        format!("(*{}*)",result)
    }
}

/// emojiをunicodeにformatして返します
fn format_emoji_to_unicode(emoji :&str) -> String {
    let mut unicode = String::new();
    let mut i = 0;
    for c in emoji.chars()
    {
        if i>0 {unicode.push_str(" ")};
        unicode.push_str(&format!("U+{:X}", c as u32));
        i = i + 1;
    }
    unicode
}
//略

replace_name_with_emoji 関数

文字列、explainフラグを受け取り、テキスト内の単語を絵文字に置き換える。

関数は、Tokenizerを使用してテキストを形態素解析し、各トークンをget_emoji関数に渡して絵文字に変換する。

get_emoji 関数

文字列、explainフラグを受け取り、与えられた単語に対応する絵文字を検索。

関数は、EmojiRowのリストをループし、英名または日本名がtextと一致する行を探し、

一致する行が見つかった場合、format_unicode_to_emoji関数でUnicodeコードを絵文字に変換し(例:"U+1F600")、

explainフラグに応じて元の単語を追加。

一致する絵文字が見つからない場合、元の単語がそのまま返す。

lib.rs
//略

#[wasm_bindgen]
pub fn replace_name_with_emoji(text: &str,explain: bool) -> String {
    let mut result = String::new();
    let dictionary = DictionaryConfig {
        kind: Some(DictionaryKind::IPADIC),
        path: None,
    };
    let config = TokenizerConfig {
        dictionary,
        user_dictionary: None,
        mode: Mode::Normal,
    };
    let tokenizer = Tokenizer::from_config(config).unwrap();
    let tokens = tokenizer.tokenize(text).unwrap();
    for token in tokens {
        result.push_str(&*get_emoji(token.text,explain));
    }
    result
}

/// short_name(類似名含む名詞単位)に紐づくemojiにして返します
fn get_emoji(text: &str,explain: bool) -> String {
    let mut result = String::new();
    let emoji_rows: Vec<EmojiRow> = from_str(get_json()).unwrap();
    for row in emoji_rows {
       // short_name
       if row.nm == text {
           if explain { result.push_str(text); }
           result.push_str(&*format_unicode_to_emoji(&*row.cd));
           break;
       }
       // short_name_jp
       if row.jp == text {
           if explain { result.push_str(text); }
            result.push_str(&*format_unicode_to_emoji(&*row.cd));
            break;
       }
    }
    if result.is_empty() {
        result.push_str(text);
    }
    result
}

/// unicodeをemojiにformatして返します
fn format_unicode_to_emoji(unicode: &str) -> String {
    let result
        = unicode.split_whitespace().map(|code| {
            if let Some(stripped) = code.strip_prefix("U+") {
                if let Ok(hex) = u32::from_str_radix(stripped, 16) {
                    char::from_u32(hex).unwrap_or_default().to_string()
                } else {
                    code.to_string()
                }
            } else {
                code.to_string()
            }
        })
        .collect::<String>();
    result
}
//略

ソース

まとめ

絵文字翻訳ツールを作ってみたが、お披露目するところがなかったので、

クソアプリとして供養いたしました。😊

自分の作ってみたいものを、

力技や自分の好きなように実装するのは、とっても楽しい!💪

9
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?