Lingara Lingara ឯកសារ មគ្គុទ្ទេសក៍សិក្សា API បណ្ណាល័យ កម្មវិធី បង្កើត បង្កប់ កម្មវិធីលើបណ្ដាញ
ភាសា: ខ្មែរ

វិដជិតគេហទំព័រ

ទំព័រនេះត្រូវបានបកប្រែពីភាសាអង់គ្លេស។ ប្រសិនបើទាំងពីរខុសគ្នា ទំព័រភាសាអង់គ្លេសគឺត្រឹមត្រូវ។ អានទំព័រភាសាអង់គ្លេស

នៅលើគេហទំព័រ Lingara ដំណើរការជាធាតុផ្ទាល់ខ្លួន (custom element) មួយ <lingara-embed>។ ធាតុនេះគូរការហាត់របស់ Lingara នៅក្នុងស៊ុម (frame) មួយដែលបម្រើដោយ Lingara ដូច្នេះទំព័ររបស់អ្នកមិនដែលឃើញទិន្នន័យរបស់អ្នករៀនទេ ហើយទំព័ររបស់ Lingara ក៏មិនដែលឃើញទិន្នន័យរបស់អ្នកដែរ។

ដាក់ធាតុ

ដំឡើង @lingara/embed ពី npm ឬផ្ទុកកំណែម៉ូឌុលរបស់វាពី CDN ប្រសិនបើគេហទំព័ររបស់អ្នកគ្មាន bundler។ បន្ទាប់មកដាក់ <lingara-embed> នៅលើទំព័រ ហើយកំណត់វា។ ធាតុនេះទទួល៖

  • plan-id ផែនការមេរៀនដែលត្រូវហាត់ ដែលជាផែនការមួយដែលអ្នកលេងជាម្ចាស់។
  • surface អ្វីដែលត្រូវបង្ហាញ៖ practice ដែលជាលំនាំដើម និងជាផ្ទៃតែមួយគត់ដែលមាន។
  • theme មួយក្នុងចំណោម light, dark ឬ auto។
  • locale ភាសានៃពាក្យផ្ទាល់ខ្លួនរបស់ស៊ុម ដែលបើមិនកំណត់ទេ នឹងធ្វើតាមអ្នករៀន។
  • title ឈ្មោះដែលអាចចូលប្រើបាន (accessible name) របស់ស៊ុម។

ការកំណត់រចនាប័ទ្មឈប់ត្រឹមស្បែក (theme)។ ទំព័ររបស់អ្នកមិនអាចចូលទៅក្នុងស៊ុមបានទេ ហើយស្បែកគឺជាការកំណត់តែមួយគត់ដែលវាផ្ដល់ឲ្យ។

ផ្ដល់តូខិនឲ្យវា

កំណត់ tokenProvider របស់ធាតុ ទៅជាអនុគមន៍មួយដែលសុំតូខិនពីម៉ាស៊ីនមេផ្ទាល់ខ្លួនរបស់អ្នក។ ម៉ាស៊ីនមេរបស់អ្នកបង្កើតតូខិននោះជាមួយប្រភពដើម (origin) របស់ទំព័រ ដោយប្រើ កញ្ចប់ឧបករណ៍ម៉ាស៊ីនមេ ហើយឆ្លើយតបដោយតូខិន និងពេលផុតកំណត់របស់វា។ ធាតុប្រគល់តូខិនទៅស៊ុមតាមរយៈសារ ហើយវាមិនដែលធ្វើដំណើរនៅក្នុង URL ឡើយ។

ចុះឈ្មោះប្រភពដើមទាំងអស់ដែលវិដជិតដំណើរការលើ មុនពេលអ្នកបង្កើតតូខិនសម្រាប់វា នៅក្នុងការកំណត់នៃក្លាយអិនរបស់អ្នកនៅក្នុងកុងសូល។ ទំព័រ កញ្ចប់ឧបករណ៍ម៉ាស៊ីនមេ ប្រាប់ពីរបៀប។ API បដិសេធតូខិនដែលបានបង្កើតសម្រាប់ប្រភពដើមផ្សេងទៀតណាមួយ ហើយស៊ុមបង្ហាញកំហុសមួយជំនួសឲ្យការហាត់។

កញ្ចប់ឧបករណ៍ម៉ាស៊ីនមេក៏អាចសរសេរ snippet ទាំងមូលជំនួសអ្នកបានដែរ គឺធាតុ និងអ្នកផ្ដល់តូខិនរួមគ្នា ជាមួយ script nonce នៃទំព័ររបស់អ្នក ប្រសិនបើគោលការណ៍សុវត្ថិភាពមាតិការបស់អ្នកត្រូវការវា។ គំរូចុងក្រោយខាងក្រោមបង្ហាញវា។

ស្ដាប់អ្វីដែលស៊ុមនិយាយ

ស៊ុមនិយាយទៅកាន់ធាតុតាមរយៈពិធីការសារដែលមានកំណែ ហើយធាតុប្ដូរអ្វីដែលទំព័ររបស់អ្នកត្រូវការ ទៅជាព្រឹត្តិការណ៍ DOM៖

  • lingara:practice-completed នៅពេលអ្នករៀនបញ្ចប់ឈុតមួយ ជាមួយ planId, setNumber, correct និង total របស់វា។
  • lingara:error នៅពេលស៊ុមឈប់ ជាមួយ code មួយ និង retryable។ កំហុសដែលអាចព្យាយាមឡើងវិញបាន មានន័យថាការដាក់ថ្មីម្ដងទៀតអាចជោគជ័យ ពេលណាត្រូវព្យាយាមម្ដងទៀតគឺជាការសម្រេចចិត្តរបស់អ្នក។

លទ្ធផលនៃការហាត់ក៏ទៅដល់ម៉ាស៊ីនមេរបស់អ្នកដែរ ដូចដែលបានពិពណ៌នានៅក្នុង លទ្ធផលនៃការហាត់។

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)
})
ភាសានៃឧទាហរណ៍កូដ

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();