├── .gitignore ├── titles.sql ├── bin ├── wikiogg ├── cloze ├── translate ├── add-audio └── export ├── extract.sql └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | output -------------------------------------------------------------------------------- /titles.sql: -------------------------------------------------------------------------------- 1 | SELECT title FROM book_info; 2 | -------------------------------------------------------------------------------- /bin/wikiogg: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | default_lang='en' 4 | 5 | ogg=$(curl -s "https://${FROM_LANG-$default_lang}.wiktionary.org/wiki/${1}" | egrep -o '//upload.wikimedia.org[^"]+?ogg' | head -n1) 6 | curl -s "https:$ogg" 7 | -------------------------------------------------------------------------------- /bin/cloze: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | tab=$'\t' 4 | 5 | while read line; do 6 | word=$(echo "$line" | cut -f2) 7 | text=$(echo "$line" | cut -f3) 8 | echo "${line}${tab}$(echo "$text" | sed "s/$word/{{c1::&}}/g")" 9 | done 10 | 11 | -------------------------------------------------------------------------------- /extract.sql: -------------------------------------------------------------------------------- 1 | SELECT 2 | words.stem, words.word, lookups.usage 3 | FROM lookups 4 | LEFT OUTER JOIN book_info 5 | ON lookups.book_key=book_info.id 6 | LEFT OUTER JOIN words 7 | ON lookups.word_key=words.id 8 | WHERE title = '#TITLE#'; 9 | -------------------------------------------------------------------------------- /bin/translate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IFS=$'\n' 4 | default_lang='en' 5 | 6 | if [ "$FROM_LANG" ]; then 7 | # from-to 8 | lang="$FROM_LANG-${TO_LANG-$default_lang}" 9 | else 10 | # to 11 | lang="$default_lang" 12 | fi 13 | 14 | apikey='trnsl.1.1.20151015T080754Z.fac48f0d13a96c3a.c0c58058288c42ba40de8aec2b36d9d86c3adb1d' 15 | endpoint="https://translate.yandex.net/api/v1.5/tr.json/translate?key=${apikey}&lang=${lang}" 16 | 17 | translated=$(curl -s -L -G "$endpoint" -X GET --data-urlencode "text=$(cat "$1" | cut -f1)" | cut -f10 -d '"' | sed 's/\\n/\ 18 | /g' | sed 's/,//g') 19 | 20 | paste <(cat "$1" | ./bin/cloze) <(echo "$translated") 21 | 22 | 23 | -------------------------------------------------------------------------------- /bin/add-audio: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IFS=$'\n' 4 | minimumsize=100 5 | wordsfile=$(mktemp) 6 | out='output/audio' 7 | 8 | mkdir -p "$out" 9 | 10 | for i in $(cat "$1" | cut -f1); do 11 | word=$(echo "$i" | cut -f2 -d ' ') 12 | oggfile="$(mktemp).ogg" 13 | 14 | ./bin/wikiogg "$word" > "$oggfile" 15 | 16 | actualsize=$(wc -c < "$oggfile") 17 | if [ $actualsize -ge $minimumsize ]; then 18 | ffmpeg -n -loglevel 0 -i "$oggfile" "$out/$i.mp3" 19 | echo "[sound:$i.mp3]" >> "$wordsfile" 20 | else 21 | echo ' ' >> "$wordsfile" 22 | fi 23 | 24 | rm "$oggfile" 25 | done 26 | 27 | paste "$1" "$wordsfile" 28 | rm -f "$wordsfile" 29 | -------------------------------------------------------------------------------- /bin/export: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | IFS=$'\n' 4 | DB='/Volumes/Kindle/system/vocabulary/vocab.db' 5 | OUT='output' 6 | 7 | # Create the output directory 8 | mkdir -p "$OUT" 9 | 10 | # Iterate over all books 11 | for title in $(cat titles.sql | sqlite3 $DB -separator $'\t'); do 12 | echo "Extracting words from $title..." 13 | 14 | # Extract the look-ups 15 | FILE="$OUT/$title.txt" 16 | escaped=$(echo "$title" | sed "s/'/''/") 17 | cat extract.sql | sed "s/#TITLE#/$escaped/g" | sqlite3 $DB -separator $'\t' > "$FILE" 18 | 19 | WORDS_NUM=$(cat $FILE | wc -l) 20 | if [ $WORDS_NUM == 0 ]; then 21 | rm "$FILE"; 22 | else 23 | echo "Extracted $WORDS_NUM words from $title." 24 | fi 25 | done 26 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Kindle Flashcards 2 | 3 | 1. Plug Kindle into the computer. 4 | 2. Open the terminal. 5 | 3. Download this repository and navigate to its folder: `cd ./kindle-flashcards`. 6 | 4. Execute `./bin/export`. This will create files with words and quotes for each book and save them to `./output`. 7 | 5. To add translations, run `FROM_LANG=de TO_LANG=en ./bin/translate output/Schachnovelle.txt > flashcards.txt`. 8 | 7. ... 9 | 8. The flashcards are ready! 10 | 11 | screen shot 2016-06-28 at 21 43 20 12 | screen shot 2016-06-28 at 21 43 23 13 | 14 | ## Importing into Anki 15 | * Create a new deck or use an existing deck. 16 | * Import the flashcards file (File -> Import). 17 | 18 | The flashcards file looks like this: 19 | ``` 20 | staubig staubig Sein langer grüner Umhang war staubig und verschlissen. Sein langer grüner Umhang war {{c1::staubig}} und verschlissen. dusty 21 | ``` 22 | 23 | The file has five fields: 24 | 25 | 1. The base form of the word (i.e. infinitive for verbs, nominative singular for nouns etc). 26 | 2. The original word form. 27 | 3. The sentence where the word was encountered. 28 | 4. The same sentence with the word clozed out. See [Cloze Deletion](http://ankisrs.net/docs/manual.html#cloze-deletion) in the Anki manual. 29 | 5. The translation of the word. 30 | 31 | The final result may look like this: 32 | 33 | ## Adding audio 34 | You can also add recordings of words' pronunciations to your cards. Run the following command: 35 | ``` 36 | ./bin/add-audio flashcards.txt > flashcards_with_audio.txt 37 | ``` 38 | The audio will be saved into `./output/audio`. Copy the audio files into the Anki media collection directory (typically `~/Documents/Anki/User 1/collection.media`). 39 | 40 | Audio files are downloaded from Wiktionary and encoded from ogg to mp3. Please note that this requires `ffmpeg` to be installed on your system (e.g. `brew install ffmpeg`). 41 | 42 | However, you can simply add this JavaScript to your card layout to enable the built-in text-to-speech: 43 | 44 | ``` 45 | 51 | ``` 52 | --------------------------------------------------------------------------------