Compare commits
166
Commits
37e48e0132
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e8e018445 | ||
|
|
363a728fc3 | ||
|
|
df05d4e875 | ||
|
|
ef57ecbc9b | ||
|
|
e51ca48bb9 | ||
|
|
f43a23bab2 | ||
|
|
4c7605156a | ||
|
|
30f48e1fc7 | ||
|
|
ee6d704d48 | ||
|
|
11b178f6f8 | ||
|
|
9c5c4d3689 | ||
|
|
162813e949 | ||
|
|
f61aaa4b40 | ||
|
|
ed5dc07f6c | ||
|
|
ffdeee6a76 | ||
|
|
f2195dd2fb | ||
|
|
5c014ba6e1 | ||
|
|
4703409a35 | ||
|
|
e68493ba35 | ||
|
|
382f642205 | ||
|
|
863142902c | ||
|
|
e9d02dbec7 | ||
|
|
15af343be7 | ||
|
|
ddcffe7a63 | ||
|
|
9da12902d7 | ||
|
|
ffeac1c0ae | ||
|
|
5c25d24073 | ||
|
|
0c628cc3f5 | ||
|
|
608d02c12a | ||
|
|
8cb95a5b9d | ||
|
|
4f891ae123 | ||
|
|
e8e7ff86f6 | ||
|
|
dd36c6fc93 | ||
|
|
daa5c73cec | ||
|
|
c2d5b4c2f2 | ||
|
|
bb20f289ff | ||
|
|
745c7dfc86 | ||
|
|
5e6022167d | ||
|
|
fc7446f62a | ||
|
|
b07a977495 | ||
|
|
6ef128292e | ||
|
|
cfe0b238d9 | ||
|
|
4813cefd18 | ||
|
|
2b5b836203 | ||
|
|
cac640fdea | ||
|
|
1118bda30f | ||
|
|
9dfae88805 | ||
|
|
7e8c38a80f | ||
|
|
7a4c71675b | ||
|
|
fced071837 | ||
|
|
82b51c0703 | ||
|
|
e734d09039 | ||
|
|
075fe19382 | ||
|
|
54277ced6b | ||
|
|
dca24a710c | ||
|
|
2c391af08b | ||
|
|
7a2571443c | ||
|
|
fe01d84777 | ||
|
|
8711bd2b4d | ||
|
|
60875f20d6 | ||
|
|
7b93eccc00 | ||
|
|
1ef4f2c02d | ||
|
|
a2d6c47133 | ||
|
|
8da598e7be | ||
|
|
98bb90a380 | ||
|
|
a9ff08f0ef | ||
|
|
0f26cdd272 | ||
|
|
2ead6da243 | ||
|
|
9e7440168e | ||
|
|
870f6c890f | ||
|
|
b13eab46de | ||
|
|
8c6ffd282c | ||
|
|
90bfbb9e72 | ||
|
|
bab239fb92 | ||
|
|
d22e27a285 | ||
|
|
38605f1ad8 | ||
|
|
0c3b7f9c6f | ||
|
|
d0355514ed | ||
|
|
501f21e532 | ||
|
|
c836385bde | ||
|
|
f707f2025b | ||
|
|
01c3ec7c91 | ||
|
|
e4621ab0b8 | ||
|
|
bc46de9e41 | ||
|
|
16aea2f26f | ||
|
|
338591c1b2 | ||
|
|
03238e23fa | ||
|
|
5b4e32b8b9 | ||
|
|
614432579b | ||
|
|
b992d81733 | ||
|
|
95e204b728 | ||
|
|
2c8dd1b145 | ||
|
|
564020bd5e | ||
|
|
6f431bb6d1 | ||
|
|
5c236885ce | ||
|
|
ea5991cc4e | ||
|
|
045f62d951 | ||
|
|
e6a8a6027c | ||
|
|
afc805c50e | ||
|
|
b14b2fde89 | ||
|
|
b37403a6ba | ||
|
|
72cd3bcd09 | ||
|
|
ee87eeb616 | ||
|
|
58240ff520 | ||
|
|
7c48643759 | ||
|
|
e682dfae6e | ||
|
|
8d5407767c | ||
|
|
787aa1a4ac | ||
|
|
e29505cf1b | ||
|
|
51b15046be | ||
|
|
12cf6b135b | ||
|
|
05d8bb3828 | ||
|
|
116ce29cb3 | ||
|
|
cb3678cc4f | ||
|
|
0a63a4a694 | ||
|
|
e642258f47 | ||
|
|
5184aefa88 | ||
|
|
dd2708f905 | ||
|
|
cfa93c6e12 | ||
|
|
e295704301 | ||
|
|
1456704918 | ||
|
|
cfb455d6ad | ||
|
|
2b62c9b9e0 | ||
|
|
f3c3b2bbb3 | ||
|
|
09af058fa1 | ||
|
|
eff1227b20 | ||
|
|
9a821b7117 | ||
|
|
7f46518257 | ||
|
|
b110ac9df8 | ||
|
|
49832aee8b | ||
|
|
aa50b9b144 | ||
|
|
ade080e47f | ||
|
|
c1ecc0781d | ||
|
|
cb89942991 | ||
|
|
09c0f311fc | ||
|
|
1d35a7bd2c | ||
|
|
c0eb4d68a7 | ||
|
|
7b9b5691dd | ||
|
|
4dd8c6ad46 | ||
|
|
a8e489a485 | ||
|
|
593e0eb404 | ||
|
|
3169289432 | ||
|
|
e0b1a03e38 | ||
|
|
01f7b4c638 | ||
|
|
1c56b3fd53 | ||
|
|
37bb023398 | ||
|
|
3cafe0af89 | ||
|
|
0ff8e1eff3 | ||
|
|
70ed29f2c9 | ||
|
|
f279917d91 | ||
|
|
d9c15fadb0 | ||
|
|
073d077bb5 | ||
|
|
82065f55d5 | ||
|
|
183be56112 | ||
|
|
5c8ef1fa4d | ||
|
|
7f9e8b52df | ||
|
|
f02c72b745 | ||
|
|
1a2800f115 | ||
|
|
33712b7d82 | ||
|
|
23a0a1ac4e | ||
|
|
471fe87429 | ||
|
|
d11d095816 | ||
|
|
b2aa693f1a | ||
|
|
eb51015c6c | ||
|
|
c2f7aa1258 | ||
|
|
d669842d01 |
No files matched your search
@@ -145,3 +145,7 @@ vite.config.ts.timestamp-*
|
||||
|
||||
docs/.vitepress/dist
|
||||
docs/.vitepress/cache
|
||||
docs/public/uploads/
|
||||
|
||||
.gtts/
|
||||
*.db
|
||||
Vendored
+11
-1
@@ -29,5 +29,15 @@
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||
"editor.maxTokenizationLineLength": 2500
|
||||
}
|
||||
},
|
||||
"[rust]": {
|
||||
"editor.quickSuggestions": {
|
||||
"other": true,
|
||||
"comments": false,
|
||||
"strings": true
|
||||
},
|
||||
"editor.tabSize": 4,
|
||||
"editor.formatOnSave": true,
|
||||
},
|
||||
"vue3snippets.enable-compile-vue-file-on-did-save-code": false
|
||||
}
|
||||
@@ -1,3 +1,71 @@
|
||||
Contents edited from <https://www.howtostudykorean.com> is at [/docs/howtostudykorean/](/docs/howtostudykorean/).
|
||||
|
||||
For specifics of how this is created, see <https://git.polv.cc/polv/zh-grammar#how-it-works-for-android>
|
||||
|
||||
## TTS
|
||||
|
||||
For Windows TTS, I don't like Korean language support pack sound, so I use
|
||||
|
||||
```shell
|
||||
docker run -it -p 5500:5500 synesthesiam/opentts:ko
|
||||
```
|
||||
|
||||
It's required to have Docker running.
|
||||
|
||||
## Full Text Search
|
||||
|
||||
This is done with [kuromoji-ko](https://www.npmjs.com/package/kuromoji-ko).
|
||||
|
||||
```js
|
||||
import { MeCab } from "kuromoji-ko";
|
||||
|
||||
const mecab = await MeCab.create({
|
||||
engine: "ko",
|
||||
dictPath: "./node_modules/kuromoji-ko/dict",
|
||||
});
|
||||
```
|
||||
|
||||
### Tagset
|
||||
|
||||
From <https://www.sketchengine.eu/hannanum-korean-tagset-simplified/>.
|
||||
|
||||
| ORIGINAL | SIMPLIFIED (in Sketch Engine) | DESCRIPTION | Example |
|
||||
| ----------------- | ----------------------------- | -------------- | --------------------- |
|
||||
| NOMINALS | | | |
|
||||
| NC | **N** | noun | |
|
||||
| NQ | **NP** | proper noun | |
|
||||
| NB | **N** | noun | |
|
||||
| NP | **Pron** | pronoun | |
|
||||
| NN | **Num** | numeral | |
|
||||
| PREDICATES | | | |
|
||||
| PV | **V** | verb | |
|
||||
| PA | **Adj** | adjective | |
|
||||
| PX | **VAux** | auxiliary verb | |
|
||||
| MODIFIERS | | | |
|
||||
| MM | **Det** | determiner | |
|
||||
| MA | **Adv** | adverb | |
|
||||
| INTERJECTION | | | |
|
||||
| II | **Interj** | interjection | |
|
||||
| RELATIONAL SUFFIX | | | |
|
||||
| JC | **Suff** | | |
|
||||
| JX | **Suff** | | |
|
||||
| JP | **Suff** | | |
|
||||
| ENDING | | | |
|
||||
| EP | **Suff** | | |
|
||||
| EC | **Suff** | | |
|
||||
| ET | **Suff** | | |
|
||||
| EF | **Suff** | | |
|
||||
| AFFIXES | | | |
|
||||
| XP | **Pref** | | 접두사 |
|
||||
| XS | **Suff** | | |
|
||||
| SYMBOLS | | | |
|
||||
| SP | **Sym** | | 쉼표 |
|
||||
| SL | **Sym** | | 여는 따옴표 및 묶음표 |
|
||||
| SD | **Sym** | | 이음표 |
|
||||
| SU | **Sym** | | 단위 기호 |
|
||||
| SF | **Sym** | | 마침표 |
|
||||
| SR | **Sym** | | 닫는 따옴표 및 묶음표 |
|
||||
| SE | **Sym** | | 줄임표 |
|
||||
| SY | **Sym** | | 기타 기호 |
|
||||
| FOREIGN WORDS | | | |
|
||||
| F | **X** | | |
|
||||
@@ -1,4 +1,6 @@
|
||||
import { defineConfig, MarkdownOptions } from "vitepress";
|
||||
import { defineConfig, type MarkdownOptions } from "vitepress";
|
||||
import { mp3DownloaderPlugin } from "./vite-plugins/mp3-downloader";
|
||||
import { gttsPlugin } from "./vite-plugins/gtts";
|
||||
|
||||
const host = process.env.TAURI_DEV_HOST;
|
||||
|
||||
@@ -7,9 +9,18 @@ export default defineConfig({
|
||||
title: "ko-grammar",
|
||||
description: "Korean grammar edited",
|
||||
lang: "ko-KR",
|
||||
head: [
|
||||
[
|
||||
"script",
|
||||
{
|
||||
async: "async",
|
||||
src: "https://www.youtube.com/iframe_api",
|
||||
},
|
||||
],
|
||||
],
|
||||
themeConfig: {
|
||||
socialLinks: [
|
||||
{ icon: "github", link: "https://github.com/vuejs/vitepress" },
|
||||
{ icon: "github", link: "https://git.polv.cc/polv/ko-grammar" },
|
||||
],
|
||||
outline: {
|
||||
level: "deep",
|
||||
@@ -65,10 +76,18 @@ export default defineConfig({
|
||||
},
|
||||
},
|
||||
vite: {
|
||||
plugins: [
|
||||
mp3DownloaderPlugin() as any,
|
||||
// (Python) pip install gtts
|
||||
// gtts will intercept /api/tts away from opentts:ko container
|
||||
gttsPlugin(),
|
||||
],
|
||||
envDir: process.cwd(),
|
||||
ssr: {
|
||||
noExternal: [],
|
||||
external: ["pdfjs-dist"], // don't bundle it for SSR — leave it browser-only
|
||||
},
|
||||
clearScreen: false,
|
||||
server: {
|
||||
/**
|
||||
* Allow Windows Firewall via Admin PowerShell with
|
||||
@@ -80,6 +99,10 @@ export default defineConfig({
|
||||
port: 5173,
|
||||
strictPort: true,
|
||||
host: host || false,
|
||||
watch: {
|
||||
// tell vite to ignore watching `src-tauri`
|
||||
ignored: ["**/src-tauri/**"],
|
||||
},
|
||||
hmr: host
|
||||
? {
|
||||
protocol: "ws",
|
||||
@@ -87,6 +110,21 @@ export default defineConfig({
|
||||
port: 5174,
|
||||
}
|
||||
: undefined,
|
||||
proxy: {
|
||||
// docker run -it -p 5500:5500 synesthesiam/opentts:ko
|
||||
"/api/tts": "http://localhost:5500",
|
||||
},
|
||||
},
|
||||
// Env variables starting with the item of `envPrefix` will be exposed in tauri's source code through `import.meta.env`.
|
||||
envPrefix: ["VITE_", "TAURI_ENV_*"],
|
||||
build: {
|
||||
// Tauri uses Chromium on Windows and WebKit on macOS and Linux
|
||||
target:
|
||||
process.env.TAURI_ENV_PLATFORM == "windows" ? "chrome105" : "safari13",
|
||||
// don't minify for debug builds
|
||||
minify: !process.env.TAURI_ENV_DEBUG ? "esbuild" : false,
|
||||
// produce sourcemaps for debug builds
|
||||
sourcemap: !!process.env.TAURI_ENV_DEBUG,
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<span>
|
||||
<span ref="main"><slot /></span>
|
||||
<button type="button" @click="playAudio()">▶️</button>
|
||||
<audio ref="audio" style="display: none"></audio>
|
||||
</span>
|
||||
@@ -7,17 +8,50 @@
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTemplateRef } from "vue";
|
||||
import { stop as stopTTS } from "tauri-plugin-tts-api";
|
||||
|
||||
const props = defineProps<{
|
||||
src: string;
|
||||
}>();
|
||||
|
||||
defineExpose({
|
||||
playAudio,
|
||||
});
|
||||
|
||||
const mainEl = useTemplateRef("main");
|
||||
const audioEl = useTemplateRef("audio");
|
||||
|
||||
function playAudio() {
|
||||
async function playAudio() {
|
||||
if (!audioEl.value) return;
|
||||
audioEl.value.src = props.src;
|
||||
audioEl.value.play();
|
||||
|
||||
document.querySelectorAll("audio").forEach((el) => {
|
||||
el.pause();
|
||||
});
|
||||
stopTTS();
|
||||
|
||||
const uploadURL = "https://www.howtostudykorean.com/wp-content/uploads";
|
||||
let src = props.src;
|
||||
if (src.startsWith(uploadURL)) {
|
||||
src = src.replace(uploadURL, "/uploads");
|
||||
if (mainEl.value) {
|
||||
src += `?text=${encodeURIComponent(mainEl.value.innerText.trim())}`;
|
||||
}
|
||||
|
||||
audioEl.value.onerror = () => {
|
||||
if (!audioEl.value) return;
|
||||
console.log(audioEl.value.error, src);
|
||||
|
||||
audioEl.value.src = props.src;
|
||||
audioEl.value.currentTime = 0;
|
||||
audioEl.value.play();
|
||||
};
|
||||
} else {
|
||||
audioEl.value.onerror = null;
|
||||
}
|
||||
|
||||
audioEl.value.src = src;
|
||||
audioEl.value.currentTime = 0;
|
||||
await audioEl.value.play();
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
<template>
|
||||
<component
|
||||
:is="lang !== 'ko' || v.audio ? 'span' : TTS"
|
||||
ref="stts"
|
||||
:text="v.ko_text"
|
||||
>
|
||||
<span
|
||||
v-for="(seg, i) in v[lang].split('**')"
|
||||
:key="i"
|
||||
:class="i % 2 === 0 ? '' : spoiler ? 'spoiler' : $style.em"
|
||||
>
|
||||
{{ seg }}
|
||||
</span>
|
||||
<AudioButton v-if="lang === 'ko' && v.audio" :src="v.audio" ref="saud" />
|
||||
</component>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useTemplateRef } from "vue";
|
||||
import TTS from "./TTS.vue";
|
||||
import AudioButton from "./AudioButton.vue";
|
||||
import { IVoc } from "../types.ts";
|
||||
|
||||
defineProps<{
|
||||
v: IVoc;
|
||||
lang: "ko" | "en";
|
||||
spoiler?: boolean;
|
||||
}>();
|
||||
|
||||
defineExpose({
|
||||
playAudio,
|
||||
});
|
||||
|
||||
const stts = useTemplateRef<HTMLSpanElement | InstanceType<typeof TTS>>("stts");
|
||||
const saud = useTemplateRef<InstanceType<typeof AudioButton>>("saud");
|
||||
|
||||
async function playAudio() {
|
||||
if (saud.value) {
|
||||
await saud.value.playAudio();
|
||||
} else if (stts.value && "playAudio" in stts.value) {
|
||||
await stts.value.playAudio();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
.em {
|
||||
font-style: italic;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<div id="sentence-quiz" :class="$style.root" ref="main">
|
||||
<button type="button" @click="nextSentence()">Next</button>
|
||||
<slot />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { nextTick, onMounted, ref, useTemplateRef } from "vue";
|
||||
|
||||
const mainEl = useTemplateRef("main");
|
||||
const sentences = ref<number[]>([]);
|
||||
const sentences_array_index = ref(NaN);
|
||||
|
||||
function nextSentence() {
|
||||
if (!mainEl.value) return;
|
||||
|
||||
const getCurrentSentenceIndex = () => {
|
||||
if (sentences.value.length <= 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (++sentences_array_index.value < sentences.value.length) {
|
||||
return sentences.value[sentences_array_index.value];
|
||||
}
|
||||
|
||||
sentences.value = sentences.value
|
||||
.map((s) => ({ s, k: Math.random() }))
|
||||
.sort((a, b) => a.k - b.k)
|
||||
.map((a) => a.s);
|
||||
|
||||
sentences_array_index.value = 0;
|
||||
|
||||
return sentences.value[sentences_array_index.value];
|
||||
};
|
||||
|
||||
const currentSentenceIndex = getCurrentSentenceIndex();
|
||||
|
||||
mainEl.value.querySelectorAll("#sentence-quiz > ul > li").forEach((el, i) => {
|
||||
if (!(el instanceof HTMLElement)) return;
|
||||
el.style.display = i === currentSentenceIndex ? "" : "none";
|
||||
});
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
nextTick(() => {
|
||||
if (!mainEl.value) return;
|
||||
|
||||
sentences.value = Array.from(
|
||||
mainEl.value.querySelectorAll("#sentence-quiz > ul > li"),
|
||||
).map((el, i) => i);
|
||||
|
||||
nextSentence();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
.root {
|
||||
margin-top: 1em;
|
||||
|
||||
&:hover li li:not(:hover) {
|
||||
filter: blur(5px);
|
||||
}
|
||||
|
||||
> button {
|
||||
float: right;
|
||||
border: 1px solid gray;
|
||||
padding: 0 0.5em;
|
||||
border-radius: 5px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -3,8 +3,15 @@
|
||||
<span ref="main" :class="class" :lang="lang">
|
||||
<slot />
|
||||
</span>
|
||||
<audio
|
||||
style="display: none"
|
||||
ref="audio"
|
||||
@error="playAudioTTSPlugin()"
|
||||
></audio>
|
||||
<span>
|
||||
<button type="button" @click="playAudio()">🗣️</button>
|
||||
<button type="button" @click="playAudio()" :class="$style.speak">
|
||||
🗣️
|
||||
</button>
|
||||
</span>
|
||||
</span>
|
||||
</template>
|
||||
@@ -13,25 +20,62 @@
|
||||
import { useTemplateRef } from "vue";
|
||||
import { speak, getVoices } from "tauri-plugin-tts-api";
|
||||
|
||||
const { lang = "ko-KR" } = defineProps<{
|
||||
defineExpose({
|
||||
playAudio,
|
||||
});
|
||||
|
||||
const { lang = "ko-KR", text } = defineProps<{
|
||||
class?: string;
|
||||
lang?: string;
|
||||
text?: string;
|
||||
}>();
|
||||
|
||||
const mainEl = useTemplateRef("main");
|
||||
const audioEl = useTemplateRef("audio");
|
||||
|
||||
function getMainText() {
|
||||
if (text) return text;
|
||||
|
||||
if (!mainEl.value) return "";
|
||||
|
||||
return mainEl.value.innerText
|
||||
.replace(/[*]/gu, " ")
|
||||
.replace(/[\p{Ps}\p{Pe}]/gu, "")
|
||||
.trim();
|
||||
}
|
||||
|
||||
async function playAudio() {
|
||||
if (!mainEl.value) return;
|
||||
const mainText = getMainText();
|
||||
if (!mainText) return;
|
||||
|
||||
if (navigator.platform === "Win32" || !(await playAudioTTSPlugin())) {
|
||||
if (!audioEl.value) return;
|
||||
|
||||
const url = new URL("/api/tts", location.origin);
|
||||
url.searchParams.set("voice", "glow-speak:ko_kss");
|
||||
url.searchParams.set("text", mainText);
|
||||
|
||||
audioEl.value.src = url.href;
|
||||
audioEl.value.currentTime = 0;
|
||||
audioEl.value.play();
|
||||
}
|
||||
}
|
||||
|
||||
async function playAudioTTSPlugin(): Promise<boolean> {
|
||||
const mainText = getMainText();
|
||||
if (!mainText) return false;
|
||||
|
||||
const voices = await getVoices(lang);
|
||||
if (!voices.length) return;
|
||||
if (!voices.length) return false;
|
||||
|
||||
document.querySelectorAll("audio").forEach((el) => {
|
||||
el.pause();
|
||||
});
|
||||
|
||||
const v = voices[Math.floor(Math.random() * voices.length)];
|
||||
console.log(JSON.stringify(v));
|
||||
await speak({
|
||||
text: mainEl.value.innerText
|
||||
.replace(/[*]/gu, " ")
|
||||
.replace(/[\p{Ps}\p{Pe}]/gu, ""),
|
||||
text: mainText,
|
||||
language: null,
|
||||
rate: null,
|
||||
volume: null,
|
||||
@@ -39,7 +83,13 @@ async function playAudio() {
|
||||
queueMode: null,
|
||||
voiceId: v.id,
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
</script>
|
||||
|
||||
<style module></style>
|
||||
<style module>
|
||||
.speak {
|
||||
margin-inline-start: 0.2em;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,705 @@
|
||||
<template>
|
||||
<div>
|
||||
<nav v-if="v">
|
||||
<Teleport to="body">
|
||||
<div v-if="isEdit" :class="$style.modal" ref="modal">
|
||||
<nav>
|
||||
<span> ko: {{ v.ko }} </span>
|
||||
<div style="flex-grow: 1"></div>
|
||||
<button type="button" @click="onVContentSave()">Save</button>
|
||||
<button type="button" @click="isEdit = false">×</button>
|
||||
</nav>
|
||||
<textarea
|
||||
v-model="vEditContent"
|
||||
spellcheck="false"
|
||||
ref="textarea"
|
||||
></textarea>
|
||||
</div>
|
||||
</Teleport>
|
||||
|
||||
<div :class="$style.mark">
|
||||
<button type="button" name="edit" @click="isEdit = true">✎</button>
|
||||
<button type="button" name="right" @click="mark(true)">✓</button>
|
||||
<button
|
||||
type="button"
|
||||
name="wrong"
|
||||
@click="mark(false)"
|
||||
style="font-size: large"
|
||||
>
|
||||
↻
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<span :class="quizState.isKoFirst ? '' : 'spoiler'">
|
||||
<SentenceAudio :v="v" lang="ko" ref="vaud" />
|
||||
</span>
|
||||
<span>{{ " = " }}</span>
|
||||
<span :class="quizState.isKoFirst ? 'spoiler' : ''">
|
||||
<SentenceAudio :v="v" lang="en" />
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<details v-if="sent_ko || v.notes" ref="sdetails">
|
||||
<summary>
|
||||
<SentenceAudio
|
||||
v-if="example"
|
||||
:v="example"
|
||||
lang="ko"
|
||||
:spoiler="!quizState.isKoFirst"
|
||||
ref="saud"
|
||||
/>
|
||||
<button
|
||||
type="button"
|
||||
name="new-sentence"
|
||||
v-if="v.examples && v.examples.length > 1"
|
||||
@click="makeNewExIndex()"
|
||||
style="margin-inline-start: 0.5em"
|
||||
>
|
||||
↻
|
||||
</button>
|
||||
</summary>
|
||||
<SentenceAudio v-if="example" :v="example" lang="en" />
|
||||
|
||||
<blockquote
|
||||
v-if="notes.length"
|
||||
:class="$style.notes"
|
||||
v-html="markdownIt.render(notes.join('\n\n'))"
|
||||
></blockquote>
|
||||
|
||||
<div>
|
||||
<button
|
||||
type="button"
|
||||
v-if="sent_ko"
|
||||
:disabled="exCurrentKo !== sent_ko"
|
||||
@click="
|
||||
if (exNotes) {
|
||||
exNotes = '';
|
||||
}
|
||||
explainSentence(sent_ko);
|
||||
"
|
||||
>
|
||||
<span v-if="exCurrentKo !== sent_ko">
|
||||
{{ exNotesLoading || "..." }}
|
||||
</span>
|
||||
<span v-else-if="!!exNotesLoading"> {{ exNotesLoading }} </span>
|
||||
<span v-else-if="!exNotes"> Explain Sentence </span>
|
||||
<span v-else> New explanation </span>
|
||||
</button>
|
||||
<blockquote v-if="exNotes" v-html="markdownIt.render(exNotes)" />
|
||||
</div>
|
||||
</details>
|
||||
</nav>
|
||||
<details :class="$style.options">
|
||||
<summary>🧐 Quiz options</summary>
|
||||
<nav v-if="vCats.length > 1">
|
||||
<label v-for="c in vCats" :key="c">
|
||||
<input
|
||||
type="checkbox"
|
||||
:name="c"
|
||||
:checked="quizState.vChosenCats.includes(c)"
|
||||
@change="updateCats(c)"
|
||||
/>
|
||||
{{ c.replace(/_/g, " ") }}
|
||||
</label>
|
||||
</nav>
|
||||
<nav>
|
||||
<span>
|
||||
<label role="switch">
|
||||
<span>KR</span>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="front"
|
||||
role="switch"
|
||||
v-model="quizState.isKoFirst"
|
||||
/>
|
||||
<span role="slider"></span>
|
||||
<span>EN</span>
|
||||
</label>
|
||||
</span>
|
||||
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="autoplay-audio"
|
||||
v-model="quizState.isAutoplayAudio"
|
||||
/>
|
||||
autoplay sentence audio
|
||||
</label>
|
||||
</nav>
|
||||
</details>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { useData } from "vitepress";
|
||||
import {
|
||||
computed,
|
||||
nextTick,
|
||||
onBeforeUnmount,
|
||||
onMounted,
|
||||
reactive,
|
||||
ref,
|
||||
useTemplateRef,
|
||||
watch,
|
||||
} from "vue";
|
||||
import yaml from "yaml";
|
||||
import SentenceAudio from "./SentenceAudio.vue";
|
||||
import { supabase } from "../supabase.ts";
|
||||
import { fmValueParser, IVoc, Voc } from "../types.ts";
|
||||
import { LLMstream } from "../llm.ts";
|
||||
import MarkdownIt from "markdown-it";
|
||||
|
||||
const { fmKey = "vocabulary", category } = defineProps<{
|
||||
fmKey?: string;
|
||||
category?: string;
|
||||
}>();
|
||||
|
||||
const vCats = ref<string[]>([]);
|
||||
const vList = ref<IVoc[]>([]);
|
||||
const vListOriginalIndex = ref<{ s: IVoc; k: number }[]>([]);
|
||||
const vIndex = ref(-1);
|
||||
const exIndex = ref(0);
|
||||
|
||||
const isEdit = ref(false);
|
||||
const vEditContent = ref("");
|
||||
|
||||
const exCurrentKo = ref("");
|
||||
const exNotes = ref("");
|
||||
const exNotesLoading = ref("");
|
||||
|
||||
const quizState = reactive({
|
||||
vChosenCats: [] as string[],
|
||||
isAutoplayAudio: true,
|
||||
isKoFirst: true,
|
||||
});
|
||||
|
||||
const modalRef = useTemplateRef("modal");
|
||||
const textareaRef = useTemplateRef("textarea");
|
||||
|
||||
const sentenceDetails = useTemplateRef("sdetails");
|
||||
const saud = useTemplateRef<InstanceType<typeof SentenceAudio>>("saud");
|
||||
const vaud = useTemplateRef<InstanceType<typeof SentenceAudio>>("vaud");
|
||||
|
||||
const v = computed<IVoc | null>(() => vList.value[vIndex.value] || null);
|
||||
const example = computed(() => {
|
||||
if (!v.value?.examples?.length) return null;
|
||||
const ex = v.value.examples;
|
||||
return ex[exIndex.value] || null;
|
||||
});
|
||||
|
||||
const sent_ko = computed(() => {
|
||||
if (example.value) return example.value.ko || "";
|
||||
if (fmKey === "vocabulary") return "";
|
||||
return v.value?.ko || "";
|
||||
});
|
||||
|
||||
const notes = computed(() => [
|
||||
...[example.value?.notes || []].flat(),
|
||||
...[v.value?.notes || []].flat(),
|
||||
]);
|
||||
|
||||
const MAX_VOC = 5;
|
||||
|
||||
const { frontmatter, page } = useData();
|
||||
|
||||
const LOCALSTORAGE_STATE = JSON.stringify([
|
||||
page.value.filePath,
|
||||
fmKey,
|
||||
category,
|
||||
]);
|
||||
|
||||
if (typeof window !== "undefined" && window.localStorage) {
|
||||
const oldStateString = window.localStorage.getItem(LOCALSTORAGE_STATE);
|
||||
if (oldStateString) {
|
||||
try {
|
||||
Object.assign(quizState, JSON.parse(oldStateString));
|
||||
} catch (e) {}
|
||||
}
|
||||
}
|
||||
|
||||
function saveQuizState() {
|
||||
window.localStorage.setItem(LOCALSTORAGE_STATE, JSON.stringify(quizState));
|
||||
}
|
||||
|
||||
watch(quizState, () => {
|
||||
saveQuizState();
|
||||
});
|
||||
|
||||
let timeoutSetExNotes = 0;
|
||||
|
||||
watch(sent_ko, () => {
|
||||
if (timeoutSetExNotes) return;
|
||||
|
||||
timeoutSetExNotes = window.setTimeout(() => {
|
||||
timeoutSetExNotes = 0;
|
||||
|
||||
if (!exNotesLoading.value) {
|
||||
exNotes.value = "";
|
||||
}
|
||||
|
||||
if (!sent_ko.value) return;
|
||||
|
||||
let ko = sent_ko.value;
|
||||
ko = ko.replaceAll("**", "");
|
||||
|
||||
if (!exNotesLoading.value) {
|
||||
exCurrentKo.value = sent_ko.value;
|
||||
}
|
||||
|
||||
if (supabase) {
|
||||
supabase
|
||||
.from("sentence-explain")
|
||||
.select<any, { explain: string }>("explain")
|
||||
.eq("ko", ko)
|
||||
.then((r) => {
|
||||
if (!r.data?.[0]) return;
|
||||
exNotes.value = r.data[0].explain;
|
||||
});
|
||||
}
|
||||
}, 50);
|
||||
});
|
||||
|
||||
const vocabulary: Record<string, IVoc[]> = {};
|
||||
|
||||
for (const [k, vs] of Object.entries(
|
||||
fmValueParser.parse(frontmatter.value[fmKey]),
|
||||
)) {
|
||||
vocabulary[k] = [...(vocabulary[k] || []), ...vs];
|
||||
|
||||
if (!vCats.value.includes(k)) {
|
||||
vCats.value = [...vCats.value, k];
|
||||
}
|
||||
}
|
||||
|
||||
if (category) {
|
||||
const vCatsSet = new Set(category.split(/[, ]+/g));
|
||||
const newVCats = vCats.value.filter((c) => vCatsSet.has(c));
|
||||
if (newVCats.length) {
|
||||
vCats.value = newVCats;
|
||||
}
|
||||
}
|
||||
|
||||
if (!quizState.vChosenCats.some((c) => vCats.value.includes(c))) {
|
||||
quizState.vChosenCats = [...vCats.value];
|
||||
}
|
||||
|
||||
watch(
|
||||
() => quizState.isKoFirst,
|
||||
() => {
|
||||
makeVList();
|
||||
},
|
||||
);
|
||||
|
||||
watch(isEdit, () => {
|
||||
if (!v.value) return;
|
||||
|
||||
if (isEdit.value) {
|
||||
const { ko, ...vContent } = v.value;
|
||||
vEditContent.value = yaml.stringify(vContent);
|
||||
|
||||
nextTick(() => {
|
||||
if (textareaRef.value) {
|
||||
textareaRef.value.style.height = textareaRef.value.scrollHeight + "px";
|
||||
}
|
||||
});
|
||||
} else {
|
||||
vEditContent.value = "";
|
||||
}
|
||||
});
|
||||
|
||||
function makeVList() {
|
||||
nextTick(() => {
|
||||
if (sentenceDetails.value) {
|
||||
sentenceDetails.value.open = false;
|
||||
}
|
||||
});
|
||||
|
||||
const newVList = Object.entries(vocabulary)
|
||||
.filter(([k]) => quizState.vChosenCats.includes(k))
|
||||
.flatMap(([, vs]) => vs);
|
||||
|
||||
vListOriginalIndex.value = newVList.map((s) => ({
|
||||
s,
|
||||
k: Math.random(),
|
||||
}));
|
||||
|
||||
vList.value = vListOriginalIndex.value
|
||||
.sort((a, b) => a.k - b.k)
|
||||
.map((a) => a.s);
|
||||
|
||||
vIndex.value = Math.floor(
|
||||
Math.random() * Math.min(MAX_VOC, vList.value.length),
|
||||
);
|
||||
|
||||
if (!v.value) return;
|
||||
|
||||
const ex = v.value.examples;
|
||||
exIndex.value = ex ? Math.floor(Math.random() * ex.length) : 0;
|
||||
}
|
||||
|
||||
function makeNewExIndex() {
|
||||
if (!v.value) return;
|
||||
|
||||
if (v.value.examples && v.value.examples.length > 1) {
|
||||
const newValue = Math.floor(Math.random() * (v.value.examples.length - 1));
|
||||
exIndex.value = newValue >= exIndex.value ? newValue + 1 : newValue;
|
||||
|
||||
nextTick(() => {
|
||||
if (saud.value && quizState.isAutoplayAudio) {
|
||||
saud.value.playAudio();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function mark(isRight: boolean) {
|
||||
exNotes.value = "";
|
||||
|
||||
nextTick(() => {
|
||||
if (sentenceDetails.value) {
|
||||
sentenceDetails.value.open = false;
|
||||
}
|
||||
|
||||
if (quizState.isAutoplayAudio) {
|
||||
nextTick(() => {
|
||||
if (saud.value) {
|
||||
saud.value.playAudio();
|
||||
} else if (vaud.value && quizState.isKoFirst) {
|
||||
vaud.value.playAudio();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
if (isRight) {
|
||||
vList.value = [...vList.value.filter((_, i) => i !== vIndex.value)];
|
||||
vIndex.value = -1;
|
||||
|
||||
if (vList.value.length <= 1) {
|
||||
makeVList();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const i = Math.floor(
|
||||
Math.random() * (Math.min(MAX_VOC, vList.value.length) - 1),
|
||||
);
|
||||
|
||||
if (i >= vIndex.value) {
|
||||
vIndex.value = i + 1;
|
||||
} else {
|
||||
vIndex.value = i;
|
||||
}
|
||||
|
||||
if (!v.value) return;
|
||||
|
||||
const ex = v.value.examples;
|
||||
exIndex.value = ex ? Math.floor(Math.random() * ex.length) : 0;
|
||||
}
|
||||
|
||||
function updateCats(cat: string) {
|
||||
const i = quizState.vChosenCats.indexOf(cat);
|
||||
if (i === -1) {
|
||||
quizState.vChosenCats = [...quizState.vChosenCats, cat];
|
||||
} else {
|
||||
quizState.vChosenCats = [
|
||||
...quizState.vChosenCats.filter((_, j) => j !== i),
|
||||
];
|
||||
}
|
||||
|
||||
makeVList();
|
||||
|
||||
saveQuizState();
|
||||
}
|
||||
|
||||
async function onVContentSave() {
|
||||
if (!v.value) return;
|
||||
|
||||
const oldV = v.value;
|
||||
const newV = Voc.parse({ ko: oldV.ko, ...yaml.parse(vEditContent.value) });
|
||||
|
||||
let key = "";
|
||||
let vKey = oldV.ko;
|
||||
|
||||
Object.entries(vocabulary).map(([k, vs]) => {
|
||||
const vCount = new Map<string, number>();
|
||||
|
||||
vs.map((v, i_vs) => {
|
||||
let vK = v.ko;
|
||||
let i = vCount.get(v.ko) || 0;
|
||||
if (i) {
|
||||
vK = vK + `(${i})`;
|
||||
}
|
||||
vCount.set(v.ko, i + 1);
|
||||
|
||||
if (oldV.ko === v.ko && oldV.en === v.en) {
|
||||
key = JSON.stringify([fmKey, k]);
|
||||
vKey = vK;
|
||||
|
||||
vocabulary[k][i_vs] = newV;
|
||||
}
|
||||
});
|
||||
});
|
||||
if (supabase && key) {
|
||||
const user_id = await supabase.auth.getUser().then((r) => r.data.user?.id);
|
||||
|
||||
await supabase.from("quiz").upsert(
|
||||
{
|
||||
url: page.value.filePath,
|
||||
key,
|
||||
v: vKey,
|
||||
data: newV,
|
||||
user_id,
|
||||
},
|
||||
{ onConflict: "url,key,v,user_id" },
|
||||
);
|
||||
}
|
||||
|
||||
const newVList = [...vList.value];
|
||||
newVList[vIndex.value] = newV;
|
||||
vList.value = newVList;
|
||||
|
||||
isEdit.value = false;
|
||||
}
|
||||
|
||||
const markdownIt = new MarkdownIt({
|
||||
html: true,
|
||||
breaks: true,
|
||||
linkify: true,
|
||||
typographer: true,
|
||||
});
|
||||
|
||||
let loadingIntervalId = 0;
|
||||
|
||||
async function explainSentence(ko: string) {
|
||||
if (loadingIntervalId) return;
|
||||
|
||||
ko = ko.replaceAll("**", "");
|
||||
|
||||
exNotesLoading.value = ".";
|
||||
loadingIntervalId = window.setInterval(() => {
|
||||
exNotesLoading.value += ".";
|
||||
}, 1000);
|
||||
|
||||
// Needs to be specified, or DeepSeek will vacillate between Korean, English, and Chinese.
|
||||
const LANG_EXPLAIN = "Japanese";
|
||||
|
||||
for await (const data of LLMstream({
|
||||
model: "deepseek-v4-flash",
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: `
|
||||
Explain in ${LANG_EXPLAIN} how this sentence works in 500 characters.
|
||||
Give me key vocabularies in a table.
|
||||
Don't give romanization forms.
|
||||
`,
|
||||
},
|
||||
{ role: "user", content: ko },
|
||||
],
|
||||
})) {
|
||||
if (data.done) break;
|
||||
if (data.content) {
|
||||
exNotes.value += data.content;
|
||||
}
|
||||
}
|
||||
|
||||
clearInterval(loadingIntervalId);
|
||||
exNotesLoading.value = "";
|
||||
loadingIntervalId = 0;
|
||||
|
||||
if (exNotes.value && supabase) {
|
||||
const user_id = await supabase.auth.getUser().then((r) => r.data.user?.id);
|
||||
|
||||
await supabase.from("sentence-explain").upsert(
|
||||
{
|
||||
user_id,
|
||||
ko,
|
||||
explain: exNotes.value,
|
||||
},
|
||||
{ onConflict: "ko,user_id" },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function onModalClickOutside(ev: MouseEvent) {
|
||||
if (!(ev.target instanceof HTMLElement)) return;
|
||||
if (ev.target.matches('[name="edit"]')) return;
|
||||
|
||||
if (!modalRef.value) {
|
||||
isEdit.value = false;
|
||||
} else if (!modalRef.value.contains(ev.target.parentNode)) {
|
||||
isEdit.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(async () => {
|
||||
document.addEventListener("click", onModalClickOutside);
|
||||
makeVList();
|
||||
|
||||
if (supabase) {
|
||||
await supabase
|
||||
.from("quiz")
|
||||
.select<any, { v: string; data: IVoc }>("v,data")
|
||||
.eq("url", page.value.filePath)
|
||||
.then((r) => {
|
||||
if (!r.data?.length) return;
|
||||
|
||||
const replacement = new Map<string, IVoc>();
|
||||
for (const { v, data } of r.data) {
|
||||
replacement.set(v, data);
|
||||
}
|
||||
|
||||
Object.entries(vocabulary).map(([k, vs]) => {
|
||||
const vCount = new Map<string, number>();
|
||||
|
||||
vocabulary[k] = vs.map((v) => {
|
||||
let vKey = v.ko;
|
||||
let i = vCount.get(v.ko) || 0;
|
||||
if (i) {
|
||||
vKey = vKey + `(${i})`;
|
||||
}
|
||||
vCount.set(v.ko, i + 1);
|
||||
|
||||
return replacement.get(vKey) || v;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// const newVList = Object.entries(vocabulary)
|
||||
// .filter(([k]) => vChosenCats.value.includes(k))
|
||||
// .flatMap(([, vs]) => vs);
|
||||
|
||||
// vList.value = vListOriginalIndex.value
|
||||
// .map((o, i) => {
|
||||
// o.s = newVList[i] || o.s;
|
||||
// return o;
|
||||
// })
|
||||
// .sort((a, b) => a.k - b.k)
|
||||
// .map((o) => o.s);
|
||||
|
||||
makeVList();
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
document.addEventListener("click", onModalClickOutside);
|
||||
|
||||
if (loadingIntervalId) {
|
||||
clearInterval(loadingIntervalId);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
.mark {
|
||||
float: right;
|
||||
|
||||
> * + * {
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
}
|
||||
.notes {
|
||||
div + div,
|
||||
p + p {
|
||||
margin-top: 0.5em !important;
|
||||
}
|
||||
}
|
||||
|
||||
.options {
|
||||
label {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
* + label {
|
||||
margin-inline-start: 0.5em;
|
||||
}
|
||||
|
||||
label[role="switch"] {
|
||||
--slider-width: 50px;
|
||||
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
width: calc(var(--slider-width) + 4em);
|
||||
height: 24px;
|
||||
|
||||
input[role="switch"] {
|
||||
opacity: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
/* The track */
|
||||
[role="slider"] {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
background-color: #ccc;
|
||||
border-radius: 24px;
|
||||
width: var(--slider-width);
|
||||
height: 100%;
|
||||
transition: background-color 0.3s;
|
||||
|
||||
+ span {
|
||||
margin-left: calc(var(--slider-width) + 0.5em);
|
||||
}
|
||||
}
|
||||
|
||||
/* The circular slider */
|
||||
[role="slider"]::before {
|
||||
content: "";
|
||||
position: absolute;
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
left: 4px;
|
||||
bottom: 2px;
|
||||
background-color: rgb(87, 87, 87);
|
||||
border-radius: 50%;
|
||||
transition: transform 0.3s;
|
||||
}
|
||||
|
||||
/* Toggled state */
|
||||
input:not(:checked) {
|
||||
+ [role="slider"] {
|
||||
/* background-color: #4caf50; */
|
||||
background-color: gainsboro;
|
||||
}
|
||||
+ [role="slider"]::before {
|
||||
transform: translateX(23px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.modal {
|
||||
--margin-top: 120px;
|
||||
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: calc(100vw - 4em);
|
||||
max-width: 1000px;
|
||||
|
||||
nav {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: rgba(128, 128, 128, 0.8);
|
||||
padding: 0.5em;
|
||||
border-radius: 0.5em 0.5em 0 0;
|
||||
|
||||
* + * {
|
||||
margin-inline-start: 1em;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
width: 100%;
|
||||
max-height: calc(90vh - var(--margin-top));
|
||||
padding: 1em;
|
||||
border-radius: 0 0 0.5em 0.5em;
|
||||
font-family: sans-serif;
|
||||
resize: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,10 +1,12 @@
|
||||
<template>
|
||||
<div :class="$style.container">
|
||||
<iframe
|
||||
ref="iframe"
|
||||
:class="$style.iframe"
|
||||
width="100%"
|
||||
height="100%"
|
||||
:src="'https://www.youtube.com/embed/' + $props.id"
|
||||
:src="url.href"
|
||||
:title="$props.title"
|
||||
frameborder="0"
|
||||
allow="
|
||||
accelerometer;
|
||||
@@ -13,14 +15,67 @@
|
||||
gyroscope;
|
||||
picture-in-picture;
|
||||
fullscreen;
|
||||
clipboard-write;
|
||||
web-share;
|
||||
"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
allowfullscreen
|
||||
>
|
||||
</iframe>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
defineProps<{ id: string; title?: string }>();
|
||||
import { onBeforeUnmount, onMounted, ref, useTemplateRef } from "vue";
|
||||
|
||||
const props = defineProps<{
|
||||
id?: string;
|
||||
list?: string;
|
||||
title?: string;
|
||||
}>();
|
||||
|
||||
const url = new URL(
|
||||
`https://www.youtube.com/embed/${props.id || "videoseries"}`,
|
||||
);
|
||||
url.searchParams.set("enablejsapi", "1");
|
||||
if (props.list) {
|
||||
url.searchParams.set("list", props.list);
|
||||
}
|
||||
|
||||
const iframe = useTemplateRef("iframe");
|
||||
const player = ref();
|
||||
|
||||
function onOrientationChanged() {
|
||||
if (player.value && iframe.value) {
|
||||
if (
|
||||
window.screen.orientation.type.startsWith("landscape") &&
|
||||
player.value.getPlayerState() === 1
|
||||
) {
|
||||
iframe.value.requestFullscreen();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const { YT } = window as any;
|
||||
if (YT?.Player && iframe.value) {
|
||||
player.value = new YT.Player(iframe.value);
|
||||
}
|
||||
|
||||
window.screen.orientation.addEventListener("change", onOrientationChanged);
|
||||
});
|
||||
|
||||
onBeforeUnmount(() => {
|
||||
window.screen.orientation.removeEventListener("change", onOrientationChanged);
|
||||
if (document.fullscreenElement) {
|
||||
document.exitFullscreen();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style module>
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
body {
|
||||
padding-top: env(safe-area-inset-top);
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
padding-left: env(safe-area-inset-left);
|
||||
padding-right: env(safe-area-inset-right);
|
||||
}
|
||||
|
||||
.spoiler:not(:hover) {
|
||||
filter: blur(5px);
|
||||
}
|
||||
@@ -7,12 +7,14 @@ import { h } from "vue";
|
||||
|
||||
import AudioButton from "./components/AudioButton.vue";
|
||||
import Details from "./components/Details.vue";
|
||||
import SentenceQuiz from "./components/SentenceQuiz.vue";
|
||||
// import PDF from "./components/PDF.vue";
|
||||
import TTS from "./components/TTS.vue";
|
||||
import VocabQuiz from "./components/VocabQuiz.vue";
|
||||
import YouTube from "./components/YouTube.vue";
|
||||
|
||||
import type { Theme } from "vitepress";
|
||||
|
||||
import { signIn } from "./supabase.ts";
|
||||
export default {
|
||||
extends: DefaultTheme,
|
||||
Layout: () => {
|
||||
@@ -24,8 +26,15 @@ export default {
|
||||
// ...
|
||||
app.component("AudioButton", AudioButton);
|
||||
app.component("Details", Details);
|
||||
app.component("SentenceQuiz", SentenceQuiz);
|
||||
app.component("TTS", TTS);
|
||||
app.component("VocabQuiz", VocabQuiz);
|
||||
app.component("YouTube", YouTube);
|
||||
// app.component("PDF", PDF);
|
||||
},
|
||||
} satisfies Theme;
|
||||
|
||||
//@ts-ignore
|
||||
if (!import.meta.env.SSR) {
|
||||
signIn();
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
import { fetch } from "@tauri-apps/plugin-http";
|
||||
|
||||
//@ts-ignore
|
||||
const { VITE_LLM_API_KEY } = import.meta.env;
|
||||
|
||||
// Minimal type definitions
|
||||
type DeepSeekChunk = {
|
||||
choices: Array<{
|
||||
delta: {
|
||||
content?: string;
|
||||
reasoning_content?: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
|
||||
// Type guard - simple and effective
|
||||
function isValidChunk(data: unknown): data is DeepSeekChunk {
|
||||
return (
|
||||
typeof data === "object" &&
|
||||
data !== null &&
|
||||
"choices" in data &&
|
||||
Array.isArray((data as any).choices) &&
|
||||
(data as any).choices.length > 0 &&
|
||||
"delta" in (data as any).choices[0]
|
||||
);
|
||||
}
|
||||
|
||||
// Helper - one-liner safe parse
|
||||
function safeParse<T>(text: string): T | null {
|
||||
try {
|
||||
return JSON.parse(text);
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export async function* LLMstream(body: {
|
||||
model: string;
|
||||
messages: {
|
||||
role: "system" | "user";
|
||||
content: string;
|
||||
}[];
|
||||
}) {
|
||||
if (!VITE_LLM_API_KEY) return;
|
||||
|
||||
let endpoint = "https://api.deepseek.com/chat/completions";
|
||||
|
||||
const response = await fetch(endpoint, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
Authorization: `Bearer ${VITE_LLM_API_KEY}`,
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
...body,
|
||||
stream: true,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!response.ok || !response.body) {
|
||||
throw response;
|
||||
}
|
||||
|
||||
const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
|
||||
|
||||
let buffer = "";
|
||||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done) break;
|
||||
|
||||
buffer += value;
|
||||
|
||||
const events = buffer.split("\n\n");
|
||||
buffer = events.pop() || "";
|
||||
|
||||
for (const event of events) {
|
||||
for (const line of event.split("\n")) {
|
||||
const DATA_START = "data: ";
|
||||
|
||||
if (!line.startsWith(DATA_START)) continue;
|
||||
const payload = line.slice(DATA_START.length);
|
||||
|
||||
if (payload === "[DONE]") {
|
||||
yield { content: "", done: true };
|
||||
return;
|
||||
}
|
||||
|
||||
const chunk = safeParse<DeepSeekChunk>(payload);
|
||||
|
||||
if (!chunk?.choices?.[0]?.delta) continue;
|
||||
|
||||
const delta = chunk.choices[0].delta;
|
||||
|
||||
// Yield content if present
|
||||
if (delta.content) {
|
||||
yield {
|
||||
content: delta.content,
|
||||
reasoning: delta.reasoning_content,
|
||||
done: false,
|
||||
};
|
||||
}
|
||||
|
||||
// Yield reasoning separately if present and no content
|
||||
if (delta.reasoning_content && !delta.content) {
|
||||
yield {
|
||||
content: "",
|
||||
reasoning: delta.reasoning_content,
|
||||
done: false,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
import { createClient } from "@supabase/supabase-js";
|
||||
|
||||
const {
|
||||
VITE_SUPABASE_URL,
|
||||
VITE_SUPABASE_PUBLISHABLE_KEY,
|
||||
VITE_SUPABASE_USER,
|
||||
VITE_SUPABASE_USER_PASSWORD,
|
||||
} =
|
||||
//@ts-ignore
|
||||
import.meta.env;
|
||||
|
||||
export const supabase = [
|
||||
VITE_SUPABASE_URL,
|
||||
VITE_SUPABASE_PUBLISHABLE_KEY,
|
||||
VITE_SUPABASE_USER,
|
||||
VITE_SUPABASE_USER_PASSWORD,
|
||||
].every((v) => v)
|
||||
? createClient(VITE_SUPABASE_URL, VITE_SUPABASE_PUBLISHABLE_KEY)
|
||||
: null;
|
||||
|
||||
export async function signIn() {
|
||||
if (!supabase) return;
|
||||
await supabase.auth.signInWithPassword({
|
||||
email: VITE_SUPABASE_USER,
|
||||
password: VITE_SUPABASE_USER_PASSWORD,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
import * as z from "zod";
|
||||
|
||||
// 1. Define the interface manually (do not use z.infer here)
|
||||
export interface IVoc {
|
||||
ko: string;
|
||||
ko_text?: string;
|
||||
audio?: string;
|
||||
en: string;
|
||||
usage?: IVoc[];
|
||||
notes?: string | string[];
|
||||
examples?: IVoc[];
|
||||
}
|
||||
|
||||
// 2. Annotate the schema with the manually defined interface
|
||||
export const Voc: z.ZodType<IVoc> = z.lazy(() =>
|
||||
z.object({
|
||||
ko: z.string(),
|
||||
ko_text: z.string().optional(),
|
||||
audio: z.string().optional(),
|
||||
en: z.string(),
|
||||
usage: z.array(Voc).optional(),
|
||||
notes: z.union([z.string(), z.array(z.string())]).optional(),
|
||||
examples: z
|
||||
.array(Voc)
|
||||
.superRefine((val, ctx) => {
|
||||
for (const x of val) {
|
||||
if (!isEmp(x.ko)) {
|
||||
ctx.addIssue(`${JSON.stringify(x)} must contain **emp** text`);
|
||||
}
|
||||
}
|
||||
})
|
||||
.optional(),
|
||||
}),
|
||||
);
|
||||
|
||||
export const fmValueParser = z.record(z.string(), z.array(Voc));
|
||||
|
||||
function isEmp(s: string) {
|
||||
return /\*\*.+\*\*/.test(s);
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
import fs from "node:fs";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import path from "node:path";
|
||||
import type { Connect, Plugin, ViteDevServer } from "vite";
|
||||
import { spawn } from "child_process";
|
||||
|
||||
export function gttsPlugin(): Plugin {
|
||||
return {
|
||||
name: "gtts",
|
||||
configureServer(server: ViteDevServer) {
|
||||
// Vite dev server middlewares are connect-style: (req, res, next)
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
const reqUrl = req.url;
|
||||
if (!reqUrl) return next();
|
||||
|
||||
const url = new URL(reqUrl, "http://localhost");
|
||||
if (url.pathname !== "/api/tts") return next();
|
||||
|
||||
const text = url.searchParams.get("text");
|
||||
if (!text) return next();
|
||||
|
||||
try {
|
||||
await gtts(text, req, res, next);
|
||||
} catch (e) {
|
||||
console.error(e, reqUrl);
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
let fileList: Record<string, number> = {};
|
||||
|
||||
async function gtts(
|
||||
text: string,
|
||||
req: Connect.IncomingMessage,
|
||||
res: ServerResponse<IncomingMessage>,
|
||||
next: Connect.NextFunction,
|
||||
) {
|
||||
text = text.replace(/["]/g, " ");
|
||||
|
||||
const saveroot = ".gtts";
|
||||
fs.mkdirSync(saveroot, { recursive: true });
|
||||
|
||||
const fileListJSON = path.join(saveroot, "gtts.json");
|
||||
|
||||
if (Object.keys(fileList).length === 0 && fs.existsSync(fileListJSON)) {
|
||||
fileList = JSON.parse(fs.readFileSync(fileListJSON, "utf-8"));
|
||||
}
|
||||
|
||||
let fileNo = fileList[text];
|
||||
|
||||
let isFileNoExists = Number.isInteger(fileNo);
|
||||
if (!isFileNoExists) {
|
||||
fileNo = Math.max(0, ...Object.values(fileList)) + 1;
|
||||
}
|
||||
|
||||
const filename = `${fileNo}.mp3`;
|
||||
const saveto = path.join(saveroot, filename);
|
||||
|
||||
if (!isFileNoExists || !fs.existsSync(saveto)) {
|
||||
await new Promise((resolve, reject) => {
|
||||
const p = spawn(
|
||||
"gtts-cli",
|
||||
[
|
||||
`"${text}"`,
|
||||
...["--lang", "ko"],
|
||||
...["--output", path.join(process.cwd(), saveto)],
|
||||
],
|
||||
{
|
||||
stdio: "inherit",
|
||||
shell: true,
|
||||
},
|
||||
);
|
||||
p.on("error", reject).on("close", resolve);
|
||||
});
|
||||
fileList[text] = fileNo;
|
||||
console.log(`gtts: ${text} saved to ${saveto}`);
|
||||
|
||||
fs.writeFileSync(fileListJSON, JSON.stringify(fileList, null, 2));
|
||||
} else {
|
||||
// console.log(`gtts: ${text} loaded from ${saveto}`);
|
||||
}
|
||||
|
||||
res.setHeader("Content-Type", "audio/mpeg");
|
||||
fs.createReadStream(saveto).pipe(res);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
import fs from "node:fs";
|
||||
import type { IncomingMessage, ServerResponse } from "node:http";
|
||||
import path from "node:path";
|
||||
import type { Connect, Plugin, ViteDevServer } from "vite";
|
||||
import sqlite3 from "better-sqlite3";
|
||||
import { Tokenizer } from "./tokenizer";
|
||||
|
||||
export function mp3DownloaderPlugin(): Plugin {
|
||||
return {
|
||||
name: "mp3-downloader",
|
||||
async configureServer(server: ViteDevServer) {
|
||||
const db = sqlite3(".sentence-mp3.db");
|
||||
db.exec(/* sql */ `
|
||||
CREATE TABLE IF NOT EXISTS sentence (
|
||||
id INTEGER NOT NULL PRIMARY KEY,
|
||||
ko TEXT NOT NULL,
|
||||
original TEXT NOT NULL,
|
||||
[url] TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_sentence_u_url ON sentence([url]);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS sentence_fts USING fts5 (
|
||||
ko,
|
||||
original UNINDEXED,
|
||||
[url] UNINDEXED,
|
||||
content='sentence',
|
||||
content_rowid='id'
|
||||
);
|
||||
|
||||
-- Triggers to keep the FTS index up to date.
|
||||
CREATE TRIGGER IF NOT EXISTS t1_ai AFTER INSERT ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(rowid, ko) VALUES (new.id, new.ko);
|
||||
END;
|
||||
CREATE TRIGGER IF NOT EXISTS t1_ad AFTER DELETE ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(fts_idx, rowid, ko) VALUES('delete', old.id, old.ko);
|
||||
END;
|
||||
CREATE TRIGGER IF NOT EXISTS t1_au AFTER UPDATE ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(fts_idx, rowid, ko) VALUES('delete', old.id, old.ko);
|
||||
INSERT INTO sentence_fts(rowid, ko) VALUES (new.id, new.ko);
|
||||
END;
|
||||
`);
|
||||
|
||||
let tokenizer: Tokenizer | null = null;
|
||||
|
||||
// Vite dev server middlewares are connect-style: (req, res, next)
|
||||
server.middlewares.use(async (req, res, next) => {
|
||||
const reqUrl = req.url;
|
||||
if (!reqUrl || !reqUrl.startsWith("/uploads/")) return next();
|
||||
|
||||
const url = new URL(reqUrl, "http://localhost");
|
||||
if (!url.pathname.endsWith(".mp3")) return next();
|
||||
|
||||
try {
|
||||
// if (!tokenizer) {
|
||||
// tokenizer = await Tokenizer.init();
|
||||
// }
|
||||
|
||||
await mp3Downloader(db, tokenizer, url, res, next);
|
||||
} catch (e) {
|
||||
console.error(e, reqUrl);
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function mp3Downloader(
|
||||
db: ReturnType<typeof sqlite3>,
|
||||
tokenizer: Tokenizer,
|
||||
url: URL,
|
||||
res: ServerResponse<IncomingMessage>,
|
||||
next: Connect.NextFunction,
|
||||
) {
|
||||
const downloadURL = new URL(
|
||||
`https://www.howtostudykorean.com/wp-content${url.pathname}`,
|
||||
);
|
||||
|
||||
// const text = url.searchParams.get("text");
|
||||
// if (text) {
|
||||
// db.prepare(
|
||||
// "INSERT OR IGNORE INTO sentence ([url], ko, original) VALUES (?, ?, ?)",
|
||||
// ).run(downloadURL.href, tokenizer.normalize(text), text);
|
||||
// }
|
||||
|
||||
const segs = url.pathname.slice(1).split("/");
|
||||
const filename = segs.pop()!;
|
||||
const saveroot = "docs/public";
|
||||
const saveto = path.join(saveroot, ...segs, filename);
|
||||
|
||||
if (fs.existsSync(saveto)) {
|
||||
return next();
|
||||
}
|
||||
|
||||
fs.mkdirSync(path.join(saveroot, ...segs), { recursive: true });
|
||||
|
||||
const r = await fetch(downloadURL, { redirect: "follow" });
|
||||
if (!r.ok) {
|
||||
console.error(r);
|
||||
return next();
|
||||
}
|
||||
|
||||
fs.writeFileSync(saveto, Buffer.from(await r.arrayBuffer()));
|
||||
// console.log(fs.statSync(saveto));
|
||||
console.log("saved to", saveto);
|
||||
|
||||
res.setHeader("Content-Type", "audio/mpeg");
|
||||
fs.createReadStream(saveto).pipe(res);
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
import { MeCab } from "kuromoji-ko";
|
||||
|
||||
export class Tokenizer {
|
||||
static async init() {
|
||||
return new Tokenizer(
|
||||
await MeCab.create({
|
||||
engine: "ko",
|
||||
dictPath: "./node_modules/kuromoji-ko/dict",
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
private constructor(public mecab: MeCab) {}
|
||||
|
||||
normalize(s: string) {
|
||||
return this.mecab
|
||||
.parse(s)
|
||||
.filter((t) => t.pos.some((p) => /^[NVM]/.test(p)))
|
||||
.map((t) => t.lemma)
|
||||
.join(" ");
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -0,0 +1,57 @@
|
||||
# Theme Lessons
|
||||
|
||||
Although our regular lessons present all the grammar and vocabulary you need to learn Korean, they do not offer specific sentences or information tailored to a specific theme. You might be able to find some sentences related to school, some sentences related to weather, and some sentences related to transportation scattered across our various lessons, these are by no means organized in one place. That is… until now.
|
||||
|
||||
The purpose of our Theme Lessons is to present you with sentences and vocabulary that you would come across in a specific situation. For example, if you were a student (or teacher) in a school, you might be interested in learning sentences and vocabulary that would be useful in this setting.
|
||||
|
||||
The purpose of these Theme Lessons is _not_ to teach the grammar within the sentences provided. However, in order to understand most of the grammar within the Theme Lessons, we suggest that you complete at least Lesson 25 of our regular lessons. On top of this (especially for learners still in Unit 1 of our regular lessons), there will definitely be some grammar that you are not familiar with. My original goal was to have the Unit 1 Theme Lessons present sentences that only used grammar introduced in Unit 1. I realized that the grammar introduced until Lesson 25 is not sufficient to make a ton of natural sentences.
|
||||
|
||||
Use this as an opportunity to maybe skip ahead to some grammatical principles that are more common but a little bit advanced. The most common grammatical principles that you might find in the Theme Lessons of Unit 1 that have not been introduced yet are:
|
||||
|
||||
| \~는 것 | [Lesson 26](../unit-2/26-describing-nouns-with-verbs.md) |
|
||||
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| 중 | [Lesson 33](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-26-33/lesson-33/ "Lesson 33: ~중 (하는 중), (~중에)") |
|
||||
| \~아/어서 | [Lesson 37](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-34-41/lesson-37/ "Lesson 37: Because: ~아/어서") |
|
||||
| 때문에 | [Lesson 38](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-34-41/lesson-38/ "Lesson 38: Because: ~기 때문에") |
|
||||
| \~아/어 주다 | [Lesson 41](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-34-41/lesson-41/ "Lesson 41: To Give: 주다, 아/어 주다") |
|
||||
| \~자 | [Lesson 44](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-42-50/lesson-44/) |
|
||||
| \~ㄹ/을래(요) | [Lesson 44](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-42-50/lesson-44/) |
|
||||
| \~ㄹ/을 수 있다 | [Lesson 45](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-42-50/lesson-45/ "Lesson 45: I can, I can’t – ~ㄹ 수 있다/없다") |
|
||||
| \~아/어 야 하다 | [Lesson 46](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-42-50/lesson-46/) |
|
||||
| \~ㄹ/을게(요) | [Lesson 63](https://www.howtostudykorean.com/unit-3-intermediate-korean-grammar/unit-3-lessons-59-66/lesson-63/ "Lesson 63: ~ㄹ/을까(요), ~ㄹ/을게요") |
|
||||
| \~ㄹ/을까(요) | [Lesson 63](https://www.howtostudykorean.com/unit-3-intermediate-korean-grammar/unit-3-lessons-59-66/lesson-63/ "Lesson 63: ~ㄹ/을까(요), ~ㄹ/을게요") |
|
||||
| \~는데 | [Lesson 76](https://www.howtostudykorean.com/upper-intermediate-korean-grammar/unit-4-lessons-76-83/lesson-76/ "Lesson 76: ~는데 and ~는 데 in Korean") |
|
||||
|
||||
The list above is by no means complete, but by knowing the grammar introduced in Unit 1, and having a general idea of some of these more difficult grammatical principles, you will definitely be able to challenge yourself with learning some great sentences.
|
||||
|
||||
In addition to the pile of sentences that will be provided, common words that relate to the particular theme will be given. All of the vocabulary words introduced in our Theme Lessons will also be introduced somewhere in our regular lessons. The purpose of these Theme Lessons is to organize all of the words (and sentences) that focus on a central subject.
|
||||
|
||||
- [Unit 1: #1 – School](./01-school.md)
|
||||
- [Unit 1: #2 – Transportation](./02-transportation.md)
|
||||
- [Unit 1: #3 – Eating](./03-eating.md)
|
||||
- [Unit 1: #4 – Shopping](./04-shopping.md)
|
||||
- [Unit 1: #5 – Weather](./05-weather.md)
|
||||
|
||||
In time, we will continue to update more Theme Lessons to this Unit.
|
||||
|
||||
In addition, we will eventually make Theme Lessons that fall under later Units. Theme Lessons under later Units will gradually be focused on more and more complex themes.
|
||||
|
||||
## Analyzing Korean Signs
|
||||
|
||||
<YouTube list=PLpkY2PdR9aLO_V0LFnP3_cdapJBcuG3-O />
|
||||
|
||||
## Sentence Practice
|
||||
|
||||
<YouTube list=PLpkY2PdR9aLOKW0N5CqSDNJF7rVaQCwpX />
|
||||
|
||||
## Dictation Practice
|
||||
|
||||
<YouTube list=PLpkY2PdR9aLMLiZnUBQFJxvr2Bs4eMbI6 />
|
||||
|
||||
## 20 SECOND LOOKS AT RAW KOREA
|
||||
|
||||
<YouTube list=PLpkY2PdR9aLOiwxKcoih94VHS4wGvOmQx />
|
||||
|
||||
---
|
||||
|
||||
How to study Korean © 2026. All Rights Reserved. | [Privacy Policy](http://www.howtostudykorean.com/privacy-policy/) | [Contact Us](http://www.howtostudykorean.com/other-stuff/contact-us/)
|
||||
@@ -1,7 +1,637 @@
|
||||
---
|
||||
vocabulary:
|
||||
nouns:
|
||||
- ko: 한국
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson1-1.mp3
|
||||
en: Korea
|
||||
notes: The formal name of the country is 대한민국
|
||||
examples:
|
||||
- ko: 저는 7년 동안 **한국**에서 살았어요
|
||||
en: I lived in **Korea** for seven years
|
||||
- ko: 저는 내년에 **한국**에 갈 거예요
|
||||
en: I will go to **Korea** next year
|
||||
- ko: 저의 어머니는 올해 **한국**에 올 것입니다
|
||||
en: My mom will come to **Korea** this year
|
||||
- ko: 저는 한국어를 **한국**에서 배웠어요
|
||||
en: I learned Korean in **Korea**
|
||||
- ko: 고등학교는 **한국**에서 어려워요
|
||||
en: High school is difficult in **Korea**
|
||||
- ko: 그 집은 **한국**에서 지어졌어요
|
||||
en: that house was built in **Korea**
|
||||
- ko: 저는 **한국**에서 살고 있어요
|
||||
en: I live in **Korea**
|
||||
|
||||
- ko: 도시
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-2.mp3
|
||||
en: city
|
||||
examples:
|
||||
- ko: 서울은 큰 **도시**예요
|
||||
en: Seoul is a big **city**
|
||||
- ko: "어느 **도시**에 갈 거예요?"
|
||||
en: What **city** are you going to go to?
|
||||
- ko: 이 **도시**는 분위기가 좋아요
|
||||
en: This **city** has a good atmosphere
|
||||
- ko: 서울 대신에 다른 **도시**에 갈 거예요?
|
||||
en: Other than Seoul, will you go to another **city**?
|
||||
- ko: 강가에는 **도시**에서 내려온 많은 쓰레기가 쌓여 있어요
|
||||
en: A great deal of garbage that had flowed down from the **city** was piled on the riverbank
|
||||
|
||||
- ko: 이름
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-3.mp3
|
||||
en: name
|
||||
examples:
|
||||
- ko: 그 사람의 **이름**은 뭐예요?
|
||||
en: What is that person's **name**?
|
||||
- ko: 저의 **이름**은 김한성이에요
|
||||
en: My **name** is 김한성
|
||||
- ko: 저는 그 사람의 **이름**이 기억 안 나요
|
||||
en: I can't remember that person's **name**
|
||||
- ko: 저는 그의 **이름**을 불렀어요
|
||||
en: I called his **name**
|
||||
- ko: 덕석은 흔하지 않은 **이름**이에요
|
||||
en: '"덕석" is not a common **name**'
|
||||
- ko: 이 길의 **이름**이 뭐죠?
|
||||
en: What is the **name** of this road/street?
|
||||
- ko: 친구 **이름**을 잊어버려서는 안 돼요
|
||||
en: You shouldn't forget your friend's **name**
|
||||
|
||||
- ko: 저
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-4.mp3
|
||||
en: I, me (formal)
|
||||
notes: |
|
||||
When used as the subject of a sentence, 저 translates to "I," when used as the object of a sentence, "저" translates to "me." For example: "저는 그 여자를 사랑해요" = "I love that girl", "그 여자는 저를 사랑해요" = "That girl loves me"
|
||||
|
||||
저 changes to 제 when 이/가 are attached. See Lesson 2 for more information. For example: "제가 한국을 좋아해요" = "I like Korea"
|
||||
|
||||
나 is used instead of 저 in informal situations.
|
||||
examples:
|
||||
- ko: "**저**는 친구를 만났어요"
|
||||
en: "**I** met a friend"
|
||||
- ko: "**저**의 친구는 **저**를 만났어요"
|
||||
en: "**My** friend met **me**"
|
||||
- ko: "**저**는 지난 주에 영화를 봤어요"
|
||||
en: "**I** saw a movie last week"
|
||||
- ko: "**저**는 삼일 동안 밥을 안 먹었어요"
|
||||
en: "**I** didn't eat rice for 3 days"
|
||||
|
||||
- ko: 나
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-5.mp3
|
||||
en: I, me (informal)
|
||||
notes: |
|
||||
When used as the subject of a sentence, 나 translates to "I," when used as the object of a sentence, "나" translates to "me." For example: "나는 그 여자를 사랑해" = "I love that girl", "그 여자는 나를 사랑해" = "That girl loves me"
|
||||
|
||||
나 changes to 내 when 이/가 are attached. See Lesson 2 for more information. For example: "내가 한국을 좋아해" = "I like Korea"
|
||||
|
||||
저 is used instead of 나 in formal situations.
|
||||
examples:
|
||||
- ko: "**나**는 친구를 만났어"
|
||||
en: "**I** met a friend"
|
||||
- ko: "**나**의 친구는 **나**를 만났어"
|
||||
en: "**My** friend met **me**"
|
||||
- ko: "**나**는 내년에 한국에 갈 거야"
|
||||
en: "**I** will go to Korea next year"
|
||||
- ko: "**나**는 사과 한 개를 샀어"
|
||||
en: "**I** bought one apple"
|
||||
|
||||
- ko: 남자
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-6.mp3
|
||||
en: man
|
||||
examples:
|
||||
- ko: 그는 잘생긴 **남자**예요
|
||||
en: He is a handsome **man**
|
||||
- ko: "**남자**는 방에 들어왔어요"
|
||||
en: That **man** came into room
|
||||
- ko: 저는 잘생긴 **남자**를 만났어요
|
||||
en: I met a handsome **man**
|
||||
- ko: 저의 친구는 주로 **남자**예요
|
||||
en: My friends are mostly **men**
|
||||
- ko: 그 **남자**가 키가 너무 커요
|
||||
en: That **man** is very tall
|
||||
- ko: 어떤 **남자**는 어제 여기에 왔어
|
||||
en: Some **man** came here yesterday
|
||||
|
||||
- ko: 여자
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-7.mp3
|
||||
en: woman
|
||||
examples:
|
||||
- ko: 그녀는 예쁜 **여자**예요
|
||||
en: She is a beautiful **girl**
|
||||
- ko: 그 **여자**의 머리 색깔은 자연스러워요
|
||||
en: That **girl**'s hair color is natural
|
||||
- ko: 저의 **여자** 친구는 귀엽고 예뻐요
|
||||
en: My **girl**friend is cute and pretty
|
||||
- ko: 저는 그 **여자**를 사랑해요
|
||||
en: I love that **girl**
|
||||
|
||||
- ko: 이
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-9.mp3
|
||||
en: this
|
||||
notes: |
|
||||
이 is a type of word called a "관형사," which isn't an adjective, but is another type of word that can be placed before nouns to describe them. In English, "관형사" translates to a "modifier" or "a determiner." 이 is placed before nouns within reaching distance to indicate that one is talking about "this" specific thing. For example: "이 사람" = "this person"
|
||||
|
||||
It is easy to distinguish between a determiner and an adjective in Korean. Although both placed before nouns to "describe" them, the dictionary (ordinary) form of an adjective always ends in ~다 and must change in order to describe them. For example, 예쁘다 changes to 예쁜 when placed before a noun to describe it (See Lesson 3 for more information). Determiners keep their original form when placed before a noun. This might be too much grammar for you at this point, but make a note of it.
|
||||
examples:
|
||||
- ko: "**이** 차는 너무 비싸요"
|
||||
en: "**This** car is too expensive"
|
||||
- ko: "**이** 방은 넓습니다"
|
||||
en: "**This** room is big/wide"
|
||||
- ko: 저는 **이** 영화를 더 이상 보고 싶지 않아요
|
||||
en: I don't want to watch **this** movie anymore
|
||||
- ko: "**이** 고기는 돼지고기입니다"
|
||||
en: "**This** meat is pork"
|
||||
- ko: "**이** 사람은 저의 누나예요"
|
||||
en: "**This** (person) is my sister"
|
||||
|
||||
- ko: 그
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-8.mp3
|
||||
en: that
|
||||
notes: |
|
||||
그 is another example of a "관형사" in Korean. 그 is placed before nouns that are being referred to from context or a previous sentence. For example, if your father is talking about a specific person, you can refer to "that person" by saying "그 사람."
|
||||
|
||||
See more information about 관형사 in my description of "이" above.
|
||||
examples:
|
||||
- ko: "**그** 남자는 저의 아버지예요"
|
||||
en: "**That** man is my father"
|
||||
- ko: "**그** 여자는 나랑 결혼하고 싶었어요"
|
||||
en: "**That** girl wanted to marry me"
|
||||
- ko: 저는 **그** 책을 원해요
|
||||
en: I want **that** book
|
||||
- ko: "**그** 병원은 멉니다"
|
||||
en: "**That** hospital is far"
|
||||
- ko: "**그** 여자의 머리카락은 깁니다"
|
||||
en: "**That** girls hair is long"
|
||||
|
||||
- ko: 저
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-10.mp3
|
||||
en: that (when something is far away)
|
||||
notes: |
|
||||
저 is another example of a "관형사" in Korean. 저 is placed before nouns that are far away (not within reach). For example, if you want to refer to the person across the street, you can refer to "that person" by saying "저 사람."
|
||||
|
||||
그 and 저 both translate to "that." This often causes confusion for English speakers.
|
||||
|
||||
Also notice that "저" has more than one meaning. Earlier, you saw that "저" means "I/me." Welcome to the world of Korean! Where often times one word has more than one meaning.
|
||||
|
||||
See more information about 관형사 in my description of "이" above.
|
||||
examples:
|
||||
- ko: "**저** 사람은 누구예요?"
|
||||
en: Who is **that** person?
|
||||
- ko: 저는 **저** 케이크를 먹고 싶어요
|
||||
en: I want to eat **that** cake
|
||||
- ko: "**저** 바지가 얼마예요?"
|
||||
en: How much are **those** pants?
|
||||
- ko: 저의 친구는 **저** 쪽으로 갔어요
|
||||
en: My friend went **that** way
|
||||
- ko: "**저** 학교는 역사적인 건물이에요"
|
||||
en: "**That** school is a historical building"
|
||||
- ko: 다음 버스는 **저** 정류장에서 출발할 거예요
|
||||
en: The next bus will depart from **that** station
|
||||
|
||||
- ko: 것
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-11.mp3
|
||||
en: thing
|
||||
notes: |
|
||||
Not only used as a simple noun, but also used as a noun that can be described by full sentences. See Lesson 26 for more information about this.
|
||||
|
||||
것 can be shortened to 거. 것이 can be shortened to 게
|
||||
examples:
|
||||
- ko: 저는 비싼 **것**만 좋아해요
|
||||
en: I only like expensive **things**
|
||||
- ko: "그**것**을 어떻게 해요?"
|
||||
en: How do you do that (**thing**)?
|
||||
- ko: "이**것**은 뭐야?"
|
||||
en: What is this (**thing**)?
|
||||
- ko: "이**것**은 얼마예요?"
|
||||
en: How much is this (**thing**)?
|
||||
|
||||
- ko: 이것
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson-1-v.mp3
|
||||
en: this (thing)
|
||||
notes: |
|
||||
The pronunciation of this word is closer to "이걷"
|
||||
|
||||
이것 is often shortened to 이거 in speech.
|
||||
|
||||
When 이, 그 or 저 are placed before "것," the result is a compound word. Therefore, when placing "것" after 이, 그 or 저, there should not be a space between the two.
|
||||
|
||||
Although it can be translated as "this thing," 이것 itself is a pronoun and can be simplified to translate to "this." For more information, see the explanation in Lesson 1.
|
||||
examples:
|
||||
- ko: "**이것**은 뭐야?"
|
||||
en: What is **this (thing)**?
|
||||
- ko: "**이것**은 너무 작은가요?"
|
||||
en: Is **this (thing)** too small?
|
||||
- ko: "**이것**은 여권이야"
|
||||
en: "**This (thing)** is a passport"
|
||||
- ko: "**이것**이 더 좋아요"
|
||||
en: "**This (thing)** is better"
|
||||
- ko: "**이것**을 보셔요"
|
||||
en: Look at **this (thing)**
|
||||
- ko: "**이것**을 먹어 봐!"
|
||||
en: Eat **this (thing)**! (Try eating **this (thing)**!)
|
||||
- ko: 모든 프린터 중에 **이것**이 제일 싸요
|
||||
en: Among all the printers, **this (one)** is the cheapest
|
||||
- ko: "**이것**을 다 작성해 주실래요?"
|
||||
en: Can you write all of **this** up for me?
|
||||
- ko: "**이것**은 처음이자 마지막 기회예요"
|
||||
en: "**This** is the first and last chance"
|
||||
|
||||
- ko: 그것
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson-1-v2.mp3
|
||||
en: that (thing)
|
||||
notes: |
|
||||
The pronunciation of this word is closer to "그걷"
|
||||
|
||||
그것 is often shortened to 그거 in speech.
|
||||
|
||||
When 이, 그 or 저 are placed before "것," the result is a compound word. Therefore, when placing "것" after 이, 그 or 저, there should not be a space between the two.
|
||||
|
||||
Although it can be translated as "that thing," 그것 itself is a pronoun and can be simplified to translate to "that." For more information, see the explanation in Lesson 1.
|
||||
examples:
|
||||
- ko: 저는 **그것**을 손으로 만들었어요
|
||||
en: I built **that (thing)** with my hands
|
||||
- ko: 저는 **그것**을 지난 번에 배웠어요
|
||||
en: I learned **that (thing)** last time
|
||||
- ko: 저는 **그것**을 처음부터 끝까지 복습했어요
|
||||
en: I reviewed **that (thing)** from start to finish
|
||||
- ko: 저는 **그것**을 영어로 할 거예요
|
||||
en: I will say **that (thing)** in English
|
||||
- ko: 저는 **그것**을 친구한테서 들었어요
|
||||
en: I heard **that (thing)** from my friend
|
||||
|
||||
- ko: 저것
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/11/Lesson-1-v3.mp3
|
||||
en: that (thing)
|
||||
notes: |
|
||||
The pronunciation of this word is closer to "저걷"
|
||||
|
||||
저것 is often shortened to 저거 in speech.
|
||||
|
||||
When 이, 그 or 저 are placed before "것," the result is a compound word. Therefore, when placing "것" after 이, 그 or 저, there should not be a space between the two.
|
||||
|
||||
Although it can be translated as "that thing," 저것 itself is a pronoun and can be simplified to translate to "that." For more information, see the explanation in Lesson 1.
|
||||
examples:
|
||||
- ko: "**저것**은 사과예요"
|
||||
en: "**That (thing)** is an apple"
|
||||
- ko: 우리 아빠는 **저것**을 싫어할 것 같아
|
||||
en: Dad will probably not like **that (thing)**
|
||||
- ko: "**저것**은 사람이 아니라 눈사람이에요"
|
||||
en: "**That (thing)** is not a person, it is a snowman"
|
||||
|
||||
- ko: 의자
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-12.mp3
|
||||
en: chair
|
||||
notes: |
|
||||
This word appears in Korean Sign Explanation [Video 14]
|
||||
|
||||
<YouTube id="b8X6ryrJGeY" />
|
||||
examples:
|
||||
- ko: 그녀는 **의자**에서 일어났어요
|
||||
en: She rose up from her **chair**
|
||||
- ko: 고양이는 **의자** 밑에 있다
|
||||
en: The cat is under the **chair**
|
||||
- ko: "**의자**는 탁자보다 더 낮아요"
|
||||
en: The **chair** is lower than the table
|
||||
- ko: 저는 **의자**를 앞으로 움직였어요
|
||||
en: I moved my **chair** forward
|
||||
|
||||
- ko: 탁자
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-13.mp3
|
||||
en: table
|
||||
notes: |
|
||||
The pronunciation of this word is closer to "탁짜"
|
||||
|
||||
The little table that Korean people use when they sit on the floor to have meals is called a "상." A kitchen table can be referred to more specifically by saying "식탁."
|
||||
examples:
|
||||
- ko: 저는 잡지를 **탁자** 위에 놓을 거예요
|
||||
en: I will put the magazine on the **table**
|
||||
- ko: 펜이 **탁자**에 놓여 있었어요
|
||||
en: The pen was (laying) on the **table**
|
||||
- ko: 의자는 **탁자**보다 더 낮아요
|
||||
en: The chair is lower than the **table**
|
||||
- ko: 밖에 나가기 전에 열쇠를 **탁자**에 두었어요
|
||||
en: Before I went outside, I put the keys on the **table**
|
||||
- ko: 이 **탁자**가 너무 낮아요
|
||||
en: This **table** is too low
|
||||
- ko: 병이 **탁자**에서 떨어졌다
|
||||
en: The bottle fell from the **table**
|
||||
|
||||
- ko: 선생님
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-14.mp3
|
||||
en: teacher
|
||||
notes: |
|
||||
This is often colloquially shortened to "쌤"
|
||||
|
||||
선생님 (or 쌤) is often used to broadly refer to anybody in any form of a teaching position, or anybody who works at any position in a school. For example, the maintenance people who work at a school would be referred to as "선생님" within the school.
|
||||
examples:
|
||||
- ko: 저는 **선생님**이 되고 싶어요
|
||||
en: I want to be a **teacher**
|
||||
- ko: 저는 학교에서 저의 **선생님**을 항상 봐요
|
||||
en: I always see my **teacher** at school
|
||||
- ko: 저는 **선생님**이에요
|
||||
en: I am a **teacher**
|
||||
- ko: 저는 어제 **선생님**을 처음 만났어요
|
||||
en: I met my **teacher** for the first time yesterday
|
||||
- ko: "**선생님**들은 다 나갔어요"
|
||||
en: All the **teachers** left (went out)
|
||||
- ko: "**선생님**은 학생들과 박물관에 갔다"
|
||||
en: The **teacher** went to the museum with the students
|
||||
- ko: 저는 **선생님**과 함께 공부했어요
|
||||
en: I studied with my **teacher**
|
||||
- ko: "**선생님**들은 똑똑해요"
|
||||
en: "**Teachers** are smart"
|
||||
|
||||
- ko: 침대
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-15.mp3
|
||||
en: bed
|
||||
examples:
|
||||
- ko: 애기는 **침대**에서 자고 있어요
|
||||
en: The baby is sleeping in the **bed**
|
||||
- ko: 저는 **침대**에 누워 있어요
|
||||
en: I'm lying in **bed**
|
||||
- ko: 저의 사진은 **침대** 위에 걸려 있어요
|
||||
en: My picture is hanging above my **bed**
|
||||
- ko: 피곤한 사람은 **침대**에 누워서 잤어요
|
||||
en: The tired person lay on the **bed** and slept
|
||||
- ko: 저는 **침대**에 잠깐 눕고 싶어요
|
||||
en: I want to lie down in **bed** for just a second
|
||||
|
||||
- ko: 집
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-16.mp3
|
||||
en: house
|
||||
examples:
|
||||
- ko: 저는 **집**에 돌아갈 거예요
|
||||
en: I am going back (returning) **home**
|
||||
- ko: "**집** 값은 비싸지고 있어"
|
||||
en: "**House** prices are getting expensive"
|
||||
- ko: 저는 내일 선생님의 **집**을 방문하겠어요
|
||||
en: I will visit the teacher's **house** tomorrow
|
||||
- ko: 저는 어제 **집**을 두 번 청소했어요
|
||||
en: I cleaned the **house** twice yesterday
|
||||
- ko: 엄마는 우리를 위해 점심을 **집**에서 만들 거예요
|
||||
en: Mom will make lunch for us at **home**
|
||||
- ko: 우리 엄마는 **집**에 와서 빨리 요리했습니다
|
||||
en: Our/my mom came **home** and quickly cooked
|
||||
- ko: 우리는 **집**에 와서 바로 잤어요
|
||||
en: We came **home** and went to sleep immediately
|
||||
- ko: "**집**에 가지 마!"
|
||||
en: Don't go **home**!
|
||||
- ko: 저는 세탁을 **집**에서 할 수 있어요
|
||||
en: I can do laundry at **home**
|
||||
|
||||
- ko: 차
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-17.mp3
|
||||
en: car
|
||||
notes: The counter for automobiles is "대". See Lesson 10 for more information
|
||||
examples:
|
||||
- ko: 우리 아버지는 **차**를 항상 안전하게 운전해요
|
||||
en: Our dad always drives his **car** safely
|
||||
- ko: 저는 **차** 두 대가 있어요
|
||||
en: I have two **cars**
|
||||
- ko: "어떤 종류의 **차**를 원해요?"
|
||||
en: What type of **car** do you want
|
||||
- ko: "이 **차**는 너무 비싸요"
|
||||
en: "This **car** is too expensive"
|
||||
- ko: 저는 새로운 **차**를 샀어요
|
||||
en: I bought a new **car**
|
||||
|
||||
- ko: 사람
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-18.mp3
|
||||
en: person
|
||||
notes: |
|
||||
The formal version of 사람 is "분"
|
||||
|
||||
The counter for people is "명" (informal) or "분" (formal). See Lesson 10 for more information
|
||||
examples:
|
||||
- ko: 그 **사람**은 아주 똑똑해요
|
||||
en: That **person** is very smart
|
||||
- ko: 모든 아시아 **사람**들은 젓가락을 잘 쓴다
|
||||
en: All Asian **people** use chopsticks well
|
||||
- ko: 그 **사람**은 미국에서 왔어요
|
||||
en: That **person** came from the United States
|
||||
- ko: 저는 그 **사람**을 알아요
|
||||
en: I know that **person**
|
||||
- ko: 저 **사람**은 저의 동생이에요
|
||||
en: That **person** is my younger sibling
|
||||
- ko: 저는 그 **사람**을 싫어해요
|
||||
en: I don't like that **person**
|
||||
- ko: 한국 **사람**들은 보통 아주 착해요
|
||||
en: Korean **people** are usually very nice
|
||||
|
||||
- ko: 책
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-19.mp3
|
||||
en: book
|
||||
notes: The word used to count books is "권"
|
||||
examples:
|
||||
- ko: 저는 좋은 **책**을 읽고 싶어요
|
||||
en: I want to read a good **book**
|
||||
- ko: 저는 그것에 대해 **책**을 쓸 거예요
|
||||
en: I will write a **book** about it
|
||||
- ko: 저는 친구에게 **책**을 돌려줬어요
|
||||
en: I gave my friend back his **book**
|
||||
- ko: 저는 **책** 두 권을 읽었어요
|
||||
en: I read two **books**
|
||||
- ko: 저는 그 **책**을 읽고 싶어요
|
||||
en: I want to read that **book**
|
||||
- ko: 그 학생은 하루 종일 **책**을 읽을 수 있어요
|
||||
en: That student can read **books** all day
|
||||
- ko: 이 박스에 **책**이 들어가 있어요
|
||||
en: There are **books** in this box
|
||||
- ko: 저는 누워서 **책**을 읽었어요
|
||||
en: I lied down and read a **book**
|
||||
|
||||
- ko: 컴퓨터
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-20.mp3
|
||||
en: computer
|
||||
notes: Many new Korean words are simply English words with a Korean pronunciation pronouncing "컴퓨터" in Korean will sound like "computer"
|
||||
examples:
|
||||
- ko: "**컴퓨터**가 꺼져 있어요"
|
||||
en: The **computer** is turned off
|
||||
- ko: 저는 **컴퓨터**를 켰어요
|
||||
en: I turned the **computer** on
|
||||
- ko: "**컴퓨터**가 켜져 있어요"
|
||||
en: The **computer** is (in the state of being) on
|
||||
- ko: 그는 고장 난 **컴퓨터**를 수리했어요
|
||||
en: He repaired the broken **computer**
|
||||
- ko: 교실에서 선생님들을 **컴퓨터**로 대체할 수 없어요
|
||||
en: You can't replace teachers with **computers** in the classroom
|
||||
|
||||
- ko: 나무
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-21.mp3
|
||||
en: tree/wood
|
||||
examples:
|
||||
- ko: 저는 집을 **나무**로 지었어요
|
||||
en: I made a house out of **wood**
|
||||
- ko: 나는 우리 집을 **나무**로 지었어
|
||||
en: I built our house out of **wood**
|
||||
- ko: 대부분의 원숭이는 **나무**에서 살아요
|
||||
en: Most monkeys live in **trees**
|
||||
- ko: 아이들은 **나무** 주위에서 놀고 있어요
|
||||
en: The children are playing around the **tree**
|
||||
|
||||
- ko: 소파
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-22.mp3
|
||||
en: sofa
|
||||
notes: |
|
||||
Many new Korean words are simply English words with a Korean pronunciation pronouncing "소파" in Korean will sound like "sofa." Note that there is no way to pronounce the "F" sound in Korean. English words with an "F" that are borrowed to Korean usually use "ㅍ" to make the "F" sound.
|
||||
examples:
|
||||
- ko: 그는 **소파**에 앉아 있어요
|
||||
en: He is sitting on the **couch**
|
||||
- ko: 이 **소파**는 아주 편해요
|
||||
en: This **sofa** is very comfortable
|
||||
- ko: 애기는 높은 **소파**에서 떨어졌어요
|
||||
en: The baby fell from the high **sofa**
|
||||
|
||||
- ko: 중국
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-23.mp3
|
||||
en: China
|
||||
examples:
|
||||
- ko: 우리는 곧 **중국**에 갈 거예요
|
||||
en: We are going to **China** soon
|
||||
- ko: 그 사람은 **중국**에서 왔어요
|
||||
en: That person came from **China**
|
||||
- ko: 그 사람은 **중국**인이에요
|
||||
en: That person is **Chinese**
|
||||
- ko: "**중국** 사람들은 한국사람들보다 더 가난해요"
|
||||
en: "**Chinese** people are poorer than Korean people"
|
||||
- ko: 한국 사람과 **중국** 사람은 문화적으로 달라요
|
||||
en: Korean and **Chinese** people are culturally different
|
||||
- ko: 한국에는 황사가 **중국**에서 봄마다 와요
|
||||
en: Yellow dust comes to Korea every spring from **China**
|
||||
- ko: "**중국** 사람들은 소금을 쓰는 것 대신에 음식에 간장을 뿌려요"
|
||||
en: Instead of using salt, **Chinese** people put soy sauce on their food
|
||||
|
||||
- ko: 일본
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-24.mp3
|
||||
en: Japan
|
||||
examples:
|
||||
- ko: 그 사람은 **일본**에서 왔어요
|
||||
en: That person is from **Japan**
|
||||
- ko: "**일본**은 전쟁에서 한국을 공격했어요"
|
||||
en: "**Japan** attacked Korea in the war"
|
||||
- ko: 저는 **일본**에 스무 번 넘게 가 봤어요
|
||||
en: I've been to **Japan** more than twenty times
|
||||
- ko: 요즘에 한국 사람들은 **일본**에 별로 가고 싶지 않아요
|
||||
en: These days, Korean people don't really want to go to **Japan**
|
||||
- ko: 한국 집값은 **일본** 집값보다 훨씬 높아요
|
||||
en: The price of Korean houses is much higher than the price of houses in **Japan**
|
||||
- ko: "**일본**에서 성인들은 미국 청소년보다 만화책을 더 많이 읽어요"
|
||||
en: "In **Japan**, adults read more comic books than young people in America"
|
||||
|
||||
- ko: 문
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-25.mp3
|
||||
en: door
|
||||
notes: |
|
||||
On the subway, you will hear "내리실 문은 왼쪽/오른쪽이에요" – "The doors are on your left/right."
|
||||
|
||||
On the bus, you will see signs saying "문이 완전히 열릴 때까지 버스에서 내리거나 문에 기대지 마세요" – "Until the door is fully/completely open, don't get off the bus or lean on the door"
|
||||
examples:
|
||||
- ko: "**문**을 닫아야 돼요"
|
||||
en: You have to close the **door**
|
||||
- ko: 저는 **문**을 잠갔어요
|
||||
en: I locked the **door**
|
||||
- ko: 저는 **문**을 열 거예요
|
||||
en: I will open the **door**
|
||||
- ko: 너무 추워서 **문**을 닫았어요
|
||||
en: I closed the **door** because it is too cold
|
||||
- ko: "**문**이 완전히 열릴 때까지 버스에서 내리거나 문에 기대지 마세요"
|
||||
en: Until the **door** is fully/completely open, don't get off the bus or lean on the **door**
|
||||
|
||||
- ko: 의사
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-26.mp3
|
||||
en: doctor
|
||||
notes: Korean people don't refer to people with a Ph.D. as "doctor." Instead, they use the term "박사(님)."
|
||||
examples:
|
||||
- ko: 저는 **의사**가 무서워요
|
||||
en: I am afraid of **doctors**
|
||||
- ko: "**의사**들은 돈이 많아요"
|
||||
en: "**doctors** have a lot of money"
|
||||
- ko: 저의 친구는 **의사**예요
|
||||
en: My friend is a **doctor**
|
||||
- ko: "**의사**들은 문제에 대해 과학적으로 생각했어요"
|
||||
en: The **doctors** thought about the problem scientifically
|
||||
- ko: 저는 정신과**의사**가 되려고 열심히 공부하고 있어요
|
||||
en: I am studying hard to become a **psychiatrist**
|
||||
|
||||
- ko: 학생
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/vLesson-7-3.mp3
|
||||
en: student
|
||||
examples:
|
||||
- ko: 저는 좋은 **학생**이에요
|
||||
en: I am a good **student**
|
||||
- ko: 저는 **학생**이 아니에요
|
||||
en: I am not a **student**
|
||||
- ko: 선생님은 내일 **학생**들을 만날 거야
|
||||
en: The teacher will meet the **students** tomorrow
|
||||
- ko: 저는 **학생**들이 실망스러웠어요
|
||||
en: I was disappointed in the **students**
|
||||
- ko: 저는 **학생**들에게 수업을 가르쳤어요
|
||||
en: I taught the class to the **students**
|
||||
- ko: "**선생님**은 **학생**들과 박물관에 갔다"
|
||||
en: The teacher went to the museum with the **students**
|
||||
|
||||
other:
|
||||
- ko: 이다
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-27.mp3
|
||||
en: to be
|
||||
notes: |
|
||||
This is the first time you are being introduced to a word that must be conjugated in order to be used. Visit Lesson 5 for more information. Any word that ends in "다" must be conjugated to be used. The conjugation of 이다 is different than other words. I introduce all of these conjugations in Lesson 9.
|
||||
|
||||
"to be" can be many words in English. For example, I am, he is, they are, I was, they were. 이다 acts as all of these words.
|
||||
examples:
|
||||
- ko: 저는 예쁜 여자**예요**
|
||||
en: I **am** a beautiful girl
|
||||
- ko: 저 건물은 학교**입니다**
|
||||
en: That building **is** a school
|
||||
- ko: 그것은 사진**이에요**
|
||||
en: That thing **is** a picture
|
||||
- ko: 이 사람은 저의 누나**예요**
|
||||
en: This (person) **is** my sister
|
||||
- ko: 그것은 큰 비밀**이었어요**
|
||||
en: That **was** a big secret
|
||||
- ko: 저는 의사**였어요**
|
||||
en: I **was** a doctor
|
||||
|
||||
- ko: 네
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-29.mp3
|
||||
en: "yes"
|
||||
notes: |
|
||||
Informally, you can say "응" to mean "yes"
|
||||
|
||||
When speaking on the phone, Korean people often say this many times and pronounce it as "데"
|
||||
examples:
|
||||
- ko: "**네**, 저는 가고 싶어요"
|
||||
en: "**Yes**, I want to go"
|
||||
- ko: "**네**, 알겠습니다"
|
||||
en: "**Yes**, okay. (I got it)"
|
||||
- ko: "**네**, 그렇습니다"
|
||||
en: "**Yes**, that is correct (that is the way it is)"
|
||||
- ko: "**네**, 그럴게요"
|
||||
en: "**Yes/Okay**, I will do that if that's what you want"
|
||||
- ko: "**네**, 갔다 올게요"
|
||||
en: "**Yes/Okay**, I will go, and then come back"
|
||||
|
||||
- ko: 아니
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-1-30.mp3
|
||||
en: "no"
|
||||
notes: |
|
||||
In formal situations, "아니요" is more respectful
|
||||
* **아니요**, 안 했어요 = **No**, I didn’t do it
|
||||
|
||||
Person 1: 숙소비가 얼마예요? 10만원? = How much is the lodging fee? 100,000 won?
|
||||
|
||||
Person 2: **아니요**. 10만원 조금 넘어요 = **No**. A little more than 100,000 won
|
||||
examples:
|
||||
- ko: "**아니요**, 안 했어요"
|
||||
en: "**No**, I didn't do it"
|
||||
- ko: "**아니요**. 10만원 조금 넘어요"
|
||||
en: "**No**. A little more than 100,000 won"
|
||||
---
|
||||
|
||||
# Lesson 1: Basic Korean Sentences
|
||||
|
||||
## Vocabulary
|
||||
|
||||
<VocabQuiz />
|
||||
|
||||
### Nouns
|
||||
|
||||
한국 <AudioButton src="https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson1-1.mp3" /> = <span class="md spoiler">Korea</span>
|
||||
@@ -29,9 +659,9 @@ Examples
|
||||
- 저는 7년 동안 **한국**에서 살았어요 = <span class="md spoiler">I lived in **Korea** for seven years</span>
|
||||
- 저는 내년에 **한국**에 갈 거예요 = <span class="md spoiler">I will go to **Korea** next year</span>
|
||||
- 저의 어머니는 올해 **한국**에 올 것입니다 = <span class="md spoiler">My mom will come to **Korea** this year</span>
|
||||
- 저는 한국어를 **한국**에서 배웠어요 = <span class="md spoiler">I learned Korean in <strong>Korea</strong></span>
|
||||
- 고등학교는 **한국**에서 어려워요 = <span class="md spoiler">High school is difficult in <strong>Korea</strong></span>
|
||||
- 그 집은 **한국**에서 지어졌어요 = <span class="md spoiler">that house was built in <strong>Korea</strong></span>
|
||||
- 저는 한국어를 **한국**에서 배웠어요 = <span class="md spoiler">I learned Korean in **Korea**</span>
|
||||
- 고등학교는 **한국**에서 어려워요 = <span class="md spoiler">High school is difficult in **Korea**</span>
|
||||
- 그 집은 **한국**에서 지어졌어요 = <span class="md spoiler">that house was built in **Korea**</span>
|
||||
- 저는 **한국**에서 살고 있어요 = <span class="md spoiler">I live in **Korea**</span>
|
||||
|
||||
</Details>
|
||||
@@ -49,7 +679,7 @@ Common Usages:
|
||||
|
||||
Example:
|
||||
|
||||
- 서울은 큰 **도시**예요 = <span class="md spoiler">Seoul is a big <strong>city</strong></span>
|
||||
- 서울은 큰 **도시**예요 = <span class="md spoiler">Seoul is a big **city**</span>
|
||||
- 어느 **도시**에 갈 거예요? = <span class="md spoiler">What **city** are you going to go to?</span>
|
||||
- 이 **도시**는 분위기가 좋아요 = <span class="md spoiler">This **city** has a good atmosphere</span>
|
||||
- 서울 대신에 다른 **도시**에 갈 거예요? = <span class="md spoiler">Other than Seoul, will you go to another **city**?</span>
|
||||
@@ -164,7 +794,7 @@ Examples
|
||||
- 그는 잘생긴 **남자**예요 = <span class="md spoiler">He is a handsome **man**</span>
|
||||
- **남자**는 방에 들어왔어요 = <span class="md spoiler">That **man** came into room</span>
|
||||
- 저는 잘생긴 **남자**를 만났어요 = <span class="md spoiler">I met a handsome **man**</span>
|
||||
- 저의 친구는 주로 남자예요 = <span class="md spoiler">My friends are mostly <strong>men</strong></span>
|
||||
- 저의 친구는 주로 남자예요 = <span class="md spoiler">My friends are mostly **men**</span>
|
||||
- 그 남자가 키가 너무 커요 = <span class="md spoiler">That **man** is very tall</span>
|
||||
- 어떤 남자는 어제 여기에 왔어 = <span class="md spoiler">Some **man** came here yesterday</span>
|
||||
|
||||
@@ -183,7 +813,7 @@ Common Usages
|
||||
|
||||
Examples
|
||||
|
||||
- 그녀는 예쁜 **여자**예요 = <span class="md spoiler">She is a beautiful <strong>girl</strong></span>
|
||||
- 그녀는 예쁜 **여자**예요 = <span class="md spoiler">She is a beautiful **girl**</span>
|
||||
- 그 **여자**의 머리 색깔은 자연스러워요 = <span class="md spoiler">That **girl**’s hair color is natural</span>
|
||||
- 저의 **여자** 친구는 귀엽고 예뻐요 = <span class="md spoiler">My **girl**friend is cute and pretty</span>
|
||||
- 저는 그 **여자**를 사랑해요 = <span class="md spoiler">I love that **girl**</span>
|
||||
@@ -282,7 +912,7 @@ Common Usages
|
||||
- <TTS>이것</TTS> = <span class="md spoiler">this thing</span>
|
||||
- <TTS>저것</TTS> = <span class="md spoiler">that thing</span>
|
||||
- <TTS>그것</TTS> = <span class="md spoiler">that thing</span>
|
||||
- ~는 것 principle (see [Lesson 26](https://www.howtostudykorean.com/unit-2-lower-intermediate-korean-grammar/unit-2-lessons-26-33/lesson-26/))
|
||||
- ~는 것 principle (see [Lesson 26](../unit-2/26-describing-nouns-with-verbs.md))
|
||||
|
||||
Notes:
|
||||
|
||||
@@ -292,7 +922,7 @@ Not only used as a simple noun, but also used as a noun that can be described by
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 비싼 **것**만 좋아해요 = <span class="md spoiler">I only like expensive <strong>things</strong></span>
|
||||
- 저는 비싼 **것**만 좋아해요 = <span class="md spoiler">I only like expensive **things**</span>
|
||||
- 그**것**을 어떻게 해요? = <span class="md spoiler">How do you do that (**thing**)?</span>
|
||||
- 이**것**은 뭐야? = <span class="md spoiler">What is this (**thing**)?</span>
|
||||
- 이**것**은 얼마예요? = <span class="md spoiler">How much is this (**thing**)?</span>
|
||||
@@ -320,11 +950,11 @@ Common Usages:
|
||||
Examples:
|
||||
|
||||
- **이것**은 뭐야? = <span class="md spoiler">What is **this (thing)**?</span>
|
||||
- **이것**은 너무 작은가요? = <span class="md spoiler">Is **this** (**thing**) too small?</span>
|
||||
- **이것**은 너무 작은가요? = <span class="md spoiler">Is **this (thing)** too small?</span>
|
||||
- **이것**은 여권이야 = <span class="md spoiler">**This (thing)** is a passport</span>
|
||||
- **이것**이 더 좋아요 = <span class="md spoiler">**This** (**thing**) is better</span>
|
||||
- **이것**을 보셔요 = <span class="md spoiler">Look at <strong>this (thing)</strong></span>
|
||||
- 이것을 먹어 봐! = <span class="md spoiler">Eat **this (thing)**! (Try eating **this (thing)**!)</span>
|
||||
- **이것**이 더 좋아요 = <span class="md spoiler">**This (thing)** is better</span>
|
||||
- **이것**을 보셔요 = <span class="md spoiler">Look at **this (thing)**</span>
|
||||
- **이것**을 먹어 봐! = <span class="md spoiler">Eat **this (thing)**! (Try eating **this (thing)**!)</span>
|
||||
- 모든 프린터 중에 **이것**이 제일 싸요 = <span class="md spoiler">Among all the printers, **this (one)** is the cheapest</span>
|
||||
- **이것**을 다 작성해 주실래요? = <span class="md spoiler">Can you write all of **this** up for me?</span>
|
||||
- **이것**은 처음이자 마지막 기회예요 = <span class="md spoiler">**This** is the first and last chance</span>
|
||||
@@ -395,7 +1025,7 @@ Common Usages
|
||||
|
||||
Example
|
||||
|
||||
- 그녀는 **의자**에서 일어났어요 = <span class="md spoiler">She rose up from her <strong>chair</strong></span>
|
||||
- 그녀는 **의자**에서 일어났어요 = <span class="md spoiler">She rose up from her **chair**</span>
|
||||
- 고양이는 **의자** 밑에 있다 = <span class="md spoiler">The cat is under the **chair**</span>
|
||||
- **의자**는 탁자보다 더 낮아요 = <span class="md spoiler">The **chair** is lower than the table</span>
|
||||
- 저는 **의자**를 앞으로 움직였어요 = <span class="md spoiler">I moved my **chair** forward</span>
|
||||
@@ -419,10 +1049,10 @@ Common Usages
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 잡지를 **탁자** 위에 놓을 거예요 = <span class="md spoiler">I will put the magazine on the <strong>table</strong></span>
|
||||
- 펜이 **탁자**에 놓여 있었어요 = <span class="md spoiler">The pen was (laying) on the <strong>table</strong></span>
|
||||
- 의자는 **탁자**보다 더 낮아요 = <span class="md spoiler">The chair is lower than the <strong>table</strong></span>
|
||||
- 밖에 나가기 전에 열쇠를 **탁자**에 두었어요 = <span class="md spoiler">Before I went outside, I put the keys on the <strong>table</strong></span>
|
||||
- 저는 잡지를 **탁자** 위에 놓을 거예요 = <span class="md spoiler">I will put the magazine on the **table**</span>
|
||||
- 펜이 **탁자**에 놓여 있었어요 = <span class="md spoiler">The pen was (laying) on the **table**</span>
|
||||
- 의자는 **탁자**보다 더 낮아요 = <span class="md spoiler">The chair is lower than the **table**</span>
|
||||
- 밖에 나가기 전에 열쇠를 **탁자**에 두었어요 = <span class="md spoiler">Before I went outside, I put the keys on the **table**</span>
|
||||
- 이 **탁자**가 너무 낮아요 = <span class="md spoiler">This **table** is too low</span>
|
||||
- 병이 **탁자**에서 떨어졌다 = <span class="md spoiler">The bottle fell from the **table**</span>
|
||||
|
||||
@@ -447,9 +1077,9 @@ Common Usages:
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 **선생님**이 되고 싶어요 = <span class="md spoiler">I want to be a <strong>teacher</strong></span>
|
||||
- 저는 **선생님**이 되고 싶어요 = <span class="md spoiler">I want to be a **teacher**</span>
|
||||
- 저는 학교에서 저의 **선생님**을 항상 봐요 = <span class="md spoiler">I always see my **teacher** at school</span>
|
||||
- 저는 **선생님**이에요 = <span class="md spoiler">I am a <strong>teacher</strong></span>
|
||||
- 저는 **선생님**이에요 = <span class="md spoiler">I am a **teacher**</span>
|
||||
- 저는 어제 **선생님**을 처음 만났어요 = <span class="md spoiler">I met my **teacher** for the first time yesterday</span>
|
||||
- **선생님**들은 다 나갔어요 = <span class="md spoiler">All the **teachers** left (went out)</span>
|
||||
- **선생님**은 학생들과 박물관에 갔다 = <span class="md spoiler">The **teacher** went to the museum with the students</span>
|
||||
@@ -471,9 +1101,9 @@ Common usages:
|
||||
|
||||
Examples
|
||||
|
||||
- 애기는 **침대**에서 자고 있어요 = <span class="md spoiler">The baby is sleeping in the <strong>bed</strong></span>
|
||||
- 애기는 **침대**에서 자고 있어요 = <span class="md spoiler">The baby is sleeping in the **bed**</span>
|
||||
- 저는 **침대**에 누워 있어요 = <span class="md spoiler">I’m lying in **bed**</span>
|
||||
- 저의 사진은 **침대** 위에 걸려 있어요 = <span class="md spoiler">My picture is hanging above my <strong>bed</strong></span>
|
||||
- 저의 사진은 **침대** 위에 걸려 있어요 = <span class="md spoiler">My picture is hanging above my **bed**</span>
|
||||
- 피곤한 사람은 **침대**에 누워서 잤어요 = <span class="md spoiler">The tired person lay on the **bed** and slept</span>
|
||||
- 저는 **침대**에 잠깐 눕고 싶어요 = <span class="md spoiler">I want to lie down in **bed** for just a second</span>
|
||||
|
||||
@@ -500,7 +1130,7 @@ Examples
|
||||
- **집** 값은 비싸지고 있어 = <span class="md spoiler">**House** prices are getting expensive</span>
|
||||
- 저는 내일 선생님의 **집**을 방문하겠어요 = <span class="md spoiler">I will visit the teacher’s **house** tomorrow</span>
|
||||
- 저는 어제 **집**을 두 번 청소했어요 = <span class="md spoiler">I cleaned the **house** twice yesterday</span>
|
||||
- 엄마는 우리를 위해 점심을 **집**에서 만들 거예요 = <span class="md spoiler">Mom will make lunch for us at <strong>home</strong></span>
|
||||
- 엄마는 우리를 위해 점심을 **집**에서 만들 거예요 = <span class="md spoiler">Mom will make lunch for us at **home**</span>
|
||||
- 우리 엄마는 **집**에 와서 빨리 요리했습니다 = <span class="md spoiler">Our/my mom came **home** and quickly cooked</span>
|
||||
- 우리는 **집**에 와서 바로 잤어요 = <span class="md spoiler">We came **home** and went to sleep immediately</span>
|
||||
- **집**에 가지 마! = <span class="md spoiler">Don’t go **home**!</span>
|
||||
@@ -561,9 +1191,9 @@ Examples
|
||||
- 그 **사람**은 아주 똑똑해요 = <span class="md spoiler">That **person** is very smart</span>
|
||||
- 모든 아시아 **사람**들은 젓가락을 잘 쓴다 = <span class="md spoiler">All Asian **people** use chopsticks well</span>
|
||||
- 그 **사람**은 미국에서 왔어요 = <span class="md spoiler">That **person** came from the United States</span>
|
||||
- 저는 그 **사람**을 알아요 = <span class="md spoiler">I know that <strong>person</strong></span>
|
||||
- 저는 그 **사람**을 알아요 = <span class="md spoiler">I know that **person**</span>
|
||||
- 저 **사람**은 저의 동생이에요 = <span class="md spoiler">That **person** is my younger sibling</span>
|
||||
- 저는 그 **사람**을 싫어해요 = <span class="md spoiler">I don’t like that <strong>person</strong></span>
|
||||
- 저는 그 **사람**을 싫어해요 = <span class="md spoiler">I don’t like that **person**</span>
|
||||
- 한국 **사람**들은 보통 아주 착해요 = <span class="md spoiler">Korean **people** are usually very nice</span>
|
||||
|
||||
</Details>
|
||||
@@ -591,11 +1221,11 @@ The word used to count books is “<TTS>권</TTS>”
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 좋은 **책**을 읽고 싶어요 = <span class="md spoiler">I want to read a good <strong>book</strong></span>
|
||||
- 저는 좋은 **책**을 읽고 싶어요 = <span class="md spoiler">I want to read a good **book**</span>
|
||||
- 저는 그것에 대해 **책**을 쓸 거예요 = <span class="md spoiler">I will write a **book** about it</span>
|
||||
- 저는 친구에게 **책**을 돌려줬어요 = <span class="md spoiler">I gave my friend back his **book**</span>
|
||||
- 저는 **책** 두 권을 읽었어요 = <span class="md spoiler">I read two <strong>books</strong></span>
|
||||
- 저는 그 **책**을 읽고 싶어요 = <span class="md spoiler">I want to read that <strong>book</strong></span>
|
||||
- 저는 **책** 두 권을 읽었어요 = <span class="md spoiler">I read two **books**</span>
|
||||
- 저는 그 **책**을 읽고 싶어요 = <span class="md spoiler">I want to read that **book**</span>
|
||||
- 그 학생은 하루 종일 **책**을 읽을 수 있어요 = <span class="md spoiler">That student can read **books** all day</span>
|
||||
- 이 박스에 **책**이 들어가 있어요 = <span class="md spoiler">There are **books** in this box</span>
|
||||
- 저는 누워서 **책**을 읽었어요 = <span class="md spoiler">I lied down and read a **book**</span>
|
||||
@@ -621,7 +1251,7 @@ Examples:
|
||||
- **컴퓨터**가 꺼져 있어요 = <span class="md spoiler">The **computer** is turned off</span>
|
||||
- 저는 **컴퓨터**를 켰어요 = <span class="md spoiler">I turned the **computer** on</span>
|
||||
- **컴퓨터**가 켜져 있어요 = <span class="md spoiler">The **computer** is (in the state of being) on</span>
|
||||
- 그는 고장 난 **컴퓨터**를 수리했어요 = <span class="md spoiler">He repaired the broken <strong>computer</strong></span>
|
||||
- 그는 고장 난 **컴퓨터**를 수리했어요 = <span class="md spoiler">He repaired the broken **computer**</span>
|
||||
- 교실에서 선생님들을 **컴퓨터**로 대체할 수 없어요 = <span class="md spoiler">You can’t replace teachers with **computers** in the classroom</span>
|
||||
|
||||
</Details>
|
||||
@@ -640,9 +1270,9 @@ Common Usages:
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 집을 **나무**로 지었어요 = <span class="md spoiler">I made a house out of <strong>wood</strong></span>
|
||||
- 나는 우리 집을 **나무**로 지었어 = <span class="md spoiler">I built our house out of <strong>wood</strong></span>
|
||||
- 대부분의 원숭이는 **나무**에서 살아요 = <span class="md spoiler">Most monkeys live in <strong>trees</strong></span>
|
||||
- 저는 집을 **나무**로 지었어요 = <span class="md spoiler">I made a house out of **wood**</span>
|
||||
- 나는 우리 집을 **나무**로 지었어 = <span class="md spoiler">I built our house out of **wood**</span>
|
||||
- 대부분의 원숭이는 **나무**에서 살아요 = <span class="md spoiler">Most monkeys live in **trees**</span>
|
||||
- 아이들은 **나무** 주위에서 놀고 있어요 = <span class="md spoiler">The children are playing around the **tree**</span>
|
||||
|
||||
</Details>
|
||||
@@ -657,7 +1287,7 @@ Many new Korean words are simply English words with a Korean pronunciation prono
|
||||
|
||||
Example
|
||||
|
||||
- 그는 **소파**에 앉아 있어요 = <span class="md spoiler">He is sitting on the <strong>couch</strong></span>
|
||||
- 그는 **소파**에 앉아 있어요 = <span class="md spoiler">He is sitting on the **couch**</span>
|
||||
- 이 **소파**는 아주 편해요 = <span class="md spoiler">This **sofa** is very comfortable</span>
|
||||
- 애기는 높은 **소파**에서 떨어졌어요 = <span class="md spoiler">The baby fell from the high **sofa**</span>
|
||||
|
||||
@@ -676,7 +1306,7 @@ Common Usages
|
||||
Example:
|
||||
|
||||
- 우리는 곧 **중국**에 갈 거예요 = <span class="md spoiler">We are going to **China** soon</span>
|
||||
- 그 사람은 **중국**에서 왔어요 = <span class="md spoiler">That person came from <strong>China</strong></span>
|
||||
- 그 사람은 **중국**에서 왔어요 = <span class="md spoiler">That person came from **China**</span>
|
||||
- 그 사람은 **중국**인이에요 = <span class="md spoiler">That person is **Chinese**</span>
|
||||
- **중국** 사람들은 한국사람들보다 더 가난해요 = <span class="md spoiler">**Chinese** people are poorer than Korean people</span>
|
||||
- 한국 사람과 **중국** 사람은 문화적으로 달라요 = <span class="md spoiler">Korean and **Chinese** people are culturally different</span>
|
||||
@@ -699,12 +1329,9 @@ Example
|
||||
- 그 사람은 **일본**에서 왔어요 = <span class="md spoiler">That person is from **Japan**</span>
|
||||
- **일본**은 전쟁에서 한국을 공격했어요 = <span class="md spoiler">**Japan** attacked Korea in the war</span>
|
||||
- 저는 **일본**에 스무 번 넘게 가 봤어요 = <span class="md spoiler">I’ve been to **Japan** more than twenty times</span>
|
||||
- 요즘에 한국 사람들은 **일본**에 별로 가고 싶지 않아요
|
||||
- <span class="md spoiler">These days, Korean people don’t really want to go to **Japan**</span>
|
||||
- 한국 집값은 **일본** 집값보다 훨씬 높아요
|
||||
- <span class="md spoiler">The price of Korean houses is much higher than the price of houses in **Japan**</span>
|
||||
- **일본**에서 성인들은 미국 청소년보다 만화책을 더 많이 읽어요
|
||||
- <span class="md spoiler">In **Japan**, adults read more comic books than young people in America</span>
|
||||
- 요즘에 한국 사람들은 **일본**에 별로 가고 싶지 않아요 = <span class="md spoiler">These days, Korean people don’t really want to go to **Japan**</span>
|
||||
- 한국 집값은 **일본** 집값보다 훨씬 높아요 = <span class="md spoiler">The price of Korean houses is much higher than the price of houses in **Japan**</span>
|
||||
- **일본**에서 성인들은 미국 청소년보다 만화책을 더 많이 읽어요 = <span class="md spoiler">In **Japan**, adults read more comic books than young people in America</span>
|
||||
|
||||
</Details>
|
||||
|
||||
@@ -730,9 +1357,11 @@ Common Usages:
|
||||
|
||||
Example
|
||||
|
||||
- **문**을 닫아야 돼요 = <span class="md spoiler">You have to close the <strong>door</strong></span>
|
||||
- 저는 **문**을 잠갔어요 = <span class="md spoiler">I locked the <strong>door</strong></span>
|
||||
- 저는 **문**을 열 거예요 = <span class="md spoiler">I will open the <strong>door</strong></span>
|
||||
- **문**을 닫아야 돼요 = <span class="md spoiler">You have to close the **door**</span>
|
||||
|
||||
# - 저는 **문**을 잠갔어요 = <span class="md spoiler">I locked the **door**</span>
|
||||
|
||||
- 저는 **문**을 열 거예요 = <span class="md spoiler">I will open the **door**</span>
|
||||
- 너무 추워서 **문**을 닫았어요 = <span class="md spoiler">I closed the **door** because it is too cold</span>
|
||||
- **문**이 완전히 열릴 때까지 버스에서 내리거나 문에 기대지 마세요 = <span class="md spoiler">Until the **door** is fully/completely open, don’t get off the bus or lean on the **door**</span>
|
||||
|
||||
@@ -781,11 +1410,11 @@ Common Usages:
|
||||
|
||||
Examples
|
||||
|
||||
- 저는 좋은 **학생**이에요 = <span class="md spoiler">I am a good <strong>student</strong></span>
|
||||
- 저는 **학생**이 아니에요 = <span class="md spoiler">I am not a <strong>student</strong></span>
|
||||
- 저는 좋은 **학생**이에요 = <span class="md spoiler">I am a good **student**</span>
|
||||
- 저는 **학생**이 아니에요 = <span class="md spoiler">I am not a **student**</span>
|
||||
- 선생님은 내일 **학생**들을 만날 거야 = <span class="md spoiler">The teacher will meet the **students** tomorrow</span>
|
||||
- 저는 **학생**들이 실망스러웠어요 = <span class="md spoiler">I was disappointed in the <strong>students</strong></span>
|
||||
- 저는 **학생**들에게 수업을 가르쳤어요 = <span class="md spoiler">I taught the class to the <strong>students</strong></span>
|
||||
- 저는 **학생**들이 실망스러웠어요 = <span class="md spoiler">I was disappointed in the **students**</span>
|
||||
- 저는 **학생**들에게 수업을 가르쳤어요 = <span class="md spoiler">I taught the class to the **students**</span>
|
||||
- 선생님은 **학생**들과 박물관에 갔다 = <span class="md spoiler">The teacher went to the museum with the **students**</span>
|
||||
|
||||
</Details>
|
||||
@@ -796,7 +1425,7 @@ Examples
|
||||
|
||||
<Details>
|
||||
|
||||
*This is the first time you are being introduced to a word that must be conjugated in order to be used. Visit [Lesson 5](./05-tenses.md) for more information. Any word that ends in “*다*” must be conjugated to be used. The conjugation of* 이다 _is different than other words. I introduce all of these conjugations in [Lesson 9](https://www.howtostudykorean.com/unit1/unit-1-lessons-9-16/unit-1-lesson-9/)._
|
||||
*This is the first time you are being introduced to a word that must be conjugated in order to be used. Visit [Lesson 5](./05-tenses.md) for more information. Any word that ends in “*다*” must be conjugated to be used. The conjugation of* 이다 _is different than other words. I introduce all of these conjugations in [Lesson 9](./09-conjugate-이다.md)._
|
||||
|
||||
Common usages
|
||||
|
||||
@@ -810,12 +1439,12 @@ Notes
|
||||
|
||||
Examples:
|
||||
|
||||
- 저는 예쁜 여자**예요** = I **am** a beautiful girl
|
||||
- 저 건물은 학교**입니다** = That building **is** a school
|
||||
- 그것은 사진**이에요** = That thing **is** a picture
|
||||
- 이 사람은 저의 누나**예요** = This (person) **is** my sister
|
||||
- 그것은 큰 비밀**이었어요** = That **was** a big secret
|
||||
- 저는 의사**였어요** = I **was** a doctor
|
||||
- 저는 예쁜 여자**예요** = <span class="md spoiler">I **am** a beautiful girl</span>
|
||||
- 저 건물은 학교**입니다** = <span class="md spoiler">That building **is** a school</span>
|
||||
- 그것은 사진**이에요** = <span class="md spoiler">That thing **is** a picture</span>
|
||||
- 이 사람은 저의 누나**예요** = <span class="md spoiler">This (person) **is** my sister</span>
|
||||
- 그것은 큰 비밀**이었어요** = <span class="md spoiler">That **was** a big secret</span>
|
||||
- 저는 의사**였어요** = <span class="md spoiler">I **was** a doctor</span>
|
||||
|
||||
</Details>
|
||||
|
||||
@@ -887,7 +1516,7 @@ The way to say “<span class="md spoiler">how are you?</span>” in Korean is:
|
||||
|
||||
- 잘 지내세요? <AudioButton src="https://www.howtostudykorean.com/wp-content/uploads/2014/10/Lesson-1new6.mp3" /> = <span class="md spoiler">How are you?</span>
|
||||
|
||||
Although this is the most literal way to ask “how are you?” in Korean, it is not as common as the English expression. Korean people love food, and common way to greet somebody is to ask them if they have eaten. The idea of asking questions in Korean is taught in [Lesson 21](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-21-asking-questions-in-korean-why-when-where-and-who/).
|
||||
Although this is the most literal way to ask “how are you?” in Korean, it is not as common as the English expression. Korean people love food, and common way to greet somebody is to ask them if they have eaten. The idea of asking questions in Korean is taught in [Lesson 21](./21-why-when-where-who.md).
|
||||
|
||||
The way to say “<span class="md spoiler">please</span>” in Korean is:
|
||||
|
||||
@@ -1110,7 +1739,7 @@ The focus of this lesson (and [Lessons 2](./02-particles.md), [3](./03-verbs.md)
|
||||
|
||||
The conjugation of sentences is very important, but so is the structure of sentences. When creating these lessons, I went back in forth many times thinking about which one I should present first. You can’t conjugate sentences if you don’t have a logical sentence to conjugate; and you can’t create a logical sentence if you don’t know how to conjugate it. In the end, I figured it would make more sense to present the information this way – where learners are introduced to sentence structure and then learn how to conjugate the words within the sentence.
|
||||
|
||||
Throughout all of my lessons, I use example sentences to show how grammar can be used. The example sentences in Lessons 1 – 4 are not conjugated. However, directly beneath each non-conjugated sentence is a conjugated version of the same sentence in parenthesis (one formal and one informal conjugation). You might want to glimpse at how the words are conjugated, but remember that this will be taught in [Lessons 5](./05-tenses.md) and [6](./06-honorifics.md) (for verbs and adjectives) and [Lesson 9](https://www.howtostudykorean.com/unit1/unit-1-lessons-9-16/unit-1-lesson-9/) (for 이다).
|
||||
Throughout all of my lessons, I use example sentences to show how grammar can be used. The example sentences in Lessons 1 – 4 are not conjugated. However, directly beneath each non-conjugated sentence is a conjugated version of the same sentence in parenthesis (one formal and one informal conjugation). You might want to glimpse at how the words are conjugated, but remember that this will be taught in [Lessons 5](./05-tenses.md) and [6](./06-honorifics.md) (for verbs and adjectives) and [Lesson 9](./09-conjugate-이다.md) (for 이다).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,7 +1,472 @@
|
||||
---
|
||||
vocabulary:
|
||||
nouns:
|
||||
- ko: 나라
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-1.mp3
|
||||
en: country
|
||||
examples:
|
||||
- ko: "어느 **나라**에서 왔어요?"
|
||||
en: What **country** did you come from?
|
||||
- ko: 미국은 민주적인 **나라**예요
|
||||
en: The US is a democratic **nation**
|
||||
- ko: 한국은 좋은 **나라**예요?
|
||||
en: is Korea a good **country**?
|
||||
- ko: 한국이 곧 좋은 **나라**가 될 것이다
|
||||
en: Korea will become a good **country** soon
|
||||
- ko: 한국은 다른 **나라**보다 땅이 작아요
|
||||
en: Korea's land is small compared to other **countries**
|
||||
|
||||
- ko: 가방
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-2.mp3
|
||||
en: bag/backpack
|
||||
notes: This is used to refer to a backpack and also other types of bags like purses.
|
||||
examples:
|
||||
- ko: 이 **가방**은 너무 무거워요
|
||||
en: This **bag** is too heavy
|
||||
- ko: 이 **가방**은 가벼워요
|
||||
en: This bag is light
|
||||
- ko: 저는 **가방**을 들었어요
|
||||
en: I carried the/my **bag**
|
||||
- ko: 저는 **가방**을 어깨에 맸어요
|
||||
en: I put the **bag** on my shoulders
|
||||
- ko: 저는 **가방**에 책을 넣었어요
|
||||
en: I put my books into my **backpack**
|
||||
- ko: "**가방**을 아무 데나 두세요"
|
||||
en: Put your **bag** down anywhere
|
||||
|
||||
- ko: 창문
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-3.mp3
|
||||
en: window
|
||||
examples:
|
||||
- ko: 너무 더워서 **창문**을 열었어요
|
||||
en: I opened a **window** because it is too hot
|
||||
- ko: 저는 **창문** 너머에 봤어요
|
||||
en: I looked through the **window**
|
||||
- ko: 저는 팔을 **창문** 너머로 내밀었어요
|
||||
en: I stuck my arm through the **window**
|
||||
- ko: "**창문**이 커튼으로 가려져 있어요"
|
||||
en: The **window** is covered by the curtains
|
||||
- ko: 아버지는 **창문**을 잠갔어요
|
||||
en: Dad locked the **window**
|
||||
|
||||
- ko: 잡지
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/02/Lesson2vocab-magazine.mp3
|
||||
en: magazine
|
||||
notes: The pronunciation of this word is closer to "잡찌"
|
||||
examples:
|
||||
- ko: 저는 **잡지**를 읽었어요
|
||||
en: I read a **magazine**
|
||||
- ko: 저는 **잡지**를 탁자 위에 놓을 거예요
|
||||
en: I will put the **magazine** on the table
|
||||
- ko: 이 **잡지**를 가져가도 돼요?
|
||||
en: May I take this **magazine**?
|
||||
|
||||
- ko: 방
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-5.mp3
|
||||
en: room
|
||||
examples:
|
||||
- ko: 저의 **방**은 너무 좁아요
|
||||
en: My **room** is too small/narrow
|
||||
- ko: 이 **방**은 좁아요
|
||||
en: This **room** is narrow
|
||||
- ko: 남자는 **방**에 들어왔어요
|
||||
en: That man came into **room**
|
||||
- ko: 저 책상은 이 **방**에 알맞아요
|
||||
en: That desk looks good in this **room**
|
||||
- ko: 저는 어제 저의 **방**을 청소했어요
|
||||
en: I cleaned my **room** yesterday
|
||||
|
||||
- ko: 냉장고
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-6.mp3
|
||||
en: refrigerator
|
||||
notes: The word for "freezer" is 냉동실.
|
||||
examples:
|
||||
- ko: 저는 야채를 **냉장고**에 넣었어요
|
||||
en: I put the vegetables in the **fridge**
|
||||
- ko: 자석을 **냉장고**에 그냥 붙여 놓았어요
|
||||
en: I just stuck the magnet onto the **fridge**
|
||||
- ko: 저는 당근을 칼로 잘라서 **냉장고**에 넣었어요
|
||||
en: I cut carrots with a knife and then put them into the **fridge**
|
||||
|
||||
- ko: 개
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-7.mp3
|
||||
en: dog
|
||||
notes: The word "강아지" is usually used for dogs that are pets.
|
||||
examples:
|
||||
- ko: "**개**는 고양이랑 쥐보다 더 커요"
|
||||
en: "**Dogs** are bigger than cats and mice"
|
||||
- ko: "**개**는 집 안에 있어요"
|
||||
en: The **dog** is in the house
|
||||
|
||||
- ko: 강아지
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-8.mp3
|
||||
en: puppy
|
||||
notes: |
|
||||
The word "개" is usually used for dogs that are not pets.
|
||||
|
||||
The counter for animals is "마리." See Lesson 10 for more information.
|
||||
|
||||
The sound a dog makes in Korean is "멍멍." This is like saying "woof woof" in English.
|
||||
examples:
|
||||
- ko: 어렸을 때 **강아지**를 키우고 싶었어요
|
||||
en: When I was young, I wanted to raise a **puppy**
|
||||
- ko: 저는 저의 **강아지**를 묻었어요
|
||||
en: I buried my **dog**
|
||||
- ko: 그 **강아지**의 주인은 누구예요?
|
||||
en: Who is the owner of that **dog**?
|
||||
- ko: 고양이는 **강아지**와 달라요
|
||||
en: Cats are different than **dogs**
|
||||
- ko: 그 **강아지**의 꼬리는 아주 귀여워요
|
||||
en: That **puppy's** tail is very cute
|
||||
- ko: 경찰관은 **강아지**의 주인에게 십만 원의 벌금을 물렸어요
|
||||
en: The police officers gave the owner of the **dog** a 100 000 won fine
|
||||
- ko: "**강아지**는 무서워서 죽는 척했어요"
|
||||
en: The **dog/puppy** pretended to be dead because it was scared
|
||||
|
||||
- ko: 고양이
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-9.mp3
|
||||
en: cat
|
||||
notes: The sound a cat makes in Korean is "야옹." This is like saying "meow" in English.
|
||||
examples:
|
||||
- ko: "**고양이**는 강아지와 달라요"
|
||||
en: "**Cats** are different than dogs"
|
||||
- ko: "**고양이**는 의자 밑에 있어요"
|
||||
en: The **cat** is under the chair
|
||||
- ko: 개는 **고양이**랑 쥐보다 더 커요
|
||||
en: Dogs are bigger than **cats** and mice
|
||||
- ko: 어미를 찾아도 이미 **고양이** 새끼가 다 죽었어요
|
||||
en: Regardless of if you find the mother, the baby **cats** (kittens) all died
|
||||
|
||||
- ko: 쥐
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-10.mp3
|
||||
en: rat, mouse
|
||||
examples:
|
||||
- ko: "**쥐**는 너무 더러워요"
|
||||
en: "**Rats** are very dirty"
|
||||
- ko: 저는 **쥐**를 들었어요
|
||||
en: I heard a **mouse**
|
||||
- ko: 개는 고양이랑 **쥐**보다 더 커요
|
||||
en: Dogs are bigger than cats and **mice**
|
||||
- ko: 우리 아빠가 **쥐**를 집에서 한 마리씩 쫓아냈어요
|
||||
en: Our dad chased the **rats** out of our house one by one
|
||||
|
||||
- ko: 펜
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-11.mp3
|
||||
en: pen
|
||||
examples:
|
||||
- ko: 저는 그것을 **펜**으로 썼어요
|
||||
en: I wrote that with a **pen**
|
||||
- ko: 나는 **펜** 네 개를 샀어
|
||||
en: I bought four **pens**
|
||||
- ko: 나는 **펜**을 가지고 있어
|
||||
en: I have a **pen**
|
||||
|
||||
- ko: 전화기
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-12.mp3
|
||||
en: phone
|
||||
notes: |
|
||||
A 전화기 usually refers to a typical land-line style phone that nobody uses anymore, and thus, is not said as often as it used to be said. A more common word to use is "핸드폰" (hand-phone, or cell-phone)
|
||||
examples:
|
||||
- ko: 요즘에 아무도 **전화기**를 안 써요
|
||||
en: These days, nobody uses a **phone**
|
||||
|
||||
- ko: 커피
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-13.mp3
|
||||
en: coffee
|
||||
notes: |
|
||||
Notice that there is no "F" in Korean, and thus, Korean people use "ㅍ" to make the "F" sound
|
||||
examples:
|
||||
- ko: 저는 친구들이랑 **커피**를 마셨어요
|
||||
en: I drank **coffee** with my friends
|
||||
- ko: 스타벅스 **커피**가 너무 달아요
|
||||
en: Starbucks **coffee** is too sweet
|
||||
- ko: "**커피**에 설탕을 안 넣어도 돼요"
|
||||
en: I/you don't need to put sugar in my/your **coffee**
|
||||
- ko: 저는 **커피**를 낮에만 마셔요
|
||||
en: I drink **coffee** only during the day
|
||||
|
||||
- ko: 식당
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-14.mp3
|
||||
en: restaurant
|
||||
notes: |
|
||||
The pronunciation of this word is closer to "식땅"
|
||||
|
||||
The Konglish word 레스토랑 is commonly used as well.
|
||||
examples:
|
||||
- ko: 좋은 **식당**에 가고 싶어요
|
||||
en: I want to go to a good **restaurant**
|
||||
- ko: "**식당**은 은행 옆에 있어요"
|
||||
en: The **restaurant** is beside the bank
|
||||
- ko: 우리학교에서 **식당**까지 10분 걸려요
|
||||
en: It takes 10 minutes to get from our school to the **restaurant**
|
||||
- ko: 호텔에 **식당**이 있어요
|
||||
en: There is a **restaurant** in the hotel
|
||||
- ko: 그 **식당**이 오래되었다
|
||||
en: That **restaurant** is old
|
||||
- ko: 우리 아버지는 **식당**에 실망했어요
|
||||
en: Our dad was disappointed in the **restaurant**
|
||||
- ko: 저는 **식당**에서 혼자서 먹었어요
|
||||
en: I ate by myself (alone) at the **restaurant**
|
||||
|
||||
- ko: 건물
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-15.mp3
|
||||
en: building
|
||||
notes: |
|
||||
This word appears in my Korean Sign Explanation Video 4
|
||||
|
||||
<YouTube id="M7YRA_3Betw" />
|
||||
examples:
|
||||
- ko: 그 **건물**은 너무 높아요
|
||||
en: That **building** is very high
|
||||
- ko: 그 **건물**은 어제와 달라요
|
||||
en: That **building** is different from yesterday
|
||||
- ko: 저 학교는 역사적인 **건물**이에요
|
||||
en: That school is a historical **building**
|
||||
- ko: 한국은 문화적인 **건물**이 많아요
|
||||
en: Korea has a lot of cultural **buildings**
|
||||
- ko: "**건물**을 지나가서 오른 쪽으로 가세요"
|
||||
en: Go past the **building**, then go right
|
||||
|
||||
- ko: 텔레비전
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-16.mp3
|
||||
en: television
|
||||
notes: |
|
||||
Originates from the English pronunciation of "Television."
|
||||
|
||||
This is often shortened to "TV" which sounds like "티비" in Korean.
|
||||
examples:
|
||||
- ko: "**텔레비전**을 오랫동안 보지 마세요!"
|
||||
en: Don't watch **TV** for a long time!
|
||||
|
||||
- ko: 미국
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-17.mp3
|
||||
en: USA
|
||||
examples:
|
||||
- ko: "**미국** 사람이에요?"
|
||||
en: Are you an **American**?
|
||||
- ko: 저는 다음 주에 **미국**에 갈 거예요
|
||||
en: I will go to the **US** next week
|
||||
- ko: 우리는 이틀 동안 **미국**에 있었어요
|
||||
en: We were in **America** for two days
|
||||
- ko: 저는 1년에 두 번 **미국**에 가요
|
||||
en: I go to **America** twice per year
|
||||
- ko: "**미국**은 대통령을 민주적으로 선출해요"
|
||||
en: "**America** elects its president democratically"
|
||||
- ko: 캐나다와 **미국**이 문화적인 차이가 있다
|
||||
en: Canada and the **US** have a cultural difference
|
||||
- ko: 저는 **미국**에서 친구를 만날 거예요
|
||||
en: I will meet a friend in **America**
|
||||
|
||||
- ko: 캐나다
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-18.mp3
|
||||
en: Canada
|
||||
examples:
|
||||
- ko: 저는 **캐나다**에서 왔어요
|
||||
en: I am from **Canada**
|
||||
- ko: 저는 **캐나다**에 가고 싶어요
|
||||
en: I want to go to **Canada**
|
||||
- ko: "**캐나다**는 미국과 같아요"
|
||||
en: "**Canada** is like the US"
|
||||
- ko: 부장님! 혹시 **캐나다**에 언제 가실 거예요?
|
||||
en: Boss! When are you going to **Canada**?
|
||||
- ko: "**캐나다** 사람들은 땅콩을 많이 먹어요"
|
||||
en: "**Canadians** eat a lot of peanuts"
|
||||
- ko: 저는 **캐나다**에서 유학했어요
|
||||
en: I studied abroad in **Canada**
|
||||
- ko: "**캐나다**에 언제 돌아올 거예요?"
|
||||
en: When are you coming back to **Canada**?
|
||||
- ko: 저는 **캐나다**에서 태어났어요
|
||||
en: I was born in **Canada**
|
||||
|
||||
- ko: 호텔
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-19.mp3
|
||||
en: hotel
|
||||
examples:
|
||||
- ko: "**호텔**에 식당이 있어요"
|
||||
en: There is a restaurant in the **hotel**
|
||||
- ko: "**호텔**은 학교 옆에 있어요"
|
||||
en: The **hotel** is beside the school
|
||||
|
||||
- ko: 학교
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-20.mp3
|
||||
en: school
|
||||
notes: The pronunciation of this word is closer to "학꾜"
|
||||
examples:
|
||||
- ko: 저는 **학교**에서 공부했어요
|
||||
en: I studied at the **school**
|
||||
- ko: 저는 **학교** 안에 있어요
|
||||
en: I am inside the **school**
|
||||
- ko: 저는 내일 **학교**에 갈 것입니다
|
||||
en: I will go to **school** tomorrow
|
||||
- ko: 어제 **학교**에 몇 번 갔어요?
|
||||
en: How many times did you go to **school** yesterday?
|
||||
- ko: 저는 3일 동안 **학교**에 안 갔어요
|
||||
en: I didn't go to **school** for 3 days
|
||||
- ko: "**학교**는 학생들한테 교과서를 제공하지 않아요"
|
||||
en: The **school** doesn't provide textbooks to the students
|
||||
- ko: 우리 **학교**가 세운 지 10주년이에요
|
||||
en: It is the 10th anniversary of our **school** opening
|
||||
|
||||
- ko: 은행
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-21.mp3
|
||||
en: bank
|
||||
examples:
|
||||
- ko: 호텔은 **은행** 옆에 있어요
|
||||
en: The hotel is beside the **bank**
|
||||
- ko: 아버지는 **은행**에 들어갔어요
|
||||
en: My dad went into the **bank**
|
||||
- ko: 저의 친구는 **은행** 안에 있어요
|
||||
en: My friend is in the **bank**
|
||||
- ko: 저는 친구를 만나고 나서 **은행**에 갈 거예요
|
||||
en: I will meet a friend and then go to the **bank**
|
||||
- ko: 친구가 오기 전에 저는 **은행**에 갔어요
|
||||
en: Before my friend came, I went to the **bank**
|
||||
|
||||
adverbs:
|
||||
- ko: 안
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-22.mp3
|
||||
en: inside
|
||||
notes: |
|
||||
Position words are typically placed after a noun to indicate in which direction in reference to that noun something occurs. ~에 is typically attached to a word of position. For example: "저의 친구는 은행 안에 있어요" = "My friend is in the bank"
|
||||
|
||||
안 can also be used to indicate that some action is completed "within" or "inside" a time period. This usage is discussed in Lesson 24. For example: "우리는 한 시간 안에 그 일을 끝내야 돼요" = "We need to finish that job/task within one hour"
|
||||
examples:
|
||||
- ko: 저의 친구는 은행 **안**에 있어요
|
||||
en: My friend is **in** the bank
|
||||
- ko: 개는 집 **안**에 있어요
|
||||
en: The dog is **in** the house
|
||||
- ko: 우리는 한 시간 **안**에 그 일을 끝내야 돼요
|
||||
en: We need to finish that job/task **within** one hour
|
||||
|
||||
- ko: 위
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-23.mp3
|
||||
en: on top
|
||||
notes: ㅅ is often added to 위 as a 받침. This is discussed in Lesson 131.
|
||||
examples:
|
||||
- ko: 잡지는 탁자 **위**에 있어요
|
||||
en: The magazine is **on** the table
|
||||
- ko: 우리 집은 언덕 **위**에 있어요
|
||||
en: Our house is **on top** of the hill
|
||||
- ko: 새는 구름 **위**에 날고 있어요
|
||||
en: The bird is flying **above** the clouds
|
||||
|
||||
- ko: 밑
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-24.mp3
|
||||
en: below
|
||||
examples:
|
||||
- ko: 고양이는 의자 **밑**에 있어요
|
||||
en: The cat is **below** the chair
|
||||
|
||||
- ko: 옆
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-25.mp3
|
||||
en: beside
|
||||
examples:
|
||||
- ko: 학교는 은행 **옆**에 있어요
|
||||
en: The school is **next to** the bank
|
||||
- ko: 은행이 학교 바로 **옆**에 있어요
|
||||
en: The bank is right (immediately) **next** **to** the school
|
||||
- ko: 강 **옆**에 큰 산이 있어요
|
||||
en: There is a big mountain **next** **to** the river
|
||||
- ko: 저는 병원을 공원 **옆**에 지었어요
|
||||
en: I built a hospital **beside** the park
|
||||
- ko: 나는 학교 **옆**에 서 있어
|
||||
en: I'm standing **next** **to** the school
|
||||
|
||||
- ko: 뒤
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-26.mp3
|
||||
en: behind
|
||||
notes: ㅅ is often added to 뒤 as a 받침. This is discussed in Lesson 131.
|
||||
examples:
|
||||
- ko: 병원은 박물관 **뒤**에 있어요
|
||||
en: The hospital is **behind** the museum
|
||||
- ko: 저는 학교 **뒤**에 있어요
|
||||
en: I am **behind** the school
|
||||
- ko: 저는 큰 박스 **뒤**에 숨었어요
|
||||
en: I hid **behind** a big box
|
||||
|
||||
- ko: 앞
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-27.mp3
|
||||
en: in front
|
||||
examples:
|
||||
- ko: 집은 가게 **앞**에 있어요
|
||||
en: The house is **in-front** of the store
|
||||
- ko: 저는 집 **앞**에 있는 눈을 다 치웠어요
|
||||
en: I cleaned up the snow **in-front** of the house
|
||||
|
||||
- ko: 여기
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-28.mp3
|
||||
en: here
|
||||
notes: |
|
||||
The placement of "~에" is usually assumed and therefore omitted. 여기 and ~에서 combine to form 여기서
|
||||
examples:
|
||||
- ko: "**여기에** 빨리 오세요!"
|
||||
en: Come **here** quick!
|
||||
- ko: 어떤 남자는 어제 **여기**에 왔어
|
||||
en: Some man came **here** yesterday
|
||||
- ko: 친구를 만나기 위해 **여기**로 왔어
|
||||
en: I came **here** to meet a friend
|
||||
- ko: 할아버지가 **여기에** 계신지 몰랐어요
|
||||
en: I didn't know you were **here**, grandpa
|
||||
- ko: 저의 친구는 (**여기**) 근처에 살아요
|
||||
en: My friend lives close (to **here**)
|
||||
- ko: "**여기서** 산이 안 보여"
|
||||
en: I can't see the mountains from **here**
|
||||
- ko: "**여기에** 주소를 써 주세요"
|
||||
en: Please write your address **here**
|
||||
- ko: 저는 **여기에** 한 달에 세 번 와요
|
||||
en: I come **here** three times per month
|
||||
- ko: 저는 오늘 이 책을 **여기**까지 읽었어요
|
||||
en: Today, I read up to **here** in this book
|
||||
- ko: "사과도 **여기서** 파나요?"
|
||||
en: Do you sell apples **here** too?
|
||||
- ko: "**여기**부터 서울까지 두 시간 30분만 걸려요"
|
||||
en: It only takes two and a half hours to get from **here** to Seoul
|
||||
- ko: 친구를 만나러 **여기**로 왔어요
|
||||
en: I came **here** to meet a friend
|
||||
|
||||
verbs:
|
||||
- ko: 있다
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/12/Lesson2vocabtobeat.mp3
|
||||
en: to be at a location
|
||||
notes: |
|
||||
~에 is typically attached to the location where something/somebody is. For more information, see the explanation in of this lesson.
|
||||
examples:
|
||||
- ko: 저는 은행에 **있어요**
|
||||
en: I am **at** the bank
|
||||
- ko: 개는 집 안에 **있어요**
|
||||
en: The dog **is** in the house
|
||||
- ko: 엄마가 어디에 **있어요**? 병원에 갔어요?
|
||||
en: Where **is** mom? Did she go to the hospital?
|
||||
- ko: 서울에 **있는** 공연을 보러 갈래요?
|
||||
en: Shall we go to the show **in** Seoul?
|
||||
- ko: 내가 한국에 **있**을 때마다 한국어로 말하고 싶어
|
||||
en: Every time I **am** **in** Korea, I want to speak Korean
|
||||
|
||||
adjectives:
|
||||
- ko: 있다
|
||||
audio: https://www.howtostudykorean.com/wp-content/uploads/2015/12/Lesson2vocabtobeat.mp3
|
||||
en: to have something
|
||||
notes: |
|
||||
~이/가 must be attached to the object that is being possessed. For more information, visit Lesson 2.
|
||||
examples:
|
||||
- ko: 저는 펜이 **있어요**
|
||||
en: I **have** a pen
|
||||
- ko: 저는 많은 돈이 **있어요**
|
||||
en: I **have** a lot of money
|
||||
- ko: "질문이 **있어요**?"
|
||||
en: Do you **have** a question?
|
||||
- ko: 저는 내일 할 일이 **있어요**
|
||||
en: I **have** something I need to do tomorrow
|
||||
- ko: 한국에서는 모든 집에 밥솥이 **있어요**
|
||||
en: All houses in Korea **have** a rice cooker
|
||||
---
|
||||
|
||||
# Lesson 2: Korean Particles 이/가
|
||||
|
||||
## Vocabulary
|
||||
|
||||
<VocabQuiz />
|
||||
|
||||
### Nouns
|
||||
|
||||
나라 <AudioButton src="https://www.howtostudykorean.com/wp-content/uploads/2014/01/wLesson-2-1.mp3" /> = <span class="md spoiler">country</span>
|
||||
@@ -15,7 +480,7 @@ Common Usages:
|
||||
Examples:
|
||||
|
||||
- 어느 **나라**에서 왔어요? = <span class="md spoiler">What **country** did you come from?</span>
|
||||
- 미국은 민주적인 **나라**예요 = <span class="md spoiler">The US is a democratic <strong>nation</strong></span>
|
||||
- 미국은 민주적인 **나라**예요 = <span class="md spoiler">The US is a democratic **nation**</span>
|
||||
- 한국은 좋은 **나라**예요? = <span class="md spoiler">is Korea a good **country**?</span>
|
||||
- 한국이 곧 좋은 **나라**가 될 것이다 = <span class="md spoiler">Korea will become a good **country** soon</span>
|
||||
- 한국은 다른 **나라**보다 땅이 작아요 = <span class="md spoiler">Korea’s land is small compared to other **countries**</span>
|
||||
@@ -40,7 +505,7 @@ Example:
|
||||
|
||||
- 이 **가방**은 너무 무거워요 = <span class="md spoiler">This **bag** is too heavy</span>
|
||||
- 이 **가방**은 가벼워요 = <span class="md spoiler">This bag is light</span>
|
||||
- 저는 **가방**을 들었어요 = <span class="md spoiler">I carried the/my <strong>bag</strong></span>
|
||||
- 저는 **가방**을 들었어요 = <span class="md spoiler">I carried the/my **bag**</span>
|
||||
- 저는 **가방**을 어깨에 맸어요 = <span class="md spoiler">I put the **bag** on my shoulders</span>
|
||||
- 저는 **가방**에 책을 넣었어요 = <span class="md spoiler">I put my books into my **backpack**</span>
|
||||
- **가방**을 아무 데나 두세요 = <span class="md spoiler">Put your **bag** down anywhere</span>
|
||||
@@ -60,7 +525,7 @@ Common Usages:
|
||||
Examples:
|
||||
|
||||
- 너무 더워서 **창문**을 열었어요 = <span class="md spoiler">I opened a **window** because it is too hot</span>
|
||||
- 저는 **창문** 너머에 봤어요 = <span class="md spoiler">I looked through the <strong>window</strong></span>
|
||||
- 저는 **창문** 너머에 봤어요 = <span class="md spoiler">I looked through the **window**</span>
|
||||
- 저는 팔을 **창문** 너머로 내밀었어요 = <span class="md spoiler">I stuck my arm through the **window**</span>
|
||||
- **창문**이 커튼으로 가려져 있어요 = <span class="md spoiler">The **window** is covered by the curtains</span>
|
||||
- 아버지는 **창문**을 잠갔어요 = <span class="md spoiler">Dad locked the **window**</span>
|
||||
@@ -83,7 +548,7 @@ Common Usages
|
||||
|
||||
Example:
|
||||
|
||||
- 저는 **잡지**를 읽었어요 = <span class="md spoiler">I read a <strong>magazine</strong></span>
|
||||
- 저는 **잡지**를 읽었어요 = <span class="md spoiler">I read a **magazine**</span>
|
||||
- 저는 **잡지**를 탁자 위에 놓을 거예요 = <span class="md spoiler">I will put the **magazine** on the table</span>
|
||||
- 이 **잡지**를 가져가도 돼요? = <span class="md spoiler">May I take this **magazine**?</span>
|
||||
|
||||
@@ -109,7 +574,7 @@ Examples:
|
||||
|
||||
- 저의 **방**은 너무 좁아요 = <span class="md spoiler">My **room** is too small/narrow</span>
|
||||
- 이 **방**은 좁아요 = <span class="md spoiler">This **room** is narrow</span>
|
||||
- 남자는 **방**에 들어왔어요 = <span class="md spoiler">That man came into <strong>room</strong></span>
|
||||
- 남자는 **방**에 들어왔어요 = <span class="md spoiler">That man came into **room**</span>
|
||||
- 저 책상은 이 **방**에 알맞아요 = <span class="md spoiler">That desk looks good in this **room**</span>
|
||||
- 저는 어제 저의 **방**을 청소했어요 = <span class="md spoiler">I cleaned my **room** yesterday</span>
|
||||
|
||||
@@ -129,8 +594,8 @@ Common Usages:
|
||||
|
||||
Examples:
|
||||
|
||||
- 저는 야채를 **냉장고**에 넣었어요 = <span class="md spoiler">I put the vegetables in the <strong>fridge</strong></span>
|
||||
- 자석을 **냉장고**에 그냥 붙여 놓았어요 = <span class="md spoiler">I just stuck the magnet onto the <strong>fridge</strong></span>
|
||||
- 저는 야채를 **냉장고**에 넣었어요 = <span class="md spoiler">I put the vegetables in the **fridge**</span>
|
||||
- 자석을 **냉장고**에 그냥 붙여 놓았어요 = <span class="md spoiler">I just stuck the magnet onto the **fridge**</span>
|
||||
- 저는 당근을 칼로 잘라서 **냉장고**에 넣었어요 = <span class="md spoiler">I cut carrots with a knife and then put them into the **fridge**</span>
|
||||
|
||||
</Details>
|
||||
@@ -157,16 +622,16 @@ Notes:
|
||||
|
||||
The word “개” is usually used for dogs that are not pets.
|
||||
|
||||
The counter for animals is “<TTS>마리</TTS>.” See [Lesson 10](https://www.howtostudykorean.com/unit1/unit-1-lessons-9-16/unit-1-lesson-10/) for more information.
|
||||
The counter for animals is “<TTS>마리</TTS>.” See [Lesson 10](./10-numbers.md) for more information.
|
||||
|
||||
The sound a dog makes in Korean is “<TTS>멍멍</TTS>.” This is like saying “woof woof” in English.
|
||||
|
||||
Examples:
|
||||
|
||||
- 어렸을 때 **강아지**를 키우고 싶었어요 = <span class="md spoiler">When I was young, I wanted to raise a <strong>puppy</strong></span>
|
||||
- 저는 저의 **강아지**를 묻었어요 = <span class="md spoiler">I buried my <strong>dog</strong></span>
|
||||
- 어렸을 때 **강아지**를 키우고 싶었어요 = <span class="md spoiler">When I was young, I wanted to raise a **puppy**</span>
|
||||
- 저는 저의 **강아지**를 묻었어요 = <span class="md spoiler">I buried my **dog**</span>
|
||||
- 그 **강아지**의 주인은 누구예요? = <span class="md spoiler">Who is the owner of that **dog**?</span>
|
||||
- 고양이는 **강아지**와 달라요 = <span class="md spoiler">Cats are different than <strong>dogs</strong></span>
|
||||
- 고양이는 **강아지**와 달라요 = <span class="md spoiler">Cats are different than **dogs**</span>
|
||||
- 그 강아지의 꼬리는 아주 귀여워요 = <span class="md spoiler">That **puppy’s** tail is very cute</span>
|
||||
- 경찰관은 **강아지**의 주인에게 십만 원의 벌금을 물렸어요 = <span class="md spoiler">The police officers gave the owner of the **dog** a 100 000 won fine</span>
|
||||
- **강아지**는 무서워서 죽는 척했어요 = <span class="md spoiler">The **dog/puppy** pretended to be dead because it was scared</span>
|
||||
@@ -203,8 +668,8 @@ Common Usages:
|
||||
Example:
|
||||
|
||||
- **쥐**는 너무 더러워요 = <span class="md spoiler">**Rats** are very dirty</span>
|
||||
- 저는 **쥐**를 들었어요 = <span class="md spoiler">I heard a <strong>mouse</strong></span>
|
||||
- 개는 고양이랑 **쥐**보다 더 커요 = <span class="md spoiler">Dogs are bigger than cats and <strong>mice</strong></span>
|
||||
- 저는 **쥐**를 들었어요 = <span class="md spoiler">I heard a **mouse**</span>
|
||||
- 개는 고양이랑 **쥐**보다 더 커요 = <span class="md spoiler">Dogs are bigger than cats and **mice**</span>
|
||||
- 우리 아빠가 **쥐**를 집에서 한 마리씩 쫓아냈어요 = <span class="md spoiler">Our dad chased the **rats** out of our house one by one</span>
|
||||
|
||||
</Details>
|
||||
@@ -220,8 +685,8 @@ Common Usages:
|
||||
|
||||
Examples:
|
||||
|
||||
- 저는 그것을 **펜**으로 썼어요 = <span class="md spoiler">I wrote that with a <strong>pen</strong></span>
|
||||
- 나는 **펜** 네 개를 샀어 = <span class="md spoiler">I bought four <strong>pens</strong></span>
|
||||
- 저는 그것을 **펜**으로 썼어요 = <span class="md spoiler">I wrote that with a **pen**</span>
|
||||
- 나는 **펜** 네 개를 샀어 = <span class="md spoiler">I bought four **pens**</span>
|
||||
- 나는 **펜**을 가지고 있어 = <span class="md spoiler">I have a **pen**</span>
|
||||
|
||||
</Details>
|
||||
@@ -259,7 +724,7 @@ Example:
|
||||
|
||||
- 저는 친구들이랑 **커피**를 마셨어요 = <span class="md spoiler">I drank **coffee** with my friends</span>
|
||||
- 스타벅스 **커피**가 너무 달아요 = <span class="md spoiler">Starbucks **coffee** is too sweet</span>
|
||||
- **커피**에 설탕을 안 넣어도 돼요 = <span class="md spoiler">I/you don’t need to put sugar in my/your <strong>coffee</strong></span>
|
||||
- **커피**에 설탕을 안 넣어도 돼요 = <span class="md spoiler">I/you don’t need to put sugar in my/your **coffee**</span>
|
||||
- 저는 **커피**를 낮에만 마셔요 = <span class="md spoiler">I drink **coffee** only during the day</span>
|
||||
|
||||
</Details>
|
||||
@@ -283,10 +748,10 @@ Examples:
|
||||
|
||||
- 좋은 **식당**에 가고 싶어요 = <span class="md spoiler">I want to go to a good **restauran**t</span>
|
||||
- **식당**은 은행 옆에 있어요 = <span class="md spoiler">The **restaurant** is beside the bank</span>
|
||||
- 우리학교에서 **식당**까지 10분 걸려요 = <span class="md spoiler">It takes 10 minutes to get from our school to the <strong>restaurant</strong></span>
|
||||
- 우리학교에서 **식당**까지 10분 걸려요 = <span class="md spoiler">It takes 10 minutes to get from our school to the **restaurant**</span>
|
||||
- 호텔에 **식당**이 있어요 = <span class="md spoiler">There is a **restaurant** in the hotel</span>
|
||||
- 그 **식당**이 오래되었다 = <span class="md spoiler">That **restaurant** is old</span>
|
||||
- 우리 아버지는 **식당**에 실망했어요 = <span class="md spoiler">Our dad was disappointed in the <strong>restaurant</strong></span>
|
||||
- 우리 아버지는 **식당**에 실망했어요 = <span class="md spoiler">Our dad was disappointed in the **restaurant**</span>
|
||||
- 저는 **식당**에서 혼자서 먹었어요 = <span class="md spoiler">I ate by myself (alone) at the **restaurant**</span>
|
||||
|
||||
</Details>
|
||||
@@ -304,7 +769,7 @@ Examples:
|
||||
|
||||
- 그 **건물**은 너무 높아요 = <span class="md spoiler">That **building** is very high</span>
|
||||
- 그 **건물**은 어제와 달라요 = <span class="md spoiler">That **building** is different from yesterday</span>
|
||||
- 저 학교는 역사적인 **건물**이에요 = <span class="md spoiler">That school is a historical <strong>building</strong></span>
|
||||
- 저 학교는 역사적인 **건물**이에요 = <span class="md spoiler">That school is a historical **building**</span>
|
||||
- 한국은 문화적인 **건물**이 많아요 = <span class="md spoiler">Korea has a lot of cultural **buildings**</span>
|
||||
- **건물**을 지나가서 오른 쪽으로 가세요 = <span class="md spoiler">Go past the **building**, then go right</span>
|
||||
|
||||
@@ -369,7 +834,7 @@ Common Usages:
|
||||
|
||||
Example:
|
||||
|
||||
- 저는 **캐나다**에서 왔어요 = <span class="md spoiler">I am from <strong>Canada</strong></span>
|
||||
- 저는 **캐나다**에서 왔어요 = <span class="md spoiler">I am from **Canada**</span>
|
||||
- 저는 **캐나다**에 가고 싶어요 = <span class="md spoiler">I want to go to **Canada**</span>
|
||||
- **캐나다**는 미국과 같아요 = <span class="md spoiler">**Canada** is like the US</span>
|
||||
- 부장님! 혹시 **캐나다**에 언제 가실 거예요? = <span class="md spoiler">Boss! When are you going to **Canada**?</span>
|
||||
@@ -390,8 +855,8 @@ Common Usages:
|
||||
|
||||
Examples:
|
||||
|
||||
- **호텔**에 식당이 있어요 = There is a restaurant in the **hotel**
|
||||
- **호텔**은 학교 옆에 있어요 = The **hotel** is beside the school
|
||||
- **호텔**에 식당이 있어요 = <span class="md spoiler">There is a restaurant in the **hotel**</span>
|
||||
- **호텔**은 학교 옆에 있어요 = <span class="md spoiler">The **hotel** is beside the school</span>
|
||||
|
||||
</Details>
|
||||
|
||||
@@ -411,8 +876,8 @@ Common Usages:
|
||||
|
||||
Examples:
|
||||
|
||||
- 저는 **학교**에서 공부했어요 = <span class="md spoiler">I studied at the <strong>school</strong></span>
|
||||
- 저는 **학교** 안에 있어요 = <span class="md spoiler">I am inside the <strong>school</strong></span>
|
||||
- 저는 **학교**에서 공부했어요 = <span class="md spoiler">I studied at the **school**</span>
|
||||
- 저는 **학교** 안에 있어요 = <span class="md spoiler">I am inside the **school**</span>
|
||||
- 저는 내일 **학교**에 갈 것입니다 = <span class="md spoiler">I will go to **school** tomorrow</span>
|
||||
- 어제 **학교**에 몇 번 갔어요? = <span class="md spoiler">How many times did you go to **school** yesterday?</span>
|
||||
- 저는 3일 동안 **학교**에 안 갔어요 = <span class="md spoiler">I didn’t go to **school** for 3 days</span>
|
||||
@@ -434,10 +899,10 @@ Common Usages:
|
||||
|
||||
Examples:
|
||||
|
||||
- 호텔은 **은행** 옆에 있어요 = <span class="md spoiler">The hotel is beside the <strong>bank</strong></span>
|
||||
- 아버지는 **은행**에 들어갔어요 = <span class="md spoiler">My dad went into the <strong>bank</strong></span>
|
||||
- 저의 친구는 **은행** 안에 있어요 = <span class="md spoiler">My friend is in the <strong>bank</strong></span>
|
||||
- 저는 친구를 만나고 나서 **은행**에 갈 거예요 = <span class="md spoiler">I will meet a friend and then go to the <strong>bank</strong></span>
|
||||
- 호텔은 **은행** 옆에 있어요 = <span class="md spoiler">The hotel is beside the **bank**</span>
|
||||
- 아버지는 **은행**에 들어갔어요 = <span class="md spoiler">My dad went into the **bank**</span>
|
||||
- 저의 친구는 **은행** 안에 있어요 = <span class="md spoiler">My friend is in the **bank**</span>
|
||||
- 저는 친구를 만나고 나서 **은행**에 갈 거예요 = <span class="md spoiler">I will meet a friend and then go to the **bank**</span>
|
||||
- 친구가 오기 전에 저는 **은행**에 갔어요 = <span class="md spoiler">Before my friend came, I went to the **bank**</span>
|
||||
|
||||
</Details>
|
||||
@@ -460,7 +925,7 @@ Position words are typically placed after a noun to indicate in which direction
|
||||
- 저의 친구는 은행 **안**에 있어요 = <span class="md spoiler">My friend is **in** the bank</span>
|
||||
- 개는 집 **안**에 있어요 = <span class="md spoiler">The dog is **in** the house</span>
|
||||
|
||||
안 can also be used to indicate that some action is completed “within” or “inside” a time period. This usage is discussed in [Lesson 24](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-24/). For example:
|
||||
안 can also be used to indicate that some action is completed “within” or “inside” a time period. This usage is discussed in [Lesson 24](./24-before-after-since-within.md). For example:
|
||||
|
||||
- 우리는 한 시간 **안**에 그 일을 끝내야 돼요 = <span class="md spoiler">We need to finish that job/task **within** one hour</span>
|
||||
|
||||
@@ -574,7 +1039,7 @@ Examples:
|
||||
- 할아버지가 **여기에** 계신지 몰랐어요 = <span class="md spoiler">I didn’t know you were **here**, grandpa</span>
|
||||
- 저의 친구는 (**여기**) 근처에 살아요 = <span class="md spoiler">My friend lives close (to **here**)</span>
|
||||
- **여기서** 산이 안 보여 = <span class="md spoiler">I can’t see the mountains from **here**</span>
|
||||
- **여기에** 주소를 써 주세요 = <span class="md spoiler">Please write your address <strong>here</strong></span>
|
||||
- **여기에** 주소를 써 주세요 = <span class="md spoiler">Please write your address **here**</span>
|
||||
- 저는 **여기에** 한 달에 세 번 와요 = <span class="md spoiler">I come **here** three times per month</span>
|
||||
- 저는 오늘 이 책을 **여기**까지 읽었어요 = <span class="md spoiler">Today, I read up to **here** in this book</span>
|
||||
- 사과도 **여기서** 파나요? = <span class="md spoiler">Do you sell apples **here** too?</span>
|
||||
@@ -636,7 +1101,7 @@ You might also want to try listening to all of the words on loop with this [Voca
|
||||
|
||||
## Introduction
|
||||
|
||||
In [Lesson 1](https://www.howtostudykorean.com/unit1/unit-1-lessons-1-8/unit-1-lesson-1/) you learned about simple Korean particles. To review, you learned that:
|
||||
In [Lesson 1](./01-sentences.md) you learned about simple Korean particles. To review, you learned that:
|
||||
|
||||
- ~는 or ~은 are used to indicate <span class="md spoiler">the subject (or main person/thing)</span> in a sentence.
|
||||
- ~를 or ~을 are used to indicate <span class="md spoiler">the object</span> in a sentence.
|
||||
@@ -668,7 +1133,7 @@ Let’s talk about the first usage, “to have.” In English, “to have” is
|
||||
|
||||
This usage of 있다 in Korean is an _adjective._ This is hard for a learner to wrap their head around. At this point, this is important to you for one reason.
|
||||
|
||||
You learned in [Lesson 1](https://www.howtostudykorean.com/unit1/unit-1-lessons-1-8/unit-1-lesson-1/) that sentences with adjectives cannot act on an object. Thus, you cannot have a word with the particle ~을/를 attached to it if the predicating word in a sentence is an adjective (because ~을/를 indicates an object in a sentence).
|
||||
You learned in [Lesson 1](./01-sentences.md) that sentences with adjectives cannot act on an object. Thus, you cannot have a word with the particle ~을/를 attached to it if the predicating word in a sentence is an adjective (because ~을/를 indicates an object in a sentence).
|
||||
|
||||
If this _weren’t_ the case, we could do the following:
|
||||
|
||||
@@ -694,7 +1159,7 @@ Remember that the example sentences provided in Lessons 1, 2, 3 and 4 are _not_
|
||||
|
||||
## Indicating a Place or Time: ~에
|
||||
|
||||
In the [previous lesson](https://www.howtostudykorean.com/unit1/unit-1-lessons-1-8/unit-1-lesson-1/), you learned how to use the particles ~은/는 and ~을/를 to denote the purpose of certain words in a Korean sentence. The particle ~에 is also used to denote certain words in a sentence. Specifically, ~에 denotes a place or time. When used to identify a place, it is similar to the underlined words in the English sentences below:
|
||||
In the [previous lesson](./01-sentences.md), you learned how to use the particles ~은/는 and ~을/를 to denote the purpose of certain words in a Korean sentence. The particle ~에 is also used to denote certain words in a sentence. Specifically, ~에 denotes a place or time. When used to identify a place, it is similar to the underlined words in the English sentences below:
|
||||
|
||||
- I am at school
|
||||
- I went to the park
|
||||
@@ -789,7 +1254,7 @@ One of the most difficult things for a new learner of Korean to understand is th
|
||||
|
||||
In addition to this, there are more functions of ~이/가 that you should know about.
|
||||
|
||||
In [Lesson 1](https://www.howtostudykorean.com/unit1/unit-1-lessons-1-8/unit-1-lesson-1/), you learned that you should add ~는/은 to the subject of the sentence. To use an example using the grammar taught earlier in this Lesson, you could say:
|
||||
In [Lesson 1](./01-sentences.md), you learned that you should add ~는/은 to the subject of the sentence. To use an example using the grammar taught earlier in this Lesson, you could say:
|
||||
|
||||
- 고양이**는** 집 뒤에 있다 = <span class="md spoiler">The cat is behind the house</span>
|
||||
- (고양이**는** 집 뒤에 있어 / 고양이**는** 집 뒤에 있어요 <AudioButton src="https://www.howtostudykorean.com/wp-content/uploads/2014/10/Lesson2new11.mp3" />)
|
||||
@@ -842,7 +1307,7 @@ In both pairs of examples (using ~는/은 or ~이/가), the translation does not
|
||||
|
||||
Note that this “comparative” function of ~는/은 can be used in much more complicated sentences, and can be attached to other grammatical principles – neither of which you have learned yet. In future lessons, not only will you see examples of increasing complexity applying this concept, but its usage with other grammatical principles will be introduced specifically. You need to remember that the example sentences given at this level are incredibly simple and do not really reflect actual sentences that you are likely to hear as one-off sentences from Korean people. Real speech is much more complex and it usually is an intricate combination of many clauses and grammatical principles.
|
||||
|
||||
Our lessons don’t really get into the use of multiple clauses until [Lesson 24](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-24/). Creating sentences with more than one clause opens an entire other can of worms that you don’t have the tools to deal with yet. I encourage you to NOT read ahead to that lesson. Rather, I encourage you to keep the information from this lesson in mind as you eventually do reach that level.
|
||||
Our lessons don’t really get into the use of multiple clauses until [Lesson 24](./24-before-after-since-within.md). Creating sentences with more than one clause opens an entire other can of worms that you don’t have the tools to deal with yet. I encourage you to NOT read ahead to that lesson. Rather, I encourage you to keep the information from this lesson in mind as you eventually do reach that level.
|
||||
|
||||
As you progress through our Lessons, you will see both “~는/은” and “~이/가” used as the subject particles in the thousands of example sentences we have provided. As almost all of our example sentences are just written as one sentence (without any background, prior context, or explanation of the situation), there is no way to tell if something is being compared to – and thus – their usage is usually arbitrary. That being said – every Korean example sentence throughout all of our lessons is always checked by a native Korean speaker to make sure that nothing is awkward (or incorrect).
|
||||
|
||||
@@ -850,15 +1315,15 @@ In addition to the distinction discussed in this lesson, there are other situati
|
||||
|
||||
At this point, I would like you to continue to [Lesson 3](./03-verbs.md) to continue learning other grammatical principles you need to deepen your understanding of Korean in general.
|
||||
|
||||
In [Lessons 17](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-17/) and [22](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-22/), we will come back to this problem and dive into more ways we can distinguish the functions of ~이/가 and ~는/은. I want to stress that I do not want you to read these now, but you should know that there is more to distinguishing ~는/은 and ~이/가 than is described here.
|
||||
In [Lessons 17](./17-connecting-want.md) and [22](./22-how-which-what-how-many.md), we will come back to this problem and dive into more ways we can distinguish the functions of ~이/가 and ~는/은. I want to stress that I do not want you to read these now, but you should know that there is more to distinguishing ~는/은 and ~이/가 than is described here.
|
||||
|
||||
If you haven’t reached [Lesson 17](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-17/) (and especially if you haven’t even moved on to [Lesson 3](./03-verbs.md)) you won’t understand what is being described in that lesson. Being able to fully understand the difference between ~이/가 and ~는/은 is important, but not as important (at the moment) as understanding other aspects of Korean grammar. I can’t stress this enough – your understanding of the difference between the two will progress with your Korean development in general.
|
||||
If you haven’t reached [Lesson 17](./17-connecting-want.md) (and especially if you haven’t even moved on to [Lesson 3](./03-verbs.md)) you won’t understand what is being described in that lesson. Being able to fully understand the difference between ~이/가 and ~는/은 is important, but not as important (at the moment) as understanding other aspects of Korean grammar. I can’t stress this enough – your understanding of the difference between the two will progress with your Korean development in general.
|
||||
|
||||
The good thing is, even if you make a mistake with the usages of ~이/가 and ~는/은 (either because you are confused or because you haven’t reached the later lessons yet), 99.9% of the time, the listener will be able to understand exactly what you are trying to express. Likewise, if you listen to somebody speaking, you will be able to understand what they are trying to say regardless of if you have learned the more complex usages of ~이/가 and ~는/은. The difference between these two particles is about nuance and does not dramatically change the meaning of the sentence.
|
||||
|
||||
Making a mistake between other particles, however, _would_ cause other people to misunderstand you. For example, using ~를/을 instead of ~는/은 would (most likely) make your sentence incomprehensible.
|
||||
|
||||
That’s it for this lesson. Please keep all of this information in your mind for future lessons. We will continue this discussion in [Lesson 17](https://www.howtostudykorean.com/unit1/unit-1-lessons-17-25-2/lesson-17/).
|
||||
That’s it for this lesson. Please keep all of this information in your mind for future lessons. We will continue this discussion in [Lesson 17](./17-connecting-want.md).
|
||||
|
||||
For now, please continue to [Lesson 3](./03-verbs.md).
|
||||
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -7,6 +7,18 @@ hero:
|
||||
tagline: "Korean grammar edited"
|
||||
---
|
||||
|
||||
[Sound Rules](./ภาษาเกาหลีเรียนง่าย/1/04-sound-rules.md)
|
||||
|
||||
## [Themes](./howtostudykorean/theme/index.md)
|
||||
|
||||
- [School](./howtostudykorean/theme/01-school.md)
|
||||
- [Transportation](./howtostudykorean/theme/02-transportation.md)
|
||||
- [Eating](./howtostudykorean/theme/03-eating.md)
|
||||
- [Shopping](./howtostudykorean/theme/04-shopping.md)
|
||||
- [Weather](./howtostudykorean/theme/05-weather.md)
|
||||
|
||||
## Unit 1
|
||||
|
||||
- [Lesson 1: Basic Sentences](./howtostudykorean/unit-1/01-sentences.md)
|
||||
- [Lesson 2: Particles](./howtostudykorean/unit-1/02-particles.md)
|
||||
- [Lesson 3: Verbs/Adjectives](./howtostudykorean/unit-1/03-verbs.md)
|
||||
@@ -19,3 +31,26 @@ hero:
|
||||
---
|
||||
|
||||
- [Lesson 9: Conjugate 이다](./howtostudykorean/unit-1/09-conjugate-이다.md)
|
||||
- [Lesson 10: Numbers](./howtostudykorean/unit-1/10-numbers.md)
|
||||
- [Lesson 11: Date, Time, Duration](./howtostudykorean/unit-1/11-time.md)
|
||||
- [Lesson 12: Particles 들, 만, 에서, 부터, 까지, (으)로](./howtostudykorean/unit-1/12-more-particles.md)
|
||||
- [Lesson 13: and, with, to, from, for, about](./howtostudykorean/unit-1/13-and-with.md)
|
||||
- [Lesson 14: Passive Verbs](./howtostudykorean/unit-1/14-passive.md)
|
||||
- [Lesson 15: 들다, Homonyms, Being Sick, Different/Similar/Same](./howtostudykorean/unit-1/15-good-carry-similar.md)
|
||||
- [Lesson 16: Noun + ~적, ~적으로, ~적이다, ~스럽다](./howtostudykorean/unit-1/16-relating-to.md)
|
||||
|
||||
---
|
||||
|
||||
- [Lesson 17: Connecting Particle \~고 and \~고 싶다 “I want to”](./howtostudykorean/unit-1/17-connecting-want.md)
|
||||
- [Lesson 18: Present Progressive \~고 있다; To be Getting \~아/어지다](./howtostudykorean/unit-1/18-present-progressive.md)
|
||||
- [Lesson 19: Comparatives and Superlatives: 더, 보다, 가장/제일](./howtostudykorean/unit-1/19-comparatives.md)
|
||||
- [Lesson 20: Well and Poorly: 잘 and 못](./howtostudykorean/unit-1/20-well-poorly.md)
|
||||
- [Lesson 21: Asking Questions: Why, When, Where, Who](./howtostudykorean/unit-1/21-why-when-where-who.md)
|
||||
- [Lesson 22: Asking Questions: How, What, Which, How Many](./howtostudykorean/unit-1/22-how-which-what-how-many.md)
|
||||
- [Lesson 23: ㅎ Irregular: Colors, 이렇다, 그렇다 and 저렇다](./howtostudykorean/unit-1/23-ㅎ-irregulars-colors.md)
|
||||
- [Lesson 24: Before, After, Since, Within (전/후/이래로/이내)](./howtostudykorean/unit-1/24-before-after-since-within.md)
|
||||
- [Lesson 25: Anybody, Everybody, Somebody, Nobody, etc.](./howtostudykorean/unit-1/25-anybody-everybody.md)
|
||||
|
||||
## Unit 2
|
||||
|
||||
- [Lesson 26: \~는 것 Describing Nouns with Verbs](./howtostudykorean/unit-2/26-describing-nouns-with-verbs.md)
|
||||
File diff suppressed because it is too large.
Load diff
+16
-4
@@ -2,6 +2,7 @@
|
||||
"name": "ko-grammar",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"type": "module",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"start": "tauri dev",
|
||||
@@ -20,12 +21,23 @@
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.30.3",
|
||||
"devDependencies": {
|
||||
"@tauri-apps/cli": "^2.10.1",
|
||||
"@tauri-apps/cli": "^2.11.4",
|
||||
"vitepress": "2.0.0-alpha.17",
|
||||
"vue": "^3.5.30"
|
||||
"vue": "^3.5.39"
|
||||
},
|
||||
"dependencies": {
|
||||
"pdfjs-dist": "^5.5.207",
|
||||
"tauri-plugin-tts-api": "^0.1.3"
|
||||
"@supabase/supabase-js": "^2.110.5",
|
||||
"@tauri-apps/plugin-http": "2.6.0",
|
||||
"@types/better-sqlite3": "^9.6.0",
|
||||
"@types/markdown-it": "^14.2.0",
|
||||
"@types/node": "^24.13.3",
|
||||
"better-sqlite3": "^13.0.3",
|
||||
"kuromoji-ko": "^1.0.8",
|
||||
"markdown-it": "^14.3.0",
|
||||
"pdfjs-dist": "^5.7.284",
|
||||
"tauri-plugin-tts-api": "0.2.1",
|
||||
"vite": "^8.1.5",
|
||||
"yaml": "^2.9.0",
|
||||
"zod": "^4.4.3"
|
||||
}
|
||||
}
|
||||
Generated
+1194
-562
File diff suppressed because it is too large.
Load diff
@@ -1,2 +1,3 @@
|
||||
onlyBuiltDependencies:
|
||||
- better-sqlite3
|
||||
- esbuild
|
||||
@@ -0,0 +1,98 @@
|
||||
import sqlite3 from "better-sqlite3";
|
||||
import { MeCab } from "kuromoji-ko";
|
||||
import fs from "node:fs/promises";
|
||||
import yaml from "yaml";
|
||||
|
||||
const mecab = await MeCab.create({
|
||||
engine: "ko",
|
||||
dictPath: "./node_modules/kuromoji-ko/dict",
|
||||
});
|
||||
|
||||
const db = sqlite3(".sentence.db");
|
||||
db.exec(/* sql */ `
|
||||
CREATE TABLE IF NOT EXISTS sentence (
|
||||
ko TEXT NOT NULL,
|
||||
en TEXT,
|
||||
original TEXT NOT NULL,
|
||||
[url] TEXT NOT NULL,
|
||||
notes TEXT,
|
||||
filepath TEXT NOT NULL
|
||||
);
|
||||
|
||||
CREATE UNIQUE INDEX IF NOT EXISTS idx_sentence_u ON sentence(original, [url]);
|
||||
|
||||
CREATE VIRTUAL TABLE IF NOT EXISTS sentence_fts USING fts5 (
|
||||
ko,
|
||||
en,
|
||||
original UNINDEXED,
|
||||
[url] UNINDEXED,
|
||||
notes UNINDEXED,
|
||||
filepath UNINDEXED,
|
||||
content='sentence',
|
||||
tokenize='porter'
|
||||
);
|
||||
|
||||
-- Triggers to keep the FTS index up to date.
|
||||
CREATE TRIGGER IF NOT EXISTS t1_ai AFTER INSERT ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(rowid, ko, en) VALUES (new.rowid, new.ko, new.en);
|
||||
END;
|
||||
CREATE TRIGGER IF NOT EXISTS t1_ad AFTER DELETE ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(fts_idx, rowid, ko, en) VALUES('delete', old.rowid, old.ko, old.en);
|
||||
END;
|
||||
CREATE TRIGGER IF NOT EXISTS t1_au AFTER UPDATE ON sentence BEGIN
|
||||
INSERT INTO sentence_fts(fts_idx, rowid, ko, en) VALUES('delete', old.rowid, old.ko, old.en);
|
||||
INSERT INTO sentence_fts(rowid, ko, en) VALUES (new.rowid, new.ko, new.en);
|
||||
END;
|
||||
`);
|
||||
|
||||
const stmt = db.prepare(/* sql */ `
|
||||
INSERT OR IGNORE INTO sentence (ko, original, en, [url], notes, filepath)
|
||||
VALUES (:parsed, :ko, :en, :audio, :notes, :filepath)
|
||||
`);
|
||||
const tx = db.transaction((ss) => {
|
||||
for (const s of ss) {
|
||||
if (s.notes === "Gemini") continue;
|
||||
stmt.run({
|
||||
ko: s.ko.replaceAll("**", ""),
|
||||
parsed: mecab
|
||||
.parse(s.ko)
|
||||
.filter((t) => t.pos.some((p) => /^[NVM]/.test(p)))
|
||||
.map((t) => t.lemma)
|
||||
.join(" "),
|
||||
en: (s.en || "").replaceAll("**", ""),
|
||||
audio: s.audio || "",
|
||||
notes: Array.isArray(s.notes) ? s.notes.join("\n") : s.notes || null,
|
||||
filepath: s.filepath,
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const SEPARATOR = "---\n";
|
||||
|
||||
for await (const md of fs.glob("docs/**/*.md")) {
|
||||
let text = await fs.readFile(md, "utf-8");
|
||||
if (!text.startsWith(SEPARATOR)) continue;
|
||||
try {
|
||||
const ss = [];
|
||||
|
||||
const { vocabulary, sentence } =
|
||||
yaml.parse(text.slice(SEPARATOR.length).split(SEPARATOR, 1)[0]) || {};
|
||||
if (!vocabulary) continue;
|
||||
|
||||
for (const { examples = [] } of Object.values(vocabulary).flat(1)) {
|
||||
ss.push(...examples.map((o) => ({ ...o, filepath: md })));
|
||||
}
|
||||
|
||||
if (sentence) {
|
||||
ss.push(
|
||||
...Object.values(sentence)
|
||||
.flat(1)
|
||||
.map((o) => ({ ...o, filepath: md })),
|
||||
);
|
||||
}
|
||||
|
||||
tx(ss);
|
||||
} catch (e) {
|
||||
console.error(e, md);
|
||||
}
|
||||
}
|
||||
Generated
+1215
-1388
File diff suppressed because it is too large.
Load diff
@@ -23,4 +23,5 @@ serde = { version = "1.0", features = ["derive"] }
|
||||
log = "0.4"
|
||||
tauri = { version = "2.10.3", features = [] }
|
||||
tauri-plugin-log = "2"
|
||||
tauri-plugin-tts = "0.1.3"
|
||||
tauri-plugin-tts = "0.2.1"
|
||||
tauri-plugin-http = "2"
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
fn main() {
|
||||
tauri_build::build()
|
||||
tauri_build::build()
|
||||
}
|
||||
@@ -7,6 +7,10 @@
|
||||
],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"tts:default"
|
||||
"tts:default",
|
||||
{
|
||||
"identifier": "http:default",
|
||||
"allow": [{ "url": "https://api.deepseek.com/chat/completions" }]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
+1
@@ -62,6 +62,7 @@ dependencies {
|
||||
implementation("androidx.appcompat:appcompat:1.7.1")
|
||||
implementation("androidx.activity:activity-ktx:1.10.1")
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("androidx.lifecycle:lifecycle-process:2.10.0")
|
||||
testImplementation("junit:junit:4.13.2")
|
||||
androidTestImplementation("androidx.test.ext:junit:1.1.4")
|
||||
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.0")
|
||||
|
||||
@@ -1,11 +1,44 @@
|
||||
package cc.polv.ko_grammar
|
||||
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.webkit.WebView
|
||||
import androidx.activity.enableEdgeToEdge
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.core.view.ViewCompat
|
||||
import androidx.core.view.WindowInsetsCompat
|
||||
|
||||
class MainActivity : TauriActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
enableEdgeToEdge()
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
val rootView: View = findViewById(android.R.id.content)
|
||||
|
||||
ViewCompat.setOnApplyWindowInsetsListener(rootView) { v, insets ->
|
||||
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
|
||||
val imeVisible = insets.isVisible(WindowInsetsCompat.Type.ime())
|
||||
val imeHeight = insets.getInsets(WindowInsetsCompat.Type.ime()).bottom
|
||||
|
||||
val bottomPadding = if (imeVisible) imeHeight else systemBars.bottom
|
||||
|
||||
v.setPadding(
|
||||
systemBars.left,
|
||||
systemBars.top,
|
||||
systemBars.right,
|
||||
bottomPadding
|
||||
)
|
||||
insets
|
||||
}
|
||||
}
|
||||
|
||||
override fun onWebViewCreate(webView: WebView) {
|
||||
super.onWebViewCreate(webView)
|
||||
|
||||
webView.setBackgroundColor(0x00000000)
|
||||
|
||||
webView.fitsSystemWindows = true
|
||||
|
||||
android.util.Log.i("MainActivity", "WebView created, waiting for Rust hide() call...")
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
<resources>
|
||||
<string name="app_name">ko-grammar</string>
|
||||
<string name="main_activity_title">ko-grammar</string>
|
||||
<string name="app_name">"ko-grammar"</string>
|
||||
<string name="main_activity_title">"ko-grammar"</string>
|
||||
</resources>
|
||||
+15
-14
@@ -1,17 +1,18 @@
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_tts::init())
|
||||
.setup(|app| {
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
.level(log::LevelFilter::Info)
|
||||
.build(),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_http::init())
|
||||
.plugin(tauri_plugin_tts::init())
|
||||
.setup(|app| {
|
||||
if cfg!(debug_assertions) {
|
||||
app.handle().plugin(
|
||||
tauri_plugin_log::Builder::default()
|
||||
.level(log::LevelFilter::Info)
|
||||
.build(),
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
}
|
||||
@@ -2,5 +2,5 @@
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
fn main() {
|
||||
app_lib::run();
|
||||
app_lib::run();
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
// testCases.map(c=>mecab.parse(c.sentence).filter(t=>t.pos.some(p=>/^[NVM]/.test(p))).map(t=>t.lemma));
|
||||
export const testCases = [
|
||||
{
|
||||
sentence: "학교에서 공부했어요",
|
||||
expected: ["학교", "공부"],
|
||||
},
|
||||
{
|
||||
sentence: "맛있는 김치찌개를 먹었어요",
|
||||
expected: ["맛있다", "김치찌개", "먹다"],
|
||||
},
|
||||
{
|
||||
sentence: "사랑하는 가족에게 선물을 줬어요",
|
||||
expected: ["사랑", "가족", "선물", "주다"],
|
||||
},
|
||||
{
|
||||
sentence: "빨리 달려가자",
|
||||
expected: ["빨리", "달려가다"],
|
||||
},
|
||||
{
|
||||
sentence: "예쁜 꽃이 피었어요",
|
||||
expected: ["예쁘다", "꽃", "피다"],
|
||||
},
|
||||
{
|
||||
sentence: "그는 학교에 갔다",
|
||||
expected: ["그", "학교", "가다"],
|
||||
},
|
||||
{
|
||||
sentence: "열심히 공부하는 학생입니다",
|
||||
expected: ["열심히", "공부", "학생", "이다"],
|
||||
},
|
||||
{
|
||||
sentence: "어제 영화를 봤어요",
|
||||
expected: ["어제", "영화", "보다"],
|
||||
},
|
||||
];
|
||||
Reference in new issue
Block a user