Lingara Lingara 문서 학습 가이드 API 라이브러리 앱 만들기 웹 앱
언어: 한국어

카드

이 페이지는 영어에서 번역되었습니다. 두 내용이 다를 경우 영어 페이지가 정확합니다. 영어 페이지 읽기

카드는 Lingara가 자체 스타일로 그리는 짧은 요소 목록입니다. 입력란, 이미지, 스크립트, 마크업은 없습니다. 앱은 학습자의 화면에 자체 코드나 자체 디자인을 넣을 수 없으므로, 모든 카드는 Lingara의 나머지 부분과 똑같이 보입니다. 응답은 JSON입니다. card가 elements를 담고, 선택적으로 tutor_note를 포함합니다(튜터 메모 참고).

요소

각 요소에는 type이 있으며, 다음 여덟 가지 중 하나입니다.

요소필드표시 내용
headingtext, level제목. level은 1 또는 2이며, 다른 값은 2가 됩니다. 텍스트는 최대 80자입니다.
texttext, lang최대 600자의 문단. 줄바꿈이 유지되는 유일한 곳입니다.
termword, reading, gloss, lang학습할 단어. word만 필수입니다. 단어는 최대 60자, 읽기는 120자, 뜻풀이는 160자입니다.
listitems최대 20개 항목. 각 항목은 text 또는 term이며, 같은 이름의 요소와 같은 필드를 가집니다.
progressvalue, label진행 막대. value는 0부터 1까지이며, 레이블은 최대 60자입니다.
divider카드의 각 부분 사이의 선.
buttonlabel, action, styleaction을 서버로 보내는 버튼. style은 primary 또는 secondary이며, 레이블은 최대 32자입니다.
linklabel, urlLingara가 학습자에게 확인한 뒤 학습자가 브라우저에서 여는 링크. 레이블은 최대 60자입니다.

lang은 ja와 같은 언어 태그로, Lingara가 올바른 문자로 그리도록 합니다. 언어 태그가 아닌 값은 제거됩니다.

제한

  • 카드에는 최대 24개의 요소가 들어갑니다. 24번째 이후의 요소는 버려집니다.
  • 목록에는 최대 20개의 항목이 들어갑니다. 20번째 이후의 항목은 버려지며, 빈 목록도 버려집니다.
  • 카드에는 최대 4개의 버튼이 들어갑니다. 4번째 이후의 버튼은 버려집니다.
  • 제한보다 긴 텍스트는 길이에 맞게 잘리고 …로 끝납니다. 문자는 Unicode 스칼라 값으로 셉니다.
  • 모든 문자열에서 제어 문자와 방향 재정의 문자가 제거됩니다.
  • 주소가 HTTPS가 아니거나, 사용자 이름을 포함하거나, IP 주소를 가리키는 링크는 버려집니다.
  • action이 64자보다 길거나 문자, 숫자, _, ., :, - 이외의 것을 사용하는 버튼은 버려집니다.
  • 이 규칙들을 적용한 뒤 텍스트가 남지 않은 요소는 버려집니다.

이 규칙들은 관대합니다. Lingara는 맞지 않는 부분을 자르거나 버리고 나머지를 그립니다. 키트는 응답하기 전에 같은 규칙을 적용하므로, 무엇이 바뀔지 확인할 수 있습니다.

엄격한 파싱

어휘는 닫혀 있습니다. 알 수 없는 요소 타입, 요소에 없는 필드, 잘못된 JSON 타입의 값, 또는 아예 JSON이 아닌 응답은 응답 전체를 대체 카드로 바꿉니다. Lingara는 읽을 수 없었던 카드의 일부만 그리는 일이 절대 없습니다.

크기와 시간

응답은 최대 32 KiB입니다. Lingara는 서버에 렌더 응답에 3초, 액션 응답에 5초를 주며, 둘 다 재시도하지 않습니다. 응답은 상태 200이어야 하고 JSON 콘텐츠 타입이어야 합니다. 리디렉션은 따르지 않습니다.

버튼과 액션

학습자가 버튼을 누르면, Lingara는 그 버튼의 action을 담은 액션 요청을 서버로 보냅니다. 서버는 새 카드로 응답하고, 새 카드가 이전 카드를 대체합니다. 같은 누름이 두 번 도착할 수 있으므로, 각 액션은 반복해도 안전하게 만드세요.

카드가 실패했을 때

Lingara가 그릴 수 있는 카드를 받지 못하면, 학습자에게는 Lingara 자체의 “이 앱이 응답하지 않았습니다” 카드가 학습자의 언어로 표시되거나, “최신 상태 아님”으로 표시된 마지막 정상 카드가 표시됩니다. 학습자에게는 그 이유가 절대 전달되지 않습니다. 이유는 앱 소유자인 여러분만 볼 수 있습니다.

  • 응답: invalid(Lingara가 읽을 수 있는 카드가 아님), empty(제한을 적용한 뒤 표시할 것이 남지 않음) 또는 too_large(32 KiB 초과).
  • 서버 연결: timeout, http_error(200 이외의 모든 상태), transport(만료된 인증서 등 연결 또는 TLS 실패) 또는 blocked(사설 주소나 IP 리터럴 주소로 이어지는 render_url).
  • Lingara 측: unavailable(Lingara가 요청에 서명할 수 없었음) 또는 busy(이미 처리 중인 요청이 너무 많음).
코드 예제 언어

TypeScript

function todayCard(streak: number): Card {
  return card()
    .heading("Today's five", 1)
    .term({ word: "雨", reading: "yǔ", gloss: "rain", lang: "zh" })
    .list([item.text("Review 3 words"), item.term({ word: "二", reading: "èr" })])
    .button(`Done (${streak})`, "done")
    .build(); // Throws CardLimitError naming the rule the relay would clamp.
}

Rust

fn today_card(title: &str, lang: &str) -> Result<lingara_apps::Card, BoxError> {
    Ok(card()
        .heading(title, 1)
        .term(Term::new("雨").reading("yǔ").gloss("rain").lang(lang))
        .list([item::text("Say it aloud"), item::term(Term::new("下雨").gloss("to rain"))])
        .button("Next word", "next")
        .build()?)
}

Go

card, err := lingaraapps.NewCard().
	Heading("Today", 1).
	Term(lingaraapps.Term{Word: "雨", Reading: "yǔ", Gloss: "rain", Lang: "zh"}).
	List(
		lingaraapps.Item.Text("Say it aloud three times."),
		lingaraapps.Item.Term(lingaraapps.Term{Word: "雨天", Gloss: "rainy day", Lang: "zh"}),
	).
	Button("Next", "next").
	Build()
if err != nil {
	// A *lingaraapps.CardLimitError names the rule the card breaks,
	// such as text_length or list_items. Nothing is cut for you.
	return lingaraapps.Card{}, err
}

Java

import com.getlingara.apps.Card;
import com.getlingara.apps.Item;

Card card =
    Card.card()
        .heading("Today's five", 1)
        .term("雨", "yǔ", "rain", "zh")
        .list(Item.text("Say it aloud"), Item.term("二", "èr", "two", "zh"))
        .button("Next", "next")
        .build(); // a CardLimitException names the first rule the card breaks

Kotlin

import com.getlingara.apps.kotlin.Card
import com.getlingara.apps.kotlin.card

val c =
    card {
        heading("Today's five", 1)
        term("雨", reading = "yǔ", gloss = "rain", lang = "zh")
        list(item.text("Say it aloud"), item.term("二", reading = "èr", gloss = "two", lang = "zh"))
        button("Next", "next")
    } // a CardLimitException names the first rule the card breaks

Ruby

def self.today_card(streak)
  Lingara::Apps.card
    .heading("Today's five", 1)
    .term(word: "雨", reading: "yǔ", gloss: "rain", lang: "zh")
    .list([Lingara::Apps.item.text("Review 3 words"), Lingara::Apps.item.term(word: "二", reading: "èr")])
    .button("Done (#{streak})", "done")
    .build # Raises Lingara::Apps::CardLimitError naming the rule Lingara would clamp.
end

PHP

use Lingara\Apps\Card;
use Lingara\Apps\Generated\Card as CardModel;
use Lingara\Apps\Item;

function todayCard(int $streak): CardModel
{
    return Card::create()
        ->heading("Today's five", 1)
        ->term('雨', reading: 'yǔ', gloss: 'rain', lang: 'zh')
        ->list([Item::text('Review 3 words'), Item::term('二', reading: 'èr')])
        ->button("Done ({$streak})", 'done')
        ->build(); // Throws CardLimitException naming the rule the relay would clamp.
}