Skip to Content
文档账号与多语言

账号与多语言

先阅读 SDK 可用性与错误处理。以下示例使用宿主注入的全局对象,游戏不需要索取账号凭据。

玩家主动操作后登录

在需要账号的操作之前调用 checkSession()。若返回 false,通过玩家主动操作触发 login(),登录界面由宿主管理。cancelled 是正常的用户选择;消息传输、弹窗或账号资料同步失败则会拒绝 Promise。

收到 success 后直接继续当前操作,不需要刷新、轮询或再次检查本次操作的登录状态。下一次独立操作再重新检查。请求进行中应禁用发起按钮。

<button id="player-button">Show player</button> <output id="player-info" aria-live="polite"></output>
async function readPlayerAfterClick() { const sdk = window.combos; if (!sdk) return null; const { methods } = await sdk.init(); if (!methods.includes("getUserInfo")) return null; if (!(await sdk.checkSession())) { const result = await sdk.login(); if (result.status !== "success") return null; } return sdk.getUserInfo(); } const button = document.querySelector<HTMLButtonElement>("#player-button"); const output = document.querySelector<HTMLOutputElement>("#player-info"); button?.addEventListener("click", async () => { if (!output) return; button.disabled = true; try { const player = await readPlayerAfterClick(); output.textContent = player ? player.nickName || "Player" : "Player information is unavailable."; } catch { output.textContent = "Unable to read player information. Please try again."; } finally { button.disabled = false; } });

示例按钮和提示是游戏内的演示文案,可按游戏语言调整。辅助函数在能力缺失或登录取消时返回 null,真正的失败交给点击处理函数捕获。

读取玩家信息

getUserInfo() 不接收参数,在登录状态检查通过或登录成功后调用。未登录时以 session_required 拒绝请求。

字段含义
appId当前游戏的应用标识
openId玩家在该应用内的身份标识
nickName显示昵称,可能为空字符串
avatarUrl头像地址,可能为空字符串
locale玩家已保存的公开产品语言,如 en、zh-CN;未保存时为当前产品语言

为缺失的显示信息提供默认值。应用内身份应保留其应用范围,不要把这份展示数据当作自己的后端凭据或授权证明。结果不包含平台用户 ID、邮箱或云能力会话。

翻译已显示的游戏文案

先展示源文案,再请求翻译。sourceLocale 表示源文案的语言,不是你希望翻译到的目标语言;目标语言由宿主当前产品语言决定。sourceTexts 传入完整的源字符串或模板,翻译结果也以这些原文作为 key。

<button data-source-text="Play"></button> <button data-source-text="Pause"></button>
async function localizeLabels() { const nodes = [...document.querySelectorAll<HTMLElement>("[data-source-text]")]; const sourceTexts = nodes.map(node => node.dataset.sourceText ?? ""); nodes.forEach((node, index) => { node.textContent = sourceTexts[index]; }); const sdk = window.combos; if (!sdk) return; try { const { methods } = await sdk.init(); if (!methods.includes("requestI18n")) return; const result = await sdk.requestI18n({ sourceLocale: "en", sourceTexts }); if (!result.needed) return; nodes.forEach((node, index) => { const source = sourceTexts[index]; node.textContent = result.translations[source] || source; }); } catch { // Keep the source copy on screen. } } void localizeLabels();

结果为 { needed: false } 或 { needed: true, locale, translations }。无需翻译、缺少某个 key、宿主不支持或请求失败时都保留原文。SDK 收到无效结果也会退回 needed: false。以文本方式显示译文,不要作为原始 HTML 插入。动态数值应在稳定模板翻译完成后再填入;修改示例的英文源文案时,也要更新 sourceLocale。

可选云能力接口参考

当前 Web 宿主不声明以下四个方法。 只有 init().methods 明确包含对应方法时才能使用。这份接口契约不代表发布游戏后就自动获得 AI 能力。

type Authorization = { decision: "AUTHORIZATION_DECISION_GRANTED" | "AUTHORIZATION_DECISION_DENIED"; decidedAtMs: number; }; type AuthSetting = Partial<Record<"ai_model", Authorization>>; type CloudAbilitySession = { session: string; expiresAtMs: number };
方法参数与结果
getSetting()无参数,返回 AuthSetting;缺少某项表示尚未询问过
authorize({ scope: "ai_model" })宿主管理授权弹窗,返回 Authorization
openSetting()无参数,打开宿主设置并返回 AuthSetting
getCloudAbilitySession()无参数,返回短期 CloudAbilitySession

AUTHORIZATION_DECISION_DENIED 是正常授权结果,不是传输失败。不要写入 UNSPECIFIED 零值。时间单位为毫秒,不要向这些方法传用户、设备或游戏 ID。返回的会话只保存在内存中,遵守 expiresAtMs,游玩结束即丢弃,不放进持久化存储、日志或 URL。

Last updated on