Lingara Lingara 說明文件 學習指南 API 程式庫 App 建立 網頁版
語言: 粵語

卡片

呢頁係由英文翻譯過嚟嘅。如果兩個版本有出入,以英文頁為準。 睇英文頁

一張卡片係一串簡短嘅元素,由 Lingara 用佢自己嘅風格畫出嚟。入面冇輸入欄、冇圖片、冇指令碼,亦冇標記。App 冇辦法將自己嘅程式碼或者自己嘅外觀放上學習者個螢幕,所以每張卡片睇落都同 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, style一個會將佢嘅 action 傳去你部伺服器嘅按鈕。style 係 primary 或者 secondary,標籤最多 32 個字元。
linklabel, url一條連結,Lingara 問過學習者之後,就喺佢嘅瀏覽器打開。標籤最多 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 自己用佢哋語言顯示嘅「呢個 App 冇回應」卡片,或者你上一張正常嘅卡片,標住「唔係最新」。學習者永遠唔會知道原因。淨係你,作為個 App 嘅擁有人,先睇到原因:

  • 你嘅回覆:invalid(唔係 Lingara 睇得明嘅卡片)、empty(套用限制之後冇嘢剩低可以顯示)或者 too_large(超過 32 KiB)。
  • 連去你部伺服器:timeout、http_error(200 以外嘅任何狀態)、transport(連線或者 TLS 失敗,例如證書過咗期)或者 blocked(render_url 指去一個私人地址或者 IP 字面地址)。
  • 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.
}