Lingara Lingara Documentation Guides API Bibliothèques Applications Créer Application web
Langue: Français

Contexte et consentement

Cette page est traduite de l'anglais. En cas de différence, la page anglaise fait foi. Lire la page en anglais

Votre application n’apprend quelque chose sur un apprenant qu’au travers de tranches de contexte. Chaque tranche est un petit enregistrement aux champs fixes. Votre manifeste liste les tranches qu’il demande, l’apprenant accepte chacune d’elles lorsqu’il installe votre application, et Lingara n’envoie une tranche que tant que ces deux conditions restent remplies.

Les tranches

TrancheChampCe qu’il contient
languagessource_langLa langue à partir de laquelle l’apprenant étudie, sous forme d’étiquette de langue comme en.
target_langLa langue qu’il apprend.
levelSon niveau dans cette langue, de 1 à 9, lorsqu’il en a défini un.
plan_summaryplan_idL’identifiant de son dernier plan de cours, qui distingue un plan d’un autre. Votre application ne peut pas récupérer le plan avec cet identifiant, car le jeton de votre application lit votre propre compte, pas celui de l’apprenant.
titleLe titre généré du plan, d’au plus 120 caractères, lorsqu’il en a un.
target_langLa langue qu’enseigne le plan.
set_countLe nombre de séries que compte le plan, au plus 200.
sets_completedLe nombre de ces séries que l’apprenant a terminées.
review_duedueLe nombre de cartes mémoire dues maintenant, au plus 100000.
learnedLe nombre de mots qu’il a appris, au plus 100000.
tutor_topictopicLe sujet de sa dernière conversation avec le tuteur, de 1 à 120 caractères. Il provient du titre d’un plan ou de l’écran où il se trouve, jamais de ses propres mots.

Ce qu’aucune tranche ne transporte

Aucune tranche ne transporte d’adresse e-mail, de nom, d’identifiant utilisateur ni quoi que ce soit que l’apprenant a saisi. Votre application apprend qui est l’apprenant grâce au subject de la requête, une valeur stable qui est différente pour chaque application. Le jeton de votre application lit votre propre compte, jamais celui de l’apprenant, si bien que les tranches sont tout ce que votre application sait de lui.

Consentement

  • L’apprenant accepte chaque tranche lorsqu’il installe votre application. Pour modifier ce qu’il a accepté, il désinstalle votre application puis l’installe à nouveau.
  • Si vous modifiez votre manifeste pour demander moins de tranches, celles que vous avez retirées s’arrêtent immédiatement.
  • Si vous le modifiez pour en demander davantage, les nouvelles tranches n’atteignent aucun apprenant tant qu’il n’a pas réinstallé l’application.
  • Lingara vérifie de nouveau le consentement à chaque requête, et abandonne toute tranche que l’apprenant n’a pas acceptée ou que votre manifeste ne demande plus. Une tranche qui ne correspond pas à son enregistrement est également abandonnée, jamais la requête entière.

L’exemple ci-dessous construit sa ligne à partir des tranches qu’il a reçues et n’appelle aucune API.

Langage de l'exemple de code

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

Voir aussi