日本語パスワードとローマ字出力
Mix.install([
{:exk_passwd, "~> 0.2.0"}
])
The Romaji transform converts Hiragana and Katakana to keyboard-friendly ASCII. It does not perform Kanji readings or morphological analysis.
Load a kana dictionary
japanese_words = [
"さくら", # cherry blossom
"たいよう", # sun
"うみ", # sea
"やま", # mountain
"かぜ", # wind
"ほし", # star
"つき", # moon
"はな", # flower
"みず", # water
"そら", # sky
"ゆき", # snow
"あめ", # rain
"ひかり", # light
"こころ", # heart
"ゆめ", # dream
"コーヒー", # coffee
"ファイル", # file
"ウィンドウ", # window
"パーティー", # party
"チェック" # check
]
:ok = ExkPasswd.Dictionary.load_custom(:japanese_demo, japanese_words)
transform = %ExkPasswd.Transform.Romaji{}
Validate output and collisions
converted =
Map.new(japanese_words, fn word ->
{word, ExkPasswd.Transform.apply(transform, word, nil)}
end)
unmapped = Enum.filter(converted, fn {_source, output} -> output =~ ~r/[^a-z]/ end)
collisions = converted |> Map.values() |> Enum.frequencies() |> Enum.filter(fn {_, n} -> n > 1 end)
%{converted: converted, unmapped: unmapped, collisions: collisions}
Run these checks against the complete application dictionary. Deterministic romanization can merge different source words, and those collisions reduce the reachable output space.
Generate passwords
config =
ExkPasswd.Config.new!(
dictionary: :japanese_demo,
word_length: 2..6,
word_length_bounds: 1..10,
num_words: 3,
separator: "-",
digits: {2, 2},
padding: %{char: "", before: 0, after: 0, to_length: 0},
case_transform: :none,
meta: %{transforms: [transform]}
)
for _ <- 1..10, do: ExkPasswd.generate(config)
Inspect the actual output space
details = ExkPasswd.Entropy.calculate_seen_detailed(config)
%{
word_entropy: Float.round(details.word_entropy, 2),
digit_entropy: Float.round(details.digit_entropy, 2),
total: Float.round(details.total, 2)
}
This 20-word list is an API demonstration, not a production dictionary. The calculation should guide claims about the example; memorability does not replace an adequate number of random choices.
Romanization checks
examples = [
{"さくら", "sakura"},
{"がっこう", "gakkou"},
{"まっちゃ", "matcha"},
{"きょう", "kyou"},
{"しゃしん", "shashin"},
{"さんぽ", "sampo"},
{"しんぶん", "shimbun"},
{"コーヒー", "koohii"},
{"ファイル", "fairu"},
{"パーティー", "paatii"},
{"ウィンドウ", "windou"},
{"チェック", "chekku"},
{"ヴァイオリン", "vaiorin"}
]
for {source, expected} <- examples do
actual = ExkPasswd.Transform.apply(transform, source, nil)
{source, actual, actual == expected}
end
The implementation uses modified Hepburn conventions together with common
Wāpuro keyboard spellings. Long Katakana vowels are duplicated in ASCII
(コーヒー → koohii) rather than written with macrons.
Kanji limitation
alias ExkPasswd.Transform.Romaji
%{
kana: ExkPasswd.Transform.apply(transform, "さくら", nil),
kanji_passes_through: ExkPasswd.Transform.apply(transform, "桜", nil),
detects_kanji: Romaji.contains_kanji?("日本語")
}
Use kana-only entries when ASCII output is required. Particles such as は and を
are romanized by character value (ha, wo); sentence-level grammatical
readings would require context the transform does not have.