fix(study): pinyin of names and sayings is typed and checked right
CC-CEDICT capitalises names, so their readings start with a capital vowel with its tone mark (欧洲 Ōu zhōu, 澳门 Ào mén, 俄语 É yǔ), which the test for pinyin didn't know: those words were never typed. It now reads the reading in lower case. CC-CEDICT also keeps a saying's comma, written between spaces (bù pà màn , jiù pà zhàn), and the comma split the reading into two readings, so typing the whole saying was wrong and half of it right. A comma with a space before it now stays part of the reading, and commas count for nothing when readings are compared; a comma written straight after a reading (xíng, háng) still separates readings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Tizian 「ティツィアーン」 <raisondetredev@pm.me>
This commit is contained in:
parent
d3063e82e1
commit
6ea7375376
2 changed files with 38 additions and 8 deletions
|
|
@ -77,22 +77,33 @@ class const PinyinInputFormatter() extends TextInputFormatter {
|
|||
}
|
||||
|
||||
/// [pinyin] as pinyin is compared: with tone marks ([withToneMarks]),
|
||||
/// lower case, without spaces, apostrophes or hyphens (`Xué xí`, `xue2xi2`
|
||||
/// → `xuéxí`).
|
||||
/// lower case, without spaces, apostrophes, hyphens or commas (`Xué xí`,
|
||||
/// `xue2xi2` → `xuéxí`; a saying's `màn , jiù` → `mànjiù`).
|
||||
String pinyinKey(String pinyin) => withToneMarks(
|
||||
pinyin.trim(),
|
||||
).toLowerCase().replaceAll(RegExp(r"[\s'’·-]+"), '');
|
||||
).toLowerCase().replaceAll(RegExp(r"[\s'’·,,-]+"), '');
|
||||
|
||||
/// The readings a card's pinyin field gives, one or several (`xíng,
|
||||
/// háng`), as compared ([pinyinKey]).
|
||||
Set<String> givenPinyin(String field) => {
|
||||
for (final reading in field.split(RegExp('[,,;;//、]')))
|
||||
for (final reading in field.split(_readingsApart))
|
||||
if (pinyinKey(reading).isNotEmpty) pinyinKey(reading),
|
||||
};
|
||||
|
||||
/// Whether [reading] is pinyin: Latin letters, with or without tone marks,
|
||||
/// and no kana or Han characters.
|
||||
bool isPinyin(String reading) =>
|
||||
reading.trim().isNotEmpty && _pinyin.hasMatch(reading.trim());
|
||||
/// What separates the readings of a pinyin field: a comma written straight
|
||||
/// after a reading (`xíng, háng`), a semicolon, a slash or an enumeration
|
||||
/// comma. A comma with a space before it is a saying's own, as CC-CEDICT
|
||||
/// writes its punctuation between spaces (`bù pà màn , jiù pà zhàn`): the
|
||||
/// whole saying is its one reading.
|
||||
final _readingsApart = RegExp(r'(?<!\s)[,,]|[;;//、]');
|
||||
|
||||
final _pinyin = RegExp(r"^[A-Za-zÜüāáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜ\s'’·,,:-]+$");
|
||||
/// Whether [reading] is pinyin: Latin letters, with or without tone marks,
|
||||
/// whatever their case (CC-CEDICT capitalises names: `Ōu zhōu`), and no
|
||||
/// kana or Han characters.
|
||||
bool isPinyin(String reading) {
|
||||
final lower = reading.trim().toLowerCase();
|
||||
return lower.isNotEmpty && _pinyin.hasMatch(lower);
|
||||
}
|
||||
|
||||
/// Pinyin in lower case, as [isPinyin] reads it.
|
||||
final _pinyin = RegExp(r"^[a-züāáǎàēéěèīíǐìōóǒòūúǔùǖǘǚǜ\s'’·,,:-]+$");
|
||||
|
|
|
|||
|
|
@ -27,6 +27,17 @@ void main() {
|
|||
expect(givenPinyin('xíng').contains(pinyinKey('xing1')), isFalse);
|
||||
});
|
||||
|
||||
test("a saying's comma is part of its reading, as CC-CEDICT writes it "
|
||||
'between spaces; a comma after a reading separates readings', () {
|
||||
final saying = givenPinyin('bù pà màn , jiù pà zhàn');
|
||||
|
||||
expect(saying.contains(pinyinKey('bu4 pa4 man4 jiu4 pa4 zhan4')), isTrue);
|
||||
expect(saying.contains(pinyinKey('bu4pa4man4, jiu4pa4zhan4')), isTrue);
|
||||
expect(saying.contains(pinyinKey('bu4 pa4 man4')), isFalse);
|
||||
expect(saying.contains(pinyinKey('jiu4 pa4 zhan4')), isFalse);
|
||||
expect(givenPinyin('xíng,háng'), {'xíng', 'háng'});
|
||||
});
|
||||
|
||||
test("pinyin is told from kana and from words' own letters", () {
|
||||
expect(isPinyin('xué xí'), isTrue);
|
||||
expect(isPinyin('shuō'), isTrue);
|
||||
|
|
@ -35,6 +46,14 @@ void main() {
|
|||
expect(isPinyin(''), isFalse);
|
||||
});
|
||||
|
||||
test('a proper noun, capitalised with its tone mark, is pinyin too', () {
|
||||
expect(isPinyin('Ōu zhōu'), isTrue);
|
||||
expect(isPinyin('Ào mén'), isTrue);
|
||||
expect(isPinyin('É yǔ'), isTrue);
|
||||
expect(isPinyin('Lǘ'), isTrue);
|
||||
expect(givenPinyin('Ōu zhōu').contains(pinyinKey('ou1zhou1')), isTrue);
|
||||
});
|
||||
|
||||
test('typing turns a syllable and its tone into the marked syllable, the '
|
||||
'caret where it was typed', () {
|
||||
const formatter = PinyinInputFormatter();
|
||||
|
|
|
|||
Loading…
Reference in a new issue