root/veekun/trunk/script/utils/convert_kana.pl

Revision 338, 4.7 kB (checked in by eevee, 15 months ago)

Fixed all the romaji for the Pokemon and moves, including all ones; they are now done in something resembling a standard way. (#23)
Also, so I don't have to fuck around with this again, I included the script I used. Might want to put it in its own oneshot-projects folder someday.

Line 
1#!/usr/bin/perl
2
3# Converts kana to my style of romaji, which is mostly wapuro.
4# Provided as-is for my benefit later; no real documentation.
5# Licensed the same as the rest of the veekun code, so feel free to rip out
6# the transliterate() sub below.
7
8use strict;
9use warnings;
10
11use DBI;
12use Convert::EastAsianWidth;
13use Encode;
14use Storable qw/dclone/;
15
16# courtesy of Lingua::JA::Romanize::Kana
17my @kana = qw(
18    xa  a   xi  i   xu  u   xe  e   xo  o   ka  ga  ki  gi  ku
19    gu  ke  ge  ko  go  sa  za  shi ji  su  zu  se  ze  so  zo  ta
20    da  chi ji  xtu tsu zu  te  de  to  do  na  ni  nu  ne  no  ha
21    ba  pa  hi  bi  pi  fu  bu  pu  he  be  pe  ho  bo  po  ma  mi
22    mu  me  mo  xya ya  xyu yu  xyo yo  ra  ri  ru  re  ro  xwa wa
23    wi  we  wo  n   vu  ka  ke
24);
25
26my $dbh = DBI->connect('dbi:mysql:pokedex', 'perl', '');
27my $rows_ref = $dbh->selectall_arrayref('SELECT id, name, name_jp, name_romaji FROM pokemon', { Slice => {} });
28my $sth = $dbh->prepare('UPDATE pokemon SET name_romaji = ? WHERE id = ?');
29
30my $mismatches = 0;
31
32for my $row (@$rows_ref) {
33    if (not $row->{name_jp}) {
34        warn "$row->{name} has no kana!";
35        next;
36    }
37
38    my $converted_romaji = transliterate($row->{name_jp});
39
40    # male/female symbols; changed to be consistent with my English
41    $converted_romaji =~ s/\x{2640}/ F/g;
42    $converted_romaji =~ s/\x{2642}/ M/g;
43
44    # capitalize Romanly
45    $converted_romaji =~ s/ \b (\w) /\u$1/gx;
46
47    if ($converted_romaji =~ /[^\x20-\xffx]/) {
48        print "!!! NON-ASCII CHARACTERS DETECTED FOR $row->{name}; SKIPPING\n";
49        next;
50    }
51   
52    if ($row->{name_romaji} ne $converted_romaji) {
53        $mismatches++;
54        $sth->execute($converted_romaji, $row->{id});
55        printf "Converted %12s: %16s -> %16s\n", $row->{name}, $row->{name_romaji}, $converted_romaji;
56    }
57}
58
59print "$mismatches changed romaji\n";
60
61
62# TODO: instead of the kana+chibivowel messiness, this should first go through
63# and tag all the kana as katakana or hiragana, small or not, etc
64sub transliterate {
65    my ($bytes) = @_;
66    my $string = decode('utf8', $bytes);
67    $string = to_halfwidth($string);
68    my @chars = split //, $string;
69
70    for my $char (@chars) {
71        my $codept = ord $char;
72
73        if ($codept < 0x3041 or
74            ($codept > 0x3093 and $codept < 0x30a1) or
75            $codept > 0x30f6)
76        {
77            # outside our range!
78            $char = [ $char, '' ];
79            next;
80        }
81
82        my $idx = ($codept - 0x3041) % 96;
83        $char = [ $char, $kana[$idx] ];
84    }
85
86    for my $i (1 .. $#chars) {
87        # pa-paru
88        if ($chars[$i][0] eq "\x{30fc}" and
89            $chars[$i][0] ne $chars[$i - 1][0]
90        ) {
91            ( $chars[$i][1] ) = ( $chars[$i - 1][1] =~ /([aeiou])h?$/ );
92        }
93    }
94
95    my $pos = $#chars;
96    while ($pos >= 0) {
97        # kana + chibi-vowel; used a lot in katakana
98        if ($chars[$pos][1] =~ /x[aeiou]/) {
99            my $vowel = $chars[$pos][1];
100            $vowel =~ s/^x//;
101            my $newchar = $chars[$pos - 1][1];
102
103            if ($vowel eq substr $newchar, -1) {
104                # special exception: sometimes this is used to double a vowel
105                # (e.g. in serebii)
106                $chars[$pos][1] = $vowel;
107            } else {
108                $newchar =~ s/[aeiou]$/$vowel/;
109                splice @chars, $pos - 1, 2, [ 'replaced', $newchar ];
110            }
111
112            $pos -= 2;
113            next;
114        }
115
116        # mini-y*; blend with preceding *i
117        # TODO: errors?
118        if ($chars[$pos][1] =~ /^xy/ and
119            $chars[$pos - 1][1] =~ /i$/)
120        {
121            my $prefix = substr $chars[$pos - 1][1], 0, -1;
122            my $suffix = substr $chars[$pos][1], 1;
123
124            # toss the y in a few cases
125            $suffix = substr $suffix, 1
126                if $prefix eq 'j' or $prefix eq 'sh' or $prefix eq 'ch';
127
128            my $newchar = $prefix . $suffix;
129            splice @chars, $pos - 1, 2, [ 'replaced', $newchar ];
130            $pos -= 2;
131            next;
132        }
133
134        # mini-tsu; double next consonant
135        # TODO: errors for the weird conditions?  what to do there?
136        if ($chars[$pos][1] eq 'xtu' and
137            $chars[$pos + 1][1] =~ /^[^xaeiou]/ and
138            $chars[$pos + 1][1] ne 'n')
139        {
140            my $newchar =
141                substr($chars[$pos + 1][1], 0, 1) .
142                $chars[$pos + 1][1];
143            splice @chars, $pos, 2, [ 'replaced', $newchar ];
144
145            # only decrement by one because we're not consuming the prior char
146            $pos--;
147            next;
148        }
149
150        $pos--;
151    }
152
153    my $result = join '', map { $_->[1] || $_->[0] } @chars;
154
155    # fullwidth garbage
156    $result =~ tr[\x{ff21}-\x{ff3a}\x{ff41}-\x{ff5a}]
157                 [A-Za-z];
158
159    return $result;
160}
Note: See TracBrowser for help on using the browser.