Lingara Lingara ドキュメント 学習ガイド API ライブラリ アプリ 作成 ウェブ版
言語: 日本語

カード

このページは英語から翻訳されています。内容に相違がある場合は、英語のページが正しい内容です。 英語のページを読む

カードは、Lingara が独自のスタイルで描画する短い要素のリストです。入力欄、画像、スクリプト、マークアップはありません。アプリが学習者の画面に独自のコードや独自の見た目を持ち込むことはできないため、どのカードも Lingara の他の部分と同じように見えます。応答は JSON です。card がその elements を保持し、任意で tutor_note を含められます(チューターへのメモを参照)。

要素

各要素には type があり、次の 8 つのいずれかです:

要素フィールド表示内容
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 が正しい文字体系で描画するためのものです。言語タグではない値は削除されます。

制限

  • 1 枚のカードに含められる要素は最大 24 個です。24 番目より後の要素は破棄されます。
  • 1 つのリストに含められる項目は最大 20 個です。20 番目より後の項目は破棄され、空のリストも破棄されます。
  • 1 枚のカードに含められるボタンは最大 4 個です。4 番目より後のボタンは破棄されます。
  • 制限より長いテキストは収まるように切り詰められ、末尾が … になります。文字数は Unicode スカラー値として数えます。
  • 制御文字と方向オーバーライドは、すべての文字列から削除されます。
  • アドレスが HTTPS でないリンク、ユーザー名を含むリンク、IP アドレスを指すリンクは破棄されます。
  • action が 64 文字を超えるボタン、または英字、数字、_、.、:、- 以外を使うボタンは破棄されます。
  • これらのルールを適用した結果、テキストが何も残らない要素は破棄されます。

これらのルールは寛容です。Lingara は収まらない部分を切り詰めたり破棄したりして、残りを描画します。キットは応答する前に同じルールを適用するので、何が変わるかを確認できます。

厳密な解析

語彙は閉じています。未知の要素タイプ、要素が持たないフィールド、JSON の型が誤った値、あるいはそもそも JSON ではない応答があると、応答全体がフォールバックになります。Lingara は、読み取れなかったカードの一部だけを描画することはありません。

サイズと時間

応答は最大 32 KiB です。Lingara はサーバーに対し、レンダーへの応答に 3 秒、アクションへの応答に 5 秒の猶予を与え、どちらも再試行しません。応答はステータス 200 で、JSON のコンテンツタイプである必要があります。リダイレクトはたどりません。

ボタンとアクション

学習者がボタンを押すと、Lingara はそのボタンの action を含むアクションリクエストをサーバーに送ります。サーバーは新しいカードで応答し、それが古いカードを置き換えます。同じ押下が 2 回届くこともあるため、各アクションは繰り返しても安全なようにしてください。

カードが失敗したとき

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.
}