Lingara Lingara Belge Rêbername API Pirtûkxane Sepan Avakirin Bicihkirin Sepana webê
Ziman: Kurdî

Widget-a malperê

Ev rûpel ji Îngilîzî hatiye wergerandin. Heke her du ji hev cuda bin, rûpela Îngilîzî rast e. Rûpela Îngilîzî bixwîne

Li ser malperekê, Lingara wek hêmaneke taybet, <lingara-embed>, dixebite. Hêman temrîna Lingara di çarçoveyeke ku Lingara pêşkêş dike de dikişîne, ji ber vê yekê rûpela te qet daneyên xwendekar nabîne û rûpela Lingara qet yên te nabîne.

Hêmanê bicih bike

@lingara/embed ji npm saz bike, an heke malpera te bundler tune be avakirina wê ya modulê ji CDN-ekê bar bike. Paşê <lingara-embed> têxe ser rûpelê û wê pênase bike. Hêman van digire:

  • plan-id, plana dersê ya ku were temrînkirin, yeke ku lîstikvan xwedî wê ye;
  • surface, çi nîşan bide: practice, ya pêşdanasîn û tekane rûyê ku heye;
  • theme, yek ji light, dark an auto;
  • locale, zimanê peyvên çarçoveyê bi xwe, ku wekî din li dû xwendekar diçe;
  • title, navê gihîştbar ê çarçoveyê.

Şêwekirin li temayê disekine. Rûpela te nikare bigihîje hundirê çarçoveyê, û tema tekane mîhenga ku ew pêşkêş dike ye.

Tokenan bide wê

tokenProvider-a hêmanê bike fonksiyoneke ku ji servera te bi xwe tokenekê dixwaze. Servera te wê bi origin-a rûpelê çêdike, bi kîta serverê, û bi token û dema qedandina wê bersiv dide. Hêman tokenê bi peyamekê radestî çarçoveyê dike, û ew qet di URL-ê de naçe.

Her origin-a ku widget li ser dixebite berî ku tu ji bo wê tokenê çêkî tomar bike, di mîhengên klientê xwe de di konsolê de. Rûpela kîtên serverê dibêje çawa. API tokeneke ku ji bo origin-eke din hatiye çêkirin red dike, û çarçove li şûna temrînê xeletiyekê nîşan dide.

Kîteke serverê dikare tevahiya parçeyê kodê jî ji te re binivîse, hêman û peydakerê tokenê bi hev re, bi nonce-a skrîpta rûpela te heke siyaseta ewlehiya naveroka te yekê hewce bike. Nimûneya dawî ya li jêr wê nîşan dide.

Guh bide tiştê ku çarçove dibêje

Çarçove bi hêmanê re bi protokoleke peyaman a guhertoyî diaxive, û hêman tiştên ku rûpela te hewce dike dike bûyerên DOM:

  • lingara:practice-completed dema ku xwendekar komekê temam dike, bi planId, setNumber, correct û total-a wê;
  • lingara:error dema ku çarçove radiweste, bi code û retryable. Xeletiyeke ku dikare dîsa were ceribandin tê wê wateyê ku bicihkirineke nû dibe ku serkeve; kengê dîsa biceribînî biryara te ye.

Encama temrînê jî digihîje servera te, wek ku di encamên temrînê de hatiye ravekirin.

npm install @lingara/embed@0.1.0-alpha.6
# No bundler? One module script instead:
# <script type="module" src="https://cdn.jsdelivr.net/npm/@lingara/embed@0.1.0-alpha.6/dist/lingara-embed.min.js"></script>
<!-- plan-id is a lesson plan your server made for this player. -->
<lingara-embed surface="practice" plan-id="0b9d4f2e-3c1a-4e8b-9f6d-2a7c5e1b8d40" theme="auto" title="Practice"></lingara-embed>
<script type="module">
  import { defineLingaraEmbed } from '@lingara/embed'
  defineLingaraEmbed()
</script>
// Your own endpoint, on your own server. It mints with this page's origin and
// returns exactly { token, expires_at }: the token (lgr_et_…) never touches a URL.
widget.tokenProvider = async () => {
  const response = await fetch('/lingara/token', { method: 'POST', credentials: 'same-origin' })
  if (!response.ok) throw new Error(`token endpoint answered ${response.status}`)
  return response.json()
}
widget.addEventListener('lingara:practice-completed', (event) => {
  const { planId, setNumber, correct, total } = (event as CustomEvent).detail
  console.log(`set ${setNumber} of ${planId}: ${correct}/${total}`)
})
widget.addEventListener('lingara:error', (event) => {
  const { code, retryable } = (event as CustomEvent).detail
  // `retryable` means a remount may succeed; when to try is yours to decide.
  if (retryable) setTimeout(() => widget.reload(), 30_000)
  else console.warn('Lingara practice stopped:', code)
})
Zimanê mînaka kodê

TypeScript

// The page that mounts the widget: the token never appears in it.
export function practicePage(planId: string, cspNonce: string): string {
  const widget = widgetSnippet({ planId, tokenEndpoint: '/lingara/token', theme: 'auto', locale: 'fr', title: 'Pratique', nonce: cspNonce })
  return `<!doctype html><title>Practice</title>${widget}`
}

Rust

// The element, its script build and a token provider that POSTs to your
// token route. The token never appears in the markup.
let html = widget_snippet(&SnippetOptions {
    locale: Some("fr".into()),
    nonce: Some(csp_nonce.into()), // your page's CSP nonce, for a strict script-src
    ..SnippetOptions::new(plan_id, "/lingara/token")
})?;

Go

// The plan your server made for this player, and the token route above.
// Pass the request's CSP nonce when your script-src allows no inline
// script; the token itself never appears in the markup.
theme := "auto"
html, err := lingaraembed.WidgetSnippet(lingaraembed.SnippetOptions{
	PlanID:        planID,
	TokenEndpoint: "/lingara/token",
	Theme:         &theme,
	Nonce:         &cspNonce,
})
if err != nil {
	return "", err // a *lingaraembed.SnippetError names the refused option
}
return template.HTML(html), nil // already escaped by the kit

Java

// planId is the lesson plan your server made for this player. The element
// POSTs to tokenEndpoint with same-origin cookies: the token never appears
// in the markup. Pass this request's CSP nonce if your page sets one.
String html =
    WidgetSnippet.render(
        SnippetOptions.builder(planId, "/lingara/token").locale("fr").nonce(cspNonce).build());

Kotlin

// planId is the lesson plan your server made for this player. The element
// POSTs to tokenEndpoint with same-origin cookies: the token never appears
// in the markup. Pass this request's CSP nonce if your page sets one.
val html =
    widgetSnippet(
        SnippetOptions(planId, tokenEndpoint = "/lingara/token").apply {
            locale = "fr"
            nonce = cspNonce
        },
    )

Ruby

# The plan your server made for this player, rendered into your page.
# nonce: your page's CSP nonce, when its script-src allows no inline script.
def self.widget(plan_id, csp_nonce)
  Lingara::Embed.widget_snippet(plan_id: plan_id, token_endpoint: "/lingara/token", locale: "fr", nonce: csp_nonce)
end

PHP

use Lingara\Embed\SnippetOptions;
use Lingara\Embed\WidgetSnippet;

// In your page's template: the plan your server made for this player, and
// your token route. Pass the request's CSP nonce if your script-src allows
// no inline script. A bad option throws SnippetException naming its field.
function practiceWidget(string $planId, string $cspNonce): string
{
    return WidgetSnippet::render(new SnippetOptions(
        planId: $planId,
        tokenEndpoint: '/lingara/token',
        theme: 'auto',
        nonce: $cspNonce,
    ));
}

C#

app.MapGet("/practice/{planId}", (string planId, HttpContext http) =>
{
    var widget = WidgetSnippet.Render(new SnippetOptions
    {
        PlanId = planId,                              // the plan your server made for this player
        TokenEndpoint = "/lingara/token",             // same origin: the element sends this page's cookies
        Nonce = http.Items["csp-nonce"] as string,     // your CSP's nonce, if script-src has one
    });
    return Results.Content($"<!doctype html><title>Practice</title>\n{widget}", "text/html");
}).RequireAuthorization();