컨텍스트와 동의 이 페이지는 영어에서 번역되었습니다. 두 내용이 다를 경우 영어 페이지가 정확합니다. 영어 페이지 읽기
앱은 오직 컨텍스트 슬라이스를 통해서만 학습자에 대해 알 수 있습니다. 각 슬라이스는 고정된 필드를 가진 작은 레코드입니다. 매니페스트에 요청할 슬라이스를 나열하면, 학습자는 앱을 설치할 때 각 슬라이스에 동의하며, Lingara는 두 조건이 모두 유지되는 동안에만 슬라이스를 보냅니다.
슬라이스
슬라이스 필드 담긴 내용 languagessource_lang학습자가 학습의 기준으로 삼는 언어로, en과 같은 언어 태그입니다. target_lang학습자가 배우고 있는 언어. level그 언어에서의 레벨로, 1부터 9까지이며 학습자가 설정한 경우에만 있습니다. plan_summaryplan_id학습자의 최신 수업 계획 ID로, 계획을 서로 구별하는 데 쓰입니다. 앱은 이 ID로 계획을 가져올 수 없습니다. 앱의 토큰은 학습자의 계정이 아니라 개발자 본인의 계정을 읽기 때문입니다. title생성된 계획 제목으로, 최대 120자이며 제목이 있는 경우에만 있습니다. target_lang계획이 가르치는 언어. set_count계획에 포함된 세트 수로, 최대 200입니다. sets_completed그중 학습자가 완료한 세트 수. review_duedue지금 복습할 플래시카드 수로, 최대 100000입니다. learned학습자가 익힌 단어 수로, 최대 100000입니다. tutor_topictopic학습자의 최신 튜터 채팅 주제로, 1자에서 120자까지입니다. 계획의 제목이나 학습자가 보고 있는 화면에서 가져오며, 학습자가 직접 쓴 말에서 가져오는 일은 절대 없습니다.
어떤 슬라이스에도 없는 것
어떤 슬라이스에도 이메일 주소, 이름, 사용자 ID, 학습자가 입력한 내용은 담기지 않습니다. 앱은 요청의 subject를 통해 학습자가 누구인지 알 수 있으며, 이 값은 안정적이고 앱마다 다릅니다. 앱의 토큰은 개발자 본인의 계정을 읽을 뿐 학습자의 계정은 절대 읽지 않으므로, 앱이 학습자에 대해 아는 것은 슬라이스가 전부입니다.
동의
학습자는 앱을 설치할 때 각 슬라이스에 동의합니다. 동의한 내용을 바꾸려면 앱을 제거한 뒤 다시 설치합니다.
매니페스트를 수정해 요청하는 슬라이스를 줄이면, 제외한 슬라이스는 즉시 전송이 중단됩니다.
매니페스트를 수정해 요청하는 슬라이스를 늘리면, 새 슬라이스는 학습자가 다시 설치할 때까지 어떤 학습자에게도 전달되지 않습니다.
Lingara는 요청마다 동의를 다시 확인하고, 학습자가 동의하지 않았거나 매니페스트가 더 이상 요청하지 않는 슬라이스를 버립니다. 레코드에 맞지 않는 슬라이스도 버려지지만, 요청 전체가 버려지는 일은 없습니다.
아래 샘플은 전달받은 슬라이스로 한 줄을 만들며 API는 호출하지 않습니다.
코드 예제 언어 TypeScript Rust Go Java Kotlin Ruby PHP TypeScript
// The app's own client reads its owner's account, never the learner's. The
// slices are all a render knows about the learner.
function planLine ( request : AppRenderRequest ) : string {
let line = "" ;
for ( const slice of request.context) {
// A slice is present only when the learner agreed to share it.
if (slice.kind === "languages" ) line += `${ slice . source_lang } → ${ slice . target_lang }. ` ;
if (slice.kind === "plan_summary" ) line += `${ slice . sets_completed }/${ slice . set_count } sets.` ;
}
return line;
} Rust
// The app's own client reads its owner's account, never the learner's. The
// slices are all a render knows about the learner.
/// The learner's target language and, when they shared their plan, its
/// `(sets_completed, set_count)`.
fn shared_plan (request : & AppRenderRequest ) -> ( String , Option <( u32 , u32 )>) {
let ( mut target_lang, mut progress) = ( String :: from ( "zh" ), None );
for slice in & request . context {
match slice {
ContextSlice :: Languages (languages) => target_lang = languages . target_lang . clone (),
ContextSlice :: PlanSummary (summary) => progress = Some ((summary . sets_completed, summary . set_count)),
_ => {}
}
}
(target_lang, progress)
} Go
// The app's own client reads its owner's account, never the learner's.
// The slices are all a render knows about the learner.
//
// Each slice is present only when the learner agreed to share it.
card := lingaraapps. NewCard (). Heading ( "Your plan" , 1 )
for _, slice := range req.Context {
switch s := slice.( type ) {
case lingaraapps . ContextSliceLanguages :
card. Text (fmt. Sprintf ( "Learning %s from %s " , s.TargetLang, s.SourceLang))
case lingaraapps . ContextSlicePlanSummary :
card. Text (fmt. Sprintf ( " %d of %d sets done" , s.SetsCompleted, s.SetCount))
}
} Java
import com.getlingara.apps.Card;
import com.getlingara.apps.Reply;
import com.getlingara.apps.model.AppRenderRequest;
import com.getlingara.apps.model.ContextSlice;
import com.getlingara.apps.model.ContextSliceLanguages;
import com.getlingara.apps.model.ContextSlicePlanSummary;
// The app's own client reads its owner's account, never the learner's. The slices are all a
// render knows about the learner.
static Reply render (AppRenderRequest request) {
Card.Builder card = Card. card ();
// A slice is present only when the learner agreed to share it; the context is read-only.
for (ContextSlice slice : request. getContext ()) {
if (slice instanceof ContextSliceLanguages languages) {
card. heading ( "Learning " + languages. targetLang (), 1 );
} else if (slice instanceof ContextSlicePlanSummary summary) {
card. text (summary. setsCompleted () + " of " + summary. setCount () + " sets done" );
}
}
return card. heading ( "Today" , 2 ). build ();
} Kotlin
import com.getlingara.apps.kotlin.Reply
import com.getlingara.apps.kotlin.card
import com.getlingara.apps.kotlin.model.AppRenderRequest
import com.getlingara.apps.kotlin.model.ContextSliceLanguages
import com.getlingara.apps.kotlin.model.ContextSlicePlanSummary
// The app's own client reads its owner's account, never the learner's. The slices are all a
// render knows about the learner.
fun renderWithContext (request: AppRenderRequest ): Reply {
// A slice is present only when the learner agreed to share it; the context is read-only.
val languages = request.context. filterIsInstance < ContextSliceLanguages >(). firstOrNull ()
val summary = request.context. filterIsInstance < ContextSlicePlanSummary >(). firstOrNull ()
return card {
heading ( "Learning ${languages?.targetLang ?: "today"}" , 1 )
if (summary != null ) {
text ( "${summary.setsCompleted} of ${summary.setCount} sets done" )
}
}
} Ruby
# The app's own client reads its owner's account, never the learner's. The
# slices are all a render knows about the learner.
#
# A slice is present only when the learner agreed to share it.
request. context . filter_map do |slice|
case slice
in Lingara :: Apps :: ContextSliceLanguages ( source_lang: , target_lang: )
" #{source_lang} → #{target_lang} ."
in Lingara :: Apps :: ContextSlicePlanSummary ( sets_completed: , set_count: )
" #{sets_completed} / #{set_count} sets."
else nil
end
end . join ( " " ) PHP
use Lingara\Apps\Generated\ContextSliceLanguages ;
use Lingara\Apps\Generated\ContextSlicePlanSummary ;
function planLine ( AppRenderRequest $request) : string
{
// The app's own client reads its owner's account, never the learner's. The
// slices are all a render knows about the learner.
$line = '' ;
// A slice is present only when the learner agreed to share it.
foreach ($request -> getContext () as $slice) {
if ($slice instanceof ContextSliceLanguages ) {
$line .= "{ $slice -> sourceLang } → { $slice -> targetLang }. " ;
} elseif ($slice instanceof ContextSlicePlanSummary ) {
$line .= "{ $slice -> setsCompleted }/{ $slice -> setCount } sets." ;
}
}
return $line;
}